]> git.proxmox.com Git - mirror_frr.git/blame - lib/command.c
vtysh: fixed compile errors
[mirror_frr.git] / lib / command.c
CommitLineData
274a4a44 1/*
9547b5d0
QY
2 * CLI backend interface.
3 *
4 * --
5 * Copyright (C) 2016 Cumulus Networks, Inc.
6 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
7 * Copyright (C) 2013 by Open Source Routing.
8 * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC")
9 *
10 * This file is part of GNU Zebra.
11 *
12 * GNU Zebra is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2, or (at your option) any
15 * later version.
16 *
17 * GNU Zebra is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with GNU Zebra; see the file COPYING. If not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 */
718e3744 27
28#include <zebra.h>
29
b21b19c5 30
718e3744 31#include "memory.h"
32#include "log.h"
5e4fa164 33#include <lib/version.h>
9ab6812d 34#include "thread.h"
b21b19c5 35#include "vector.h"
d0bfb22c 36#include "linklist.h"
b21b19c5 37#include "vty.h"
38#include "command.h"
354d119a 39#include "workqueue.h"
19dc275e 40#include "vrf.h"
d0bfb22c
QY
41#include "command_match.h"
42#include "command_parse.h"
43
4a1ab8e4
DL
44DEFINE_MTYPE( LIB, HOST, "Host config")
45DEFINE_MTYPE( LIB, STRVEC, "String vector")
46DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc")
47
718e3744 48/* Command vector which includes some level of command lists. Normally
49 each daemon maintains each own cmdvec. */
eb820afe 50vector cmdvec = NULL;
718e3744 51
52/* Host information structure. */
53struct host host;
54
718e3744 55/* Standard command node structures. */
7fc626de 56static struct cmd_node auth_node =
718e3744 57{
58 AUTH_NODE,
59 "Password: ",
60};
61
7fc626de 62static struct cmd_node view_node =
718e3744 63{
64 VIEW_NODE,
65 "%s> ",
66};
67
7fc626de 68static struct cmd_node restricted_node =
62687ff1
PJ
69{
70 RESTRICTED_NODE,
71 "%s$ ",
72};
73
7fc626de 74static struct cmd_node auth_enable_node =
718e3744 75{
76 AUTH_ENABLE_NODE,
77 "Password: ",
78};
79
7fc626de 80static struct cmd_node enable_node =
718e3744 81{
82 ENABLE_NODE,
83 "%s# ",
84};
85
7fc626de 86static struct cmd_node config_node =
718e3744 87{
88 CONFIG_NODE,
89 "%s(config)# ",
90 1
91};
6590f2c3 92
93/* Default motd string. */
2d362d10 94static const char *default_motd =
6590f2c3 95"\r\n\
96Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
97" QUAGGA_COPYRIGHT "\r\n\
0be793e6 98" GIT_INFO "\r\n";
6590f2c3 99
274a4a44 100
2d362d10 101static const struct facility_map {
274a4a44 102 int facility;
103 const char *name;
104 size_t match;
d0bfb22c 105} syslog_facilities[] =
274a4a44 106 {
107 { LOG_KERN, "kern", 1 },
108 { LOG_USER, "user", 2 },
109 { LOG_MAIL, "mail", 1 },
110 { LOG_DAEMON, "daemon", 1 },
111 { LOG_AUTH, "auth", 1 },
112 { LOG_SYSLOG, "syslog", 1 },
113 { LOG_LPR, "lpr", 2 },
114 { LOG_NEWS, "news", 1 },
115 { LOG_UUCP, "uucp", 2 },
116 { LOG_CRON, "cron", 1 },
117#ifdef LOG_FTP
118 { LOG_FTP, "ftp", 1 },
119#endif
120 { LOG_LOCAL0, "local0", 6 },
121 { LOG_LOCAL1, "local1", 6 },
122 { LOG_LOCAL2, "local2", 6 },
123 { LOG_LOCAL3, "local3", 6 },
124 { LOG_LOCAL4, "local4", 6 },
125 { LOG_LOCAL5, "local5", 6 },
126 { LOG_LOCAL6, "local6", 6 },
127 { LOG_LOCAL7, "local7", 6 },
128 { 0, NULL, 0 },
129 };
130
131static const char *
132facility_name(int facility)
133{
2d362d10 134 const struct facility_map *fm;
274a4a44 135
136 for (fm = syslog_facilities; fm->name; fm++)
137 if (fm->facility == facility)
138 return fm->name;
139 return "";
140}
141
142static int
143facility_match(const char *str)
144{
2d362d10 145 const struct facility_map *fm;
274a4a44 146
147 for (fm = syslog_facilities; fm->name; fm++)
148 if (!strncmp(str,fm->name,fm->match))
149 return fm->facility;
150 return -1;
151}
152
153static int
154level_match(const char *s)
155{
156 int level ;
d0bfb22c 157
274a4a44 158 for ( level = 0 ; zlog_priority [level] != NULL ; level ++ )
159 if (!strncmp (s, zlog_priority[level], 2))
160 return level;
161 return ZLOG_DISABLED;
162}
163
cb585b65 164/* This is called from main when a daemon is invoked with -v or --version. */
6590f2c3 165void
166print_version (const char *progname)
167{
cb585b65 168 printf ("%s version %s\n", progname, QUAGGA_VERSION);
169 printf ("%s\n", QUAGGA_COPYRIGHT);
80db5ac1 170 printf ("configured with:\n\t%s\n", QUAGGA_CONFIG_ARGS);
6590f2c3 171}
172
6b0655a2 173
718e3744 174/* Utility function to concatenate argv argument into a single string
175 with inserting ' ' character between each argument. */
176char *
d0bfb22c 177argv_concat (struct cmd_token **argv, int argc, int shift)
718e3744 178{
179 int i;
f6834d4c 180 size_t len;
718e3744 181 char *str;
f6834d4c 182 char *p;
718e3744 183
f6834d4c 184 len = 0;
185 for (i = shift; i < argc; i++)
d0bfb22c 186 len += strlen(argv[i]->arg)+1;
f6834d4c 187 if (!len)
188 return NULL;
189 p = str = XMALLOC(MTYPE_TMP, len);
718e3744 190 for (i = shift; i < argc; i++)
191 {
f6834d4c 192 size_t arglen;
d0bfb22c 193 memcpy(p, argv[i]->arg, (arglen = strlen(argv[i]->arg)));
f6834d4c 194 p += arglen;
195 *p++ = ' ';
718e3744 196 }
f6834d4c 197 *(p-1) = '\0';
718e3744 198 return str;
199}
200
201/* Install top node of command vector. */
202void
d0bfb22c
QY
203install_node (struct cmd_node *node,
204 int (*func) (struct vty *))
718e3744 205{
206 vector_set_index (cmdvec, node->node, node);
207 node->func = func;
d0bfb22c 208 node->cmdgraph = graph_new ();
718e3744 209}
210
718e3744 211/* Breaking up string into each command piece. I assume given
212 character is separated by a space character. Return value is a
213 vector which includes char ** data element. */
214vector
ea8e9d97 215cmd_make_strvec (const char *string)
718e3744 216{
ea8e9d97 217 const char *cp, *start;
218 char *token;
718e3744 219 int strlen;
220 vector strvec;
d0bfb22c 221
718e3744 222 if (string == NULL)
223 return NULL;
d0bfb22c 224
718e3744 225 cp = string;
226
227 /* Skip white spaces. */
228 while (isspace ((int) *cp) && *cp != '\0')
229 cp++;
230
231 /* Return if there is only white spaces */
232 if (*cp == '\0')
233 return NULL;
234
235 if (*cp == '!' || *cp == '#')
236 return NULL;
237
238 /* Prepare return vector. */
239 strvec = vector_init (VECTOR_MIN_SIZE);
240
241 /* Copy each command piece and set into vector. */
d0bfb22c 242 while (1)
718e3744 243 {
244 start = cp;
245 while (!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') &&
d0bfb22c
QY
246 *cp != '\0')
247 cp++;
718e3744 248 strlen = cp - start;
249 token = XMALLOC (MTYPE_STRVEC, strlen + 1);
250 memcpy (token, start, strlen);
251 *(token + strlen) = '\0';
252 vector_set (strvec, token);
253
254 while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r') &&
d0bfb22c
QY
255 *cp != '\0')
256 cp++;
718e3744 257
258 if (*cp == '\0')
d0bfb22c 259 return strvec;
718e3744 260 }
261}
262
263/* Free allocated string vector. */
264void
265cmd_free_strvec (vector v)
266{
8c328f11 267 unsigned int i;
718e3744 268 char *cp;
269
270 if (!v)
271 return;
272
55468c86 273 for (i = 0; i < vector_active (v); i++)
718e3744 274 if ((cp = vector_slot (v, i)) != NULL)
275 XFREE (MTYPE_STRVEC, cp);
276
277 vector_free (v);
278}
279
718e3744 280
281/* Return prompt character of specified node. */
8c328f11 282const char *
718e3744 283cmd_prompt (enum node_type node)
284{
285 struct cmd_node *cnode;
286
287 cnode = vector_slot (cmdvec, node);
288 return cnode->prompt;
289}
290
291/* Install a command into a node. */
292void
293install_element (enum node_type ntype, struct cmd_element *cmd)
294{
295 struct cmd_node *cnode;
d0bfb22c 296
eb820afe 297 /* cmd_init hasn't been called */
298 if (!cmdvec)
299 return;
d0bfb22c 300
718e3744 301 cnode = vector_slot (cmdvec, ntype);
302
d0bfb22c 303 if (cnode == NULL)
718e3744 304 {
305 fprintf (stderr, "Command node %d doesn't exist, please check it\n",
d0bfb22c
QY
306 ntype);
307 exit (EXIT_FAILURE);
718e3744 308 }
309
d0bfb22c
QY
310 // add node to command graph and command vector
311 command_parse_format (cnode->cmdgraph, cmd);
718e3744 312 vector_set (cnode->cmd_vector, cmd);
718e3744 313}
314
2d362d10 315static const unsigned char itoa64[] =
718e3744 316"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
317
274a4a44 318static void
718e3744 319to64(char *s, long v, int n)
320{
d0bfb22c 321 while (--n >= 0)
718e3744 322 {
323 *s++ = itoa64[v&0x3f];
324 v >>= 6;
325 }
326}
327
274a4a44 328static char *
329zencrypt (const char *passwd)
718e3744 330{
331 char salt[6];
332 struct timeval tv;
333 char *crypt (const char *, const char *);
334
335 gettimeofday(&tv,0);
d0bfb22c 336
718e3744 337 to64(&salt[0], random(), 3);
338 to64(&salt[3], tv.tv_usec, 3);
339 salt[5] = '\0';
340
341 return crypt (passwd, salt);
342}
343
344/* This function write configuration of this host. */
274a4a44 345static int
718e3744 346config_write_host (struct vty *vty)
347{
348 if (host.name)
349 vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE);
350
351 if (host.encrypt)
352 {
353 if (host.password_encrypt)
d0bfb22c 354 vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE);
718e3744 355 if (host.enable_encrypt)
d0bfb22c 356 vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE);
718e3744 357 }
358 else
359 {
360 if (host.password)
361 vty_out (vty, "password %s%s", host.password, VTY_NEWLINE);
362 if (host.enable)
363 vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE);
364 }
365
274a4a44 366 if (zlog_default->default_lvl != LOG_DEBUG)
82146b88 367 {
368 vty_out (vty, "! N.B. The 'log trap' command is deprecated.%s",
d0bfb22c 369 VTY_NEWLINE);
82146b88 370 vty_out (vty, "log trap %s%s",
d0bfb22c 371 zlog_priority[zlog_default->default_lvl], VTY_NEWLINE);
82146b88 372 }
274a4a44 373
374 if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED))
375 {
376 vty_out (vty, "log file %s", host.logfile);
377 if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl)
d0bfb22c
QY
378 vty_out (vty, " %s",
379 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]);
274a4a44 380 vty_out (vty, "%s", VTY_NEWLINE);
381 }
382
383 if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED)
384 {
385 vty_out (vty, "log stdout");
386 if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl)
d0bfb22c
QY
387 vty_out (vty, " %s",
388 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]);
274a4a44 389 vty_out (vty, "%s", VTY_NEWLINE);
390 }
718e3744 391
274a4a44 392 if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
393 vty_out(vty,"no log monitor%s",VTY_NEWLINE);
394 else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl)
395 vty_out(vty,"log monitor %s%s",
d0bfb22c 396 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE);
718e3744 397
274a4a44 398 if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
12ab19f1 399 {
400 vty_out (vty, "log syslog");
274a4a44 401 if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl)
d0bfb22c
QY
402 vty_out (vty, " %s",
403 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]);
12ab19f1 404 vty_out (vty, "%s", VTY_NEWLINE);
405 }
274a4a44 406
407 if (zlog_default->facility != LOG_DAEMON)
408 vty_out (vty, "log facility %s%s",
d0bfb22c 409 facility_name(zlog_default->facility), VTY_NEWLINE);
718e3744 410
411 if (zlog_default->record_priority == 1)
412 vty_out (vty, "log record-priority%s", VTY_NEWLINE);
413
1ed72e0b
AS
414 if (zlog_default->timestamp_precision > 0)
415 vty_out (vty, "log timestamp precision %d%s",
d0bfb22c 416 zlog_default->timestamp_precision, VTY_NEWLINE);
1ed72e0b 417
718e3744 418 if (host.advanced)
419 vty_out (vty, "service advanced-vty%s", VTY_NEWLINE);
420
421 if (host.encrypt)
422 vty_out (vty, "service password-encryption%s", VTY_NEWLINE);
423
424 if (host.lines >= 0)
425 vty_out (vty, "service terminal-length %d%s", host.lines,
d0bfb22c 426 VTY_NEWLINE);
718e3744 427
3b0c5d9a 428 if (host.motdfile)
429 vty_out (vty, "banner motd file %s%s", host.motdfile, VTY_NEWLINE);
430 else if (! host.motd)
718e3744 431 vty_out (vty, "no banner motd%s", VTY_NEWLINE);
432
433 return 1;
434}
435
436/* Utility function for getting command vector. */
274a4a44 437static vector
718e3744 438cmd_node_vector (vector v, enum node_type ntype)
439{
440 struct cmd_node *cnode = vector_slot (v, ntype);
441 return cnode->cmd_vector;
442}
443
d0bfb22c
QY
444/* Utility function for getting command graph. */
445static struct graph *
446cmd_node_graph (vector v, enum node_type ntype)
718e3744 447{
d0bfb22c
QY
448 struct cmd_node *cnode = vector_slot (v, ntype);
449 return cnode->cmdgraph;
718e3744 450}
451
d0bfb22c
QY
452static int
453cmd_try_do_shortcut (enum node_type node, char* first_word) {
454 if ( first_word != NULL &&
455 node != AUTH_NODE &&
456 node != VIEW_NODE &&
457 node != AUTH_ENABLE_NODE &&
458 node != ENABLE_NODE &&
459 node != RESTRICTED_NODE &&
460 0 == strcmp( "do", first_word ) )
461 return 1;
462 return 0;
718e3744 463}
464
d0bfb22c
QY
465/**
466 * Compare function for cmd_token.
467 * Used with qsort to sort command completions.
468 */
274a4a44 469static int
d0bfb22c 470compare_completions (const void *fst, const void *snd)
718e3744 471{
d0bfb22c
QY
472 struct cmd_token *first = *(struct cmd_token **) fst,
473 *secnd = *(struct cmd_token **) snd;
474 return strcmp (first->text, secnd->text);
718e3744 475}
476
d0bfb22c
QY
477/**
478 * Takes a list of completions returned by command_complete,
479 * dedeuplicates them based on both text and description,
480 * and returns them as a vector.
481 */
482static vector
483completions_to_vec (struct list *completions)
718e3744 484{
d0bfb22c 485 vector comps = vector_init (VECTOR_MIN_SIZE);
718e3744 486
d0bfb22c
QY
487 struct listnode *ln;
488 struct cmd_token *token;
489 unsigned int i, exists;
490 for (ALL_LIST_ELEMENTS_RO(completions,ln,token))
491 {
492 // linear search for token in completions vector
493 exists = 0;
494 for (i = 0; i < vector_active (comps) && !exists; i++)
cd40b329 495 {
d0bfb22c
QY
496 struct cmd_token *curr = vector_slot (comps, i);
497 exists = !strcmp (curr->text, token->text) &&
498 !strcmp (curr->desc, token->desc);
cd40b329 499 }
909a2155 500
d0bfb22c
QY
501 if (!exists)
502 vector_set (comps, copy_cmd_token (token));
503 }
cd40b329 504
d0bfb22c
QY
505 // sort completions
506 qsort (comps->index,
507 vector_active (comps),
508 sizeof (void *),
509 &compare_completions);
cd40b329 510
d0bfb22c 511 return comps;
cd40b329 512}
d0bfb22c
QY
513/**
514 * Generates a vector of cmd_token representing possible completions
515 * on the current input.
516 *
517 * @param vline the vectorized input line
518 * @param vty the vty with the node to match on
519 * @param status pointer to matcher status code
520 */
521static vector
522cmd_complete_command_real (vector vline, struct vty *vty, int *status)
cd40b329 523{
d0bfb22c
QY
524 struct list *completions;
525 struct graph *cmdgraph = cmd_node_graph (cmdvec, vty->node);
cd40b329 526
d0bfb22c 527 enum matcher_rv rv = command_complete (cmdgraph, vline, &completions);
cd40b329 528
d0bfb22c
QY
529 if (MATCHER_ERROR(rv))
530 {
531 switch (rv)
718e3744 532 {
d0bfb22c
QY
533 case MATCHER_AMBIGUOUS:
534 *status = CMD_ERR_AMBIGUOUS;
c117e027 535 default:
d0bfb22c 536 *status = CMD_ERR_NO_MATCH;
718e3744 537 }
d0bfb22c 538 return NULL;
b92938a7 539 }
540
d0bfb22c
QY
541 vector comps = completions_to_vec (completions);
542 list_delete (completions);
b92938a7 543
d0bfb22c
QY
544 // set status code appropriately
545 switch (vector_active (comps))
546 {
547 case 0:
548 *status = CMD_ERR_NO_MATCH;
549 break;
550 case 1:
551 *status = CMD_COMPLETE_FULL_MATCH;
552 break;
553 default:
554 *status = CMD_COMPLETE_LIST_MATCH;
555 }
718e3744 556
d0bfb22c
QY
557 return comps;
558}
718e3744 559
d0bfb22c
QY
560vector
561cmd_describe_command (vector vline, struct vty *vty, int *status)
562{
563 vector ret;
718e3744 564
d0bfb22c 565 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
718e3744 566 {
d0bfb22c
QY
567 enum node_type onode;
568 vector shifted_vline;
569 unsigned int index;
718e3744 570
d0bfb22c
QY
571 onode = vty->node;
572 vty->node = ENABLE_NODE;
573 /* We can try it on enable node, cos' the vty is authenticated */
718e3744 574
d0bfb22c
QY
575 shifted_vline = vector_init (vector_count(vline));
576 /* use memcpy? */
577 for (index = 1; index < vector_active (vline); index++)
578 {
579 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
580 }
718e3744 581
d0bfb22c
QY
582 ret = cmd_complete_command_real (shifted_vline, vty, status);
583
584 vector_free(shifted_vline);
585 vty->node = onode;
586 return ret;
587 }
718e3744 588
d0bfb22c 589 return cmd_complete_command_real (vline, vty, status);
718e3744 590}
591
b92938a7 592char **
cde9f101 593cmd_complete_command_lib (vector vline, struct vty *vty, int *status, int islib)
b92938a7 594{
595 char **ret;
596
597 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
598 {
599 enum node_type onode;
600 vector shifted_vline;
8c328f11 601 unsigned int index;
b92938a7 602
603 onode = vty->node;
604 vty->node = ENABLE_NODE;
605 /* We can try it on enable node, cos' the vty is authenticated */
606
607 shifted_vline = vector_init (vector_count(vline));
608 /* use memcpy? */
d0bfb22c
QY
609 for (index = 1; index < vector_active (vline); index++)
610 {
611 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
612 }
b92938a7 613
d0bfb22c
QY
614 // get token completions
615 vector comps = cmd_complete_command_real (shifted_vline, vty, status);
616 ret = XMALLOC (MTYPE_TMP, vector_active (comps) * sizeof (char *));
617 for (unsigned int i = 0; i < vector_active (comps); i++)
618 {
619 struct cmd_token *token = vector_slot (comps, i);
620 ret[i] = XSTRDUP (MTYPE_TMP, token->text);
621 vector_unset (comps, i);
622 del_cmd_token (token);
623 }
624 vector_free (comps);
b92938a7 625
626 vector_free(shifted_vline);
627 vty->node = onode;
628 return ret;
629 }
630
d0bfb22c
QY
631 // get token completions
632 vector comps = cmd_complete_command_real (vline, vty, status);
633 ret = XMALLOC (MTYPE_TMP, vector_active (comps) * sizeof (char *));
634 for (unsigned int i = 0; i < vector_active (comps); i++)
635 {
636 struct cmd_token *token = vector_slot (comps, i);
637 ret[i] = XSTRDUP (MTYPE_TMP, token->text);
638 vector_unset (comps, i);
639 del_cmd_token (token);
640 }
641 vector_free (comps);
642
643 return ret;
cde9f101 644}
b92938a7 645
cde9f101
LB
646char **
647cmd_complete_command (vector vline, struct vty *vty, int *status)
648{
649 return cmd_complete_command_lib (vline, vty, status, 0);
b92938a7 650}
651
652/* return parent node */
653/* MUST eventually converge on CONFIG_NODE */
13bfca7a 654enum node_type
274a4a44 655node_parent ( enum node_type node )
b92938a7 656{
657 enum node_type ret;
658
9ab6812d 659 assert (node > CONFIG_NODE);
660
661 switch (node)
662 {
663 case BGP_VPNV4_NODE:
8ecd3266 664 case BGP_VPNV6_NODE:
8b1fb8be
LB
665 case BGP_ENCAP_NODE:
666 case BGP_ENCAPV6_NODE:
9ab6812d 667 case BGP_IPV4_NODE:
668 case BGP_IPV4M_NODE:
669 case BGP_IPV6_NODE:
1e836590 670 case BGP_IPV6M_NODE:
9ab6812d 671 ret = BGP_NODE;
672 break;
673 case KEYCHAIN_KEY_NODE:
674 ret = KEYCHAIN_NODE;
675 break;
16f1b9ee
OD
676 case LINK_PARAMS_NODE:
677 ret = INTERFACE_NODE;
678 break;
9ab6812d 679 default:
680 ret = CONFIG_NODE;
16f1b9ee 681 break;
b92938a7 682 }
683
684 return ret;
685}
686
718e3744 687/* Execute command by argument vline vector. */
274a4a44 688static int
cd40b329 689cmd_execute_command_real (vector vline,
d0bfb22c
QY
690 enum filter_type filter,
691 struct vty *vty,
692 struct cmd_element **cmd)
693{
694 struct list *argv_list;
695 enum matcher_rv status;
696 struct graph *cmdgraph = cmd_node_graph (cmdvec, vty->node);
697 status = command_match (cmdgraph, vline, &argv_list, cmd);
698
699 // if matcher error, return corresponding CMD_ERR
700 if (MATCHER_ERROR(status))
701 switch (status)
702 {
703 case MATCHER_INCOMPLETE:
704 return CMD_ERR_INCOMPLETE;
705 case MATCHER_AMBIGUOUS:
706 return CMD_ERR_AMBIGUOUS;
707 default:
708 return CMD_ERR_NO_MATCH;
718e3744 709 }
710
d0bfb22c
QY
711 // build argv array from argv list
712 struct cmd_token **argv = XMALLOC (MTYPE_TMP, argv_list->count * sizeof (struct cmd_token *));
713 struct listnode *ln;
714 struct cmd_token *token;
715 unsigned int i = 0;
716 for (ALL_LIST_ELEMENTS_RO(argv_list,ln,token))
717 argv[i++] = token;
718e3744 718
d0bfb22c 719 int argc = argv_list->count;
718e3744 720
d0bfb22c
QY
721 int ret;
722 if ((*cmd)->daemon)
723 ret = CMD_SUCCESS_DAEMON;
724 else
725 ret = (*cmd)->func (*cmd, vty, argc, argv);
718e3744 726
d0bfb22c
QY
727 // delete list and cmd_token's in it
728 list_delete (argv_list);
718e3744 729
d0bfb22c 730 return ret;
718e3744 731}
732
cd40b329
CF
733/**
734 * Execute a given command, handling things like "do ..." and checking
735 * whether the given command might apply at a parent node if doesn't
736 * apply for the current node.
737 *
738 * @param vline Command line input, vector of char* where each element is
739 * one input token.
740 * @param vty The vty context in which the command should be executed.
741 * @param cmd Pointer where the struct cmd_element of the matched command
742 * will be stored, if any. May be set to NULL if this info is
743 * not needed.
744 * @param vtysh If set != 0, don't lookup the command at parent nodes.
745 * @return The status of the command that has been executed or an error code
746 * as to why no command could be executed.
747 */
eda031f6 748int
87d683b0 749cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd,
d0bfb22c 750 int vtysh) {
04e64062 751 int ret, saved_ret = 0;
9ab6812d 752 enum node_type onode, try_node;
eda031f6 753
9ab6812d 754 onode = try_node = vty->node;
b92938a7 755
756 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
757 {
758 vector shifted_vline;
8c328f11 759 unsigned int index;
b92938a7 760
761 vty->node = ENABLE_NODE;
762 /* We can try it on enable node, cos' the vty is authenticated */
763
764 shifted_vline = vector_init (vector_count(vline));
765 /* use memcpy? */
d0bfb22c 766 for (index = 1; index < vector_active (vline); index++)
04e64062 767 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
b92938a7 768
cd40b329 769 ret = cmd_execute_command_real (shifted_vline, FILTER_RELAXED, vty, cmd);
b92938a7 770
771 vector_free(shifted_vline);
772 vty->node = onode;
773 return ret;
774 }
775
776
cd40b329 777 saved_ret = ret = cmd_execute_command_real (vline, FILTER_RELAXED, vty, cmd);
b92938a7 778
87d683b0 779 if (vtysh)
780 return saved_ret;
781
04e64062 782 if (ret != CMD_SUCCESS && ret != CMD_WARNING)
b92938a7 783 {
04e64062
QY
784 /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
785 while (vty->node > CONFIG_NODE)
786 {
787 try_node = node_parent(try_node);
788 vty->node = try_node;
789 ret = cmd_execute_command_real (vline, FILTER_RELAXED, vty, cmd);
790 if (ret == CMD_SUCCESS || ret == CMD_WARNING)
791 return ret;
792 }
793 /* no command succeeded, reset the vty to the original node */
794 vty->node = onode;
b92938a7 795 }
04e64062
QY
796
797 /* return command status for original node */
9ab6812d 798 return saved_ret;
b92938a7 799}
800
cd40b329
CF
801/**
802 * Execute a given command, matching it strictly against the current node.
803 * This mode is used when reading config files.
804 *
805 * @param vline Command line input, vector of char* where each element is
806 * one input token.
807 * @param vty The vty context in which the command should be executed.
808 * @param cmd Pointer where the struct cmd_element* of the matched command
809 * will be stored, if any. May be set to NULL if this info is
810 * not needed.
811 * @return The status of the command that has been executed or an error code
812 * as to why no command could be executed.
813 */
718e3744 814int
909a2155 815cmd_execute_command_strict (vector vline, struct vty *vty,
d0bfb22c 816 struct cmd_element **cmd)
718e3744 817{
cd40b329 818 return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd);
718e3744 819}
820
bed578b8
DS
821/**
822 * Parse one line of config, walking up the parse tree attempting to find a match
823 *
824 * @param vty The vty context in which the command should be executed.
825 * @param cmd Pointer where the struct cmd_element* of the match command
826 * will be stored, if any. May be set to NULL if this info is
827 * not needed.
828 * @param use_daemon Boolean to control whether or not we match on CMD_SUCCESS_DAEMON
829 * or not.
830 * @return The status of the command that has been executed or an error code
831 * as to why no command could be executed.
832 */
833int
834command_config_read_one_line (struct vty *vty, struct cmd_element **cmd, int use_daemon)
835{
836 vector vline;
837 int saved_node;
838 int ret;
839
840 vline = cmd_make_strvec (vty->buf);
841
842 /* In case of comment line */
843 if (vline == NULL)
844 return CMD_SUCCESS;
845
846 /* Execute configuration command : this is strict match */
847 ret = cmd_execute_command_strict (vline, vty, cmd);
848
849 // Climb the tree and try the command again at each node
850 if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
fd715b78
DW
851 !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) &&
852 ret != CMD_SUCCESS &&
853 ret != CMD_WARNING &&
854 vty->node != CONFIG_NODE) {
bed578b8
DS
855
856 saved_node = vty->node;
857
858 while (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
fd715b78 859 !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) &&
d0bfb22c 860 ret != CMD_SUCCESS &&
fd715b78 861 ret != CMD_WARNING &&
73d2dad0 862 vty->node > CONFIG_NODE) {
bed578b8 863 vty->node = node_parent(vty->node);
fd715b78 864 ret = cmd_execute_command_strict (vline, vty, cmd);
bed578b8
DS
865 }
866
867 // If climbing the tree did not work then ignore the command and
868 // stay at the same node
869 if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) &&
fd715b78 870 !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) &&
d0bfb22c 871 ret != CMD_SUCCESS &&
fd715b78 872 ret != CMD_WARNING)
bed578b8 873 {
d0bfb22c
QY
874 vty->node = saved_node;
875 memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ);
bed578b8
DS
876 }
877 }
878
879 cmd_free_strvec (vline);
880
881 return ret;
882}
883
5689fe5f 884/* Configuration make from file. */
718e3744 885int
13fbc82d 886config_from_file (struct vty *vty, FILE *fp, unsigned int *line_num)
718e3744 887{
5689fe5f 888 int ret, error_ret=0;
13fbc82d 889 *line_num = 0;
718e3744 890
891 while (fgets (vty->buf, VTY_BUFSIZ, fp))
892 {
13fbc82d 893 if (!error_ret)
d0bfb22c 894 ++(*line_num);
13fbc82d 895
bed578b8 896 ret = command_config_read_one_line (vty, NULL, 0);
718e3744 897
5689fe5f 898 if (ret != CMD_SUCCESS && ret != CMD_WARNING &&
d0bfb22c
QY
899 ret != CMD_ERR_NOTHING_TODO)
900 error_ret = ret;
718e3744 901 }
5689fe5f
DW
902
903 if (error_ret) {
904 return error_ret;
905 }
906
718e3744 907 return CMD_SUCCESS;
908}
909
5689fe5f 910/* Configuration from terminal */
718e3744 911DEFUN (config_terminal,
912 config_terminal_cmd,
913 "configure terminal",
914 "Configuration from vty interface\n"
915 "Configuration terminal\n")
916{
917 if (vty_config_lock (vty))
918 vty->node = CONFIG_NODE;
919 else
920 {
921 vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
922 return CMD_WARNING;
923 }
924 return CMD_SUCCESS;
925}
926
927/* Enable command */
d0bfb22c 928DEFUN (enable,
718e3744 929 config_enable_cmd,
930 "enable",
931 "Turn on privileged mode command\n")
932{
933 /* If enable password is NULL, change to ENABLE_NODE */
934 if ((host.enable == NULL && host.enable_encrypt == NULL) ||
935 vty->type == VTY_SHELL_SERV)
936 vty->node = ENABLE_NODE;
937 else
938 vty->node = AUTH_ENABLE_NODE;
939
940 return CMD_SUCCESS;
941}
942
943/* Disable command */
d0bfb22c 944DEFUN (disable,
718e3744 945 config_disable_cmd,
946 "disable",
947 "Turn off privileged mode command\n")
948{
949 if (vty->node == ENABLE_NODE)
950 vty->node = VIEW_NODE;
951 return CMD_SUCCESS;
952}
953
954/* Down vty node level. */
955DEFUN (config_exit,
956 config_exit_cmd,
957 "exit",
958 "Exit current mode and down to previous mode\n")
959{
960 switch (vty->node)
961 {
962 case VIEW_NODE:
963 case ENABLE_NODE:
62687ff1 964 case RESTRICTED_NODE:
718e3744 965 if (vty_shell (vty))
d0bfb22c 966 exit (0);
718e3744 967 else
d0bfb22c 968 vty->status = VTY_CLOSE;
718e3744 969 break;
970 case CONFIG_NODE:
971 vty->node = ENABLE_NODE;
972 vty_config_unlock (vty);
973 break;
974 case INTERFACE_NODE:
13460c44 975 case NS_NODE:
f93e3f69 976 case VRF_NODE:
718e3744 977 case ZEBRA_NODE:
978 case BGP_NODE:
979 case RIP_NODE:
980 case RIPNG_NODE:
981 case OSPF_NODE:
982 case OSPF6_NODE:
9e867fe6 983 case ISIS_NODE:
718e3744 984 case KEYCHAIN_NODE:
985 case MASC_NODE:
986 case RMAP_NODE:
12e41d03 987 case PIM_NODE:
718e3744 988 case VTY_NODE:
989 vty->node = CONFIG_NODE;
990 break;
718e3744 991 case BGP_IPV4_NODE:
992 case BGP_IPV4M_NODE:
8ecd3266 993 case BGP_VPNV4_NODE:
994 case BGP_VPNV6_NODE:
8b1fb8be
LB
995 case BGP_ENCAP_NODE:
996 case BGP_ENCAPV6_NODE:
718e3744 997 case BGP_IPV6_NODE:
1e836590 998 case BGP_IPV6M_NODE:
718e3744 999 vty->node = BGP_NODE;
1000 break;
1001 case KEYCHAIN_KEY_NODE:
1002 vty->node = KEYCHAIN_NODE;
1003 break;
16f1b9ee
OD
1004 case LINK_PARAMS_NODE:
1005 vty->node = INTERFACE_NODE;
1006 break;
718e3744 1007 default:
1008 break;
1009 }
1010 return CMD_SUCCESS;
1011}
1012
f667a580
QY
1013/* ALIAS_FIXME */
1014DEFUN (config_quit,
1015 config_quit_cmd,
1016 "quit",
1017 "Exit current mode and down to previous mode\n")
1018{
1019 return config_exit (self, vty, argc, argv);
1020}
1021
d0bfb22c 1022
718e3744 1023/* End of configuration. */
1024DEFUN (config_end,
1025 config_end_cmd,
1026 "end",
1027 "End current mode and change to enable mode.")
1028{
1029 switch (vty->node)
1030 {
1031 case VIEW_NODE:
1032 case ENABLE_NODE:
62687ff1 1033 case RESTRICTED_NODE:
718e3744 1034 /* Nothing to do. */
1035 break;
1036 case CONFIG_NODE:
1037 case INTERFACE_NODE:
13460c44 1038 case NS_NODE:
f93e3f69 1039 case VRF_NODE:
718e3744 1040 case ZEBRA_NODE:
1041 case RIP_NODE:
1042 case RIPNG_NODE:
1043 case BGP_NODE:
8b1fb8be
LB
1044 case BGP_ENCAP_NODE:
1045 case BGP_ENCAPV6_NODE:
718e3744 1046 case BGP_VPNV4_NODE:
8ecd3266 1047 case BGP_VPNV6_NODE:
718e3744 1048 case BGP_IPV4_NODE:
1049 case BGP_IPV4M_NODE:
1050 case BGP_IPV6_NODE:
1e836590 1051 case BGP_IPV6M_NODE:
718e3744 1052 case RMAP_NODE:
1053 case OSPF_NODE:
1054 case OSPF6_NODE:
9e867fe6 1055 case ISIS_NODE:
718e3744 1056 case KEYCHAIN_NODE:
1057 case KEYCHAIN_KEY_NODE:
1058 case MASC_NODE:
12e41d03 1059 case PIM_NODE:
718e3744 1060 case VTY_NODE:
16f1b9ee 1061 case LINK_PARAMS_NODE:
718e3744 1062 vty_config_unlock (vty);
1063 vty->node = ENABLE_NODE;
1064 break;
1065 default:
1066 break;
1067 }
1068 return CMD_SUCCESS;
1069}
1070
1071/* Show version. */
1072DEFUN (show_version,
1073 show_version_cmd,
1074 "show version",
1075 SHOW_STR
1076 "Displays zebra version\n")
1077{
12f6ea23 1078 vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name?host.name:"",
d0bfb22c 1079 VTY_NEWLINE);
0be793e6 1080 vty_out (vty, "%s%s%s", QUAGGA_COPYRIGHT, GIT_INFO, VTY_NEWLINE);
80db5ac1
DL
1081 vty_out (vty, "configured with:%s %s%s", VTY_NEWLINE,
1082 QUAGGA_CONFIG_ARGS, VTY_NEWLINE);
718e3744 1083
1084 return CMD_SUCCESS;
1085}
1086
1087/* Help display function for all node. */
1088DEFUN (config_help,
1089 config_help_cmd,
1090 "help",
1091 "Description of the interactive help system\n")
1092{
d0bfb22c
QY
1093 vty_out (vty,
1094 "Quagga VTY provides advanced help feature. When you need help,%s\
718e3744 1095anytime at the command line please press '?'.%s\
1096%s\
1097If nothing matches, the help list will be empty and you must backup%s\
1098 until entering a '?' shows the available options.%s\
1099Two styles of help are provided:%s\
11001. Full help is available when you are ready to enter a%s\
1101command argument (e.g. 'show ?') and describes each possible%s\
1102argument.%s\
11032. Partial help is provided when an abbreviated argument is entered%s\
1104 and you want to know what arguments match the input%s\
1105 (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
d0bfb22c
QY
1106 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
1107 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
718e3744 1108 return CMD_SUCCESS;
1109}
1110
1111/* Help display function for all node. */
1112DEFUN (config_list,
1113 config_list_cmd,
1114 "list",
1115 "Print command list\n")
1116{
8c328f11 1117 unsigned int i;
718e3744 1118 struct cmd_node *cnode = vector_slot (cmdvec, vty->node);
1119 struct cmd_element *cmd;
1120
55468c86 1121 for (i = 0; i < vector_active (cnode->cmd_vector); i++)
4275b1de 1122 if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL
1123 && !(cmd->attr == CMD_ATTR_DEPRECATED
1124 || cmd->attr == CMD_ATTR_HIDDEN))
718e3744 1125 vty_out (vty, " %s%s", cmd->string,
d0bfb22c 1126 VTY_NEWLINE);
718e3744 1127 return CMD_SUCCESS;
1128}
1129
1130/* Write current configuration into file. */
d862bffb 1131
d0bfb22c
QY
1132DEFUN (config_write,
1133 config_write_cmd,
1134 "write [<file|memory|terminal>]",
718e3744 1135 "Write running configuration to memory, network, or terminal\n"
d0bfb22c
QY
1136 "Write to configuration file\n"
1137 "Write configuration currently in memory\n"
1138 "Write configuration to terminal\n")
718e3744 1139{
c349116d 1140 int idx_type = 1;
8c328f11 1141 unsigned int i;
718e3744 1142 int fd;
1143 struct cmd_node *node;
1144 char *config_file;
1145 char *config_file_tmp = NULL;
1146 char *config_file_sav = NULL;
05865c90 1147 int ret = CMD_WARNING;
718e3744 1148 struct vty *file_vty;
e4421165 1149 struct stat conf_stat;
718e3744 1150
d862bffb
QY
1151 // if command was 'write terminal', 'write memory' or 'show running-config'
1152 if (argc == 2 && (!strcmp(argv[idx_type]->text, "terminal") ||
1153 !strcmp(argv[idx_type]->text, "memory") ||
1154 !strcmp(argv[0]->text, "show")))
d0bfb22c
QY
1155 {
1156 if (vty->type == VTY_SHELL_SERV)
1157 {
1158 for (i = 0; i < vector_active (cmdvec); i++)
1159 if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
1160 {
1161 if ((*node->func) (vty))
1162 vty_out (vty, "!%s", VTY_NEWLINE);
1163 }
1164 }
1165 else
1166 {
1167 vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
1168 VTY_NEWLINE);
1169 vty_out (vty, "!%s", VTY_NEWLINE);
1170
1171 for (i = 0; i < vector_active (cmdvec); i++)
1172 if ((node = vector_slot (cmdvec, i)) && node->func)
1173 {
1174 if ((*node->func) (vty))
1175 vty_out (vty, "!%s", VTY_NEWLINE);
1176 }
1177 vty_out (vty, "end%s",VTY_NEWLINE);
1178 }
1179 return CMD_SUCCESS;
1180 }
1181
718e3744 1182 /* Check and see if we are operating under vtysh configuration */
1183 if (host.config == NULL)
1184 {
1185 vty_out (vty, "Can't save to configuration file, using vtysh.%s",
d0bfb22c 1186 VTY_NEWLINE);
718e3744 1187 return CMD_WARNING;
1188 }
1189
1190 /* Get filename. */
1191 config_file = host.config;
d0bfb22c 1192
05865c90 1193 config_file_sav =
1194 XMALLOC (MTYPE_TMP, strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1);
718e3744 1195 strcpy (config_file_sav, config_file);
1196 strcat (config_file_sav, CONF_BACKUP_EXT);
1197
1198
05865c90 1199 config_file_tmp = XMALLOC (MTYPE_TMP, strlen (config_file) + 8);
718e3744 1200 sprintf (config_file_tmp, "%s.XXXXXX", config_file);
d0bfb22c 1201
718e3744 1202 /* Open file to configuration write. */
1203 fd = mkstemp (config_file_tmp);
1204 if (fd < 0)
1205 {
1206 vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp,
d0bfb22c 1207 VTY_NEWLINE);
05865c90 1208 goto finished;
718e3744 1209 }
d0bfb22c 1210
718e3744 1211 /* Make vty for configuration file. */
1212 file_vty = vty_new ();
c5e69a02 1213 file_vty->wfd = fd;
718e3744 1214 file_vty->type = VTY_FILE;
1215
1216 /* Config file header print. */
1217 vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! ");
1218 vty_time_print (file_vty, 1);
1219 vty_out (file_vty, "!\n");
1220
55468c86 1221 for (i = 0; i < vector_active (cmdvec); i++)
718e3744 1222 if ((node = vector_slot (cmdvec, i)) && node->func)
1223 {
d0bfb22c
QY
1224 if ((*node->func) (file_vty))
1225 vty_out (file_vty, "!\n");
718e3744 1226 }
1227 vty_close (file_vty);
1228
e4421165 1229 if (stat(config_file, &conf_stat) >= 0)
718e3744 1230 {
e4421165 1231 if (unlink (config_file_sav) != 0)
d0bfb22c
QY
1232 if (errno != ENOENT)
1233 {
1234 vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav,
1235 VTY_NEWLINE);
1236 goto finished;
1237 }
e4421165 1238 if (link (config_file, config_file_sav) != 0)
d0bfb22c
QY
1239 {
1240 vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
1241 VTY_NEWLINE);
1242 goto finished;
1243 }
e4421165
DS
1244 sync ();
1245 if (unlink (config_file) != 0)
d0bfb22c
QY
1246 {
1247 vty_out (vty, "Can't unlink configuration file %s.%s", config_file,
1248 VTY_NEWLINE);
1249 goto finished;
1250 }
718e3744 1251 }
1252 if (link (config_file_tmp, config_file) != 0)
1253 {
1254 vty_out (vty, "Can't save configuration file %s.%s", config_file,
d0bfb22c 1255 VTY_NEWLINE);
05865c90 1256 goto finished;
718e3744 1257 }
718e3744 1258 sync ();
d0bfb22c 1259
aa593d5e 1260 if (chmod (config_file, CONFIGFILE_MASK) != 0)
1261 {
d0bfb22c
QY
1262 vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s",
1263 config_file, safe_strerror(errno), errno, VTY_NEWLINE);
05865c90 1264 goto finished;
aa593d5e 1265 }
1266
718e3744 1267 vty_out (vty, "Configuration saved to %s%s", config_file,
d0bfb22c 1268 VTY_NEWLINE);
05865c90 1269 ret = CMD_SUCCESS;
1270
1271finished:
1272 unlink (config_file_tmp);
1273 XFREE (MTYPE_TMP, config_file_tmp);
1274 XFREE (MTYPE_TMP, config_file_sav);
1275 return ret;
718e3744 1276}
1277
d862bffb
QY
1278/* ALIAS_FIXME for 'write <terminal|memory>' */
1279DEFUN (show_running_config,
1280 show_running_config_cmd,
1281 "show running-config",
1282 SHOW_STR
1283 "running configuration (same as write terminal/memory)\n")
1284{
1285 return config_write (self, vty, argc, argv);
1286}
718e3744 1287
d862bffb
QY
1288/* ALIAS_FIXME for 'write file' */
1289DEFUN (copy_runningconf_startupconf,
1290 copy_runningconf_startupconf_cmd,
1291 "copy running-config startup-config",
1292 "Copy configuration\n"
1293 "Copy running config to... \n"
1294 "Copy running config to startup config (same as write file)\n")
1295{
1296 return config_write (self, vty, argc, argv);
1297}
1298/** -- **/
718e3744 1299
1300/* Write startup configuration into the terminal. */
1301DEFUN (show_startup_config,
1302 show_startup_config_cmd,
1303 "show startup-config",
1304 SHOW_STR
d0bfb22c 1305 "Contents of startup configuration\n")
718e3744 1306{
1307 char buf[BUFSIZ];
1308 FILE *confp;
1309
1310 confp = fopen (host.config, "r");
1311 if (confp == NULL)
1312 {
1db63918 1313 vty_out (vty, "Can't open configuration file [%s] due to '%s'%s",
d0bfb22c 1314 host.config, safe_strerror(errno), VTY_NEWLINE);
718e3744 1315 return CMD_WARNING;
1316 }
1317
1318 while (fgets (buf, BUFSIZ, confp))
1319 {
1320 char *cp = buf;
1321
1322 while (*cp != '\r' && *cp != '\n' && *cp != '\0')
d0bfb22c 1323 cp++;
718e3744 1324 *cp = '\0';
1325
1326 vty_out (vty, "%s%s", buf, VTY_NEWLINE);
1327 }
1328
1329 fclose (confp);
1330
1331 return CMD_SUCCESS;
1332}
1333
1334/* Hostname configuration */
d0bfb22c 1335DEFUN (config_hostname,
718e3744 1336 hostname_cmd,
1337 "hostname WORD",
1338 "Set system's network name\n"
1339 "This system's network name\n")
1340{
d0bfb22c
QY
1341 struct cmd_token *word = argv[1];
1342
e4123a9b 1343 if (!isalpha((int) word->arg[0]))
718e3744 1344 {
1345 vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE);
1346 return CMD_WARNING;
1347 }
1348
1349 if (host.name)
05865c90 1350 XFREE (MTYPE_HOST, host.name);
d0bfb22c
QY
1351
1352 host.name = XSTRDUP (MTYPE_HOST, word->arg);
718e3744 1353 return CMD_SUCCESS;
1354}
1355
d0bfb22c 1356DEFUN (config_no_hostname,
718e3744 1357 no_hostname_cmd,
1358 "no hostname [HOSTNAME]",
1359 NO_STR
1360 "Reset system's network name\n"
1361 "Host name of this router\n")
1362{
1363 if (host.name)
05865c90 1364 XFREE (MTYPE_HOST, host.name);
718e3744 1365 host.name = NULL;
1366 return CMD_SUCCESS;
1367}
1368
1369/* VTY interface password set. */
f412b39a
DW
1370DEFUN (config_password,
1371 password_cmd,
d0bfb22c 1372 "password [8] WORD",
718e3744 1373 "Assign the terminal connection password\n"
1374 "Specifies a HIDDEN password will follow\n"
d0bfb22c 1375 "The password string\n")
718e3744 1376{
c349116d
DW
1377 int idx_8 = 1;
1378 int idx_word = 2;
d0bfb22c
QY
1379 if (argc == 3) // '8' was specified
1380 {
1381 if (host.password)
1382 XFREE (MTYPE_HOST, host.password);
1383 host.password = NULL;
1384 if (host.password_encrypt)
1385 XFREE (MTYPE_HOST, host.password_encrypt);
c349116d 1386 host.password_encrypt = XSTRDUP (MTYPE_HOST, argv[idx_word]->arg);
d0bfb22c
QY
1387 return CMD_SUCCESS;
1388 }
718e3744 1389
c349116d 1390 if (!isalnum (argv[idx_8]->arg[0]))
718e3744 1391 {
d0bfb22c
QY
1392 vty_out (vty,
1393 "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
718e3744 1394 return CMD_WARNING;
1395 }
1396
1397 if (host.password)
05865c90 1398 XFREE (MTYPE_HOST, host.password);
718e3744 1399 host.password = NULL;
1400
1401 if (host.encrypt)
1402 {
1403 if (host.password_encrypt)
d0bfb22c 1404 XFREE (MTYPE_HOST, host.password_encrypt);
c349116d 1405 host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[idx_8]->arg));
718e3744 1406 }
1407 else
c349116d 1408 host.password = XSTRDUP (MTYPE_HOST, argv[idx_8]->arg);
718e3744 1409
1410 return CMD_SUCCESS;
1411}
1412
718e3744 1413/* VTY enable password set. */
f412b39a
DW
1414DEFUN (config_enable_password,
1415 enable_password_cmd,
d0bfb22c 1416 "enable password [8] WORD",
718e3744 1417 "Modify enable password parameters\n"
1418 "Assign the privileged level password\n"
1419 "Specifies a HIDDEN password will follow\n"
1420 "dummy string \n"
1421 "The HIDDEN 'enable' password string\n")
1422{
c349116d
DW
1423 int idx_8 = 2;
1424 int idx_word = 3;
58749582 1425
718e3744 1426 /* Crypt type is specified. */
d0bfb22c 1427 if (argc == 4)
718e3744 1428 {
c349116d 1429 if (argv[idx_8]->arg[0] == '8')
d0bfb22c
QY
1430 {
1431 if (host.enable)
1432 XFREE (MTYPE_HOST, host.enable);
1433 host.enable = NULL;
1434
1435 if (host.enable_encrypt)
1436 XFREE (MTYPE_HOST, host.enable_encrypt);
c349116d 1437 host.enable_encrypt = XSTRDUP (MTYPE_HOST, argv[idx_word]->arg);
d0bfb22c
QY
1438
1439 return CMD_SUCCESS;
1440 }
718e3744 1441 else
d0bfb22c
QY
1442 {
1443 vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
1444 return CMD_WARNING;
1445 }
718e3744 1446 }
1447
c349116d 1448 if (!isalnum (argv[idx_8]->arg[0]))
718e3744 1449 {
d0bfb22c
QY
1450 vty_out (vty,
1451 "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
718e3744 1452 return CMD_WARNING;
1453 }
1454
1455 if (host.enable)
05865c90 1456 XFREE (MTYPE_HOST, host.enable);
718e3744 1457 host.enable = NULL;
1458
1459 /* Plain password input. */
1460 if (host.encrypt)
1461 {
1462 if (host.enable_encrypt)
d0bfb22c 1463 XFREE (MTYPE_HOST, host.enable_encrypt);
c349116d 1464 host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[idx_8]->arg));
718e3744 1465 }
1466 else
c349116d 1467 host.enable = XSTRDUP (MTYPE_HOST, argv[idx_8]->arg);
718e3744 1468
1469 return CMD_SUCCESS;
1470}
1471
718e3744 1472/* VTY enable password delete. */
f412b39a
DW
1473DEFUN (no_config_enable_password,
1474 no_enable_password_cmd,
718e3744 1475 "no enable password",
1476 NO_STR
1477 "Modify enable password parameters\n"
1478 "Assign the privileged level password\n")
1479{
1480 if (host.enable)
05865c90 1481 XFREE (MTYPE_HOST, host.enable);
718e3744 1482 host.enable = NULL;
1483
1484 if (host.enable_encrypt)
05865c90 1485 XFREE (MTYPE_HOST, host.enable_encrypt);
718e3744 1486 host.enable_encrypt = NULL;
1487
1488 return CMD_SUCCESS;
1489}
d0bfb22c 1490
718e3744 1491DEFUN (service_password_encrypt,
1492 service_password_encrypt_cmd,
1493 "service password-encryption",
1494 "Set up miscellaneous service\n"
1495 "Enable encrypted passwords\n")
1496{
1497 if (host.encrypt)
1498 return CMD_SUCCESS;
1499
1500 host.encrypt = 1;
1501
1502 if (host.password)
1503 {
1504 if (host.password_encrypt)
d0bfb22c 1505 XFREE (MTYPE_HOST, host.password_encrypt);
05865c90 1506 host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.password));
718e3744 1507 }
1508 if (host.enable)
1509 {
1510 if (host.enable_encrypt)
d0bfb22c 1511 XFREE (MTYPE_HOST, host.enable_encrypt);
05865c90 1512 host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.enable));
718e3744 1513 }
1514
1515 return CMD_SUCCESS;
1516}
1517
1518DEFUN (no_service_password_encrypt,
1519 no_service_password_encrypt_cmd,
1520 "no service password-encryption",
1521 NO_STR
1522 "Set up miscellaneous service\n"
1523 "Enable encrypted passwords\n")
1524{
1525 if (! host.encrypt)
1526 return CMD_SUCCESS;
1527
1528 host.encrypt = 0;
1529
1530 if (host.password_encrypt)
05865c90 1531 XFREE (MTYPE_HOST, host.password_encrypt);
718e3744 1532 host.password_encrypt = NULL;
1533
1534 if (host.enable_encrypt)
05865c90 1535 XFREE (MTYPE_HOST, host.enable_encrypt);
718e3744 1536 host.enable_encrypt = NULL;
1537
1538 return CMD_SUCCESS;
1539}
1540
f412b39a
DW
1541DEFUN (config_terminal_length,
1542 config_terminal_length_cmd,
d0bfb22c 1543 "terminal length (0-512)",
718e3744 1544 "Set terminal line parameters\n"
1545 "Set number of lines on a screen\n"
1546 "Number of lines on screen (0 for no pausing)\n")
1547{
c349116d 1548 int idx_number = 2;
718e3744 1549 int lines;
1550 char *endptr = NULL;
1551
c349116d 1552 lines = strtol (argv[idx_number]->arg, &endptr, 10);
718e3744 1553 if (lines < 0 || lines > 512 || *endptr != '\0')
1554 {
1555 vty_out (vty, "length is malformed%s", VTY_NEWLINE);
1556 return CMD_WARNING;
1557 }
1558 vty->lines = lines;
1559
1560 return CMD_SUCCESS;
1561}
1562
f412b39a
DW
1563DEFUN (config_terminal_no_length,
1564 config_terminal_no_length_cmd,
718e3744 1565 "terminal no length",
1566 "Set terminal line parameters\n"
1567 NO_STR
1568 "Set number of lines on a screen\n")
1569{
1570 vty->lines = -1;
1571 return CMD_SUCCESS;
1572}
1573
f412b39a
DW
1574DEFUN (service_terminal_length,
1575 service_terminal_length_cmd,
d0bfb22c 1576 "service terminal-length (0-512)",
718e3744 1577 "Set up miscellaneous service\n"
1578 "System wide terminal length configuration\n"
1579 "Number of lines of VTY (0 means no line control)\n")
1580{
c349116d 1581 int idx_number = 2;
718e3744 1582 int lines;
1583 char *endptr = NULL;
1584
c349116d 1585 lines = strtol (argv[idx_number]->arg, &endptr, 10);
718e3744 1586 if (lines < 0 || lines > 512 || *endptr != '\0')
1587 {
1588 vty_out (vty, "length is malformed%s", VTY_NEWLINE);
1589 return CMD_WARNING;
1590 }
1591 host.lines = lines;
1592
1593 return CMD_SUCCESS;
1594}
1595
f412b39a
DW
1596DEFUN (no_service_terminal_length,
1597 no_service_terminal_length_cmd,
d0bfb22c 1598 "no service terminal-length [(0-512)]",
718e3744 1599 NO_STR
1600 "Set up miscellaneous service\n"
1601 "System wide terminal length configuration\n"
1602 "Number of lines of VTY (0 means no line control)\n")
1603{
1604 host.lines = -1;
1605 return CMD_SUCCESS;
1606}
1607
2885f72d 1608DEFUN_HIDDEN (do_echo,
d0bfb22c
QY
1609 echo_cmd,
1610 "echo MESSAGE...",
1611 "Echo a message back to the vty\n"
1612 "The message to echo\n")
2885f72d 1613{
1614 char *message;
1615
58749582 1616 vty_out (vty, "%s%s", ((message = argv_concat (argv, argc, 1)) ? message : ""),
d0bfb22c 1617 VTY_NEWLINE);
f6834d4c 1618 if (message)
1619 XFREE(MTYPE_TMP, message);
2885f72d 1620 return CMD_SUCCESS;
1621}
1622
274a4a44 1623DEFUN (config_logmsg,
1624 config_logmsg_cmd,
199d90a1 1625 "logmsg <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging> MESSAGE...",
274a4a44 1626 "Send a message to enabled logging destinations\n"
1627 LOG_LEVEL_DESC
1628 "The message to send\n")
1629{
c349116d 1630 int idx_log_level = 1;
58749582 1631 int idx_message = 2;
274a4a44 1632 int level;
1633 char *message;
1634
c349116d 1635 if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED)
274a4a44 1636 return CMD_ERR_NO_MATCH;
1637
58749582 1638 zlog(NULL, level, "%s", ((message = argv_concat(argv, argc, idx_message)) ? message : ""));
f6834d4c 1639 if (message)
1640 XFREE(MTYPE_TMP, message);
274a4a44 1641 return CMD_SUCCESS;
1642}
1643
1644DEFUN (show_logging,
1645 show_logging_cmd,
1646 "show logging",
1647 SHOW_STR
1648 "Show current logging configuration\n")
1649{
1650 struct zlog *zl = zlog_default;
1651
1652 vty_out (vty, "Syslog logging: ");
1653 if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED)
1654 vty_out (vty, "disabled");
1655 else
1656 vty_out (vty, "level %s, facility %s, ident %s",
d0bfb22c
QY
1657 zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]],
1658 facility_name(zl->facility), zl->ident);
274a4a44 1659 vty_out (vty, "%s", VTY_NEWLINE);
1660
1661 vty_out (vty, "Stdout logging: ");
1662 if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED)
1663 vty_out (vty, "disabled");
1664 else
1665 vty_out (vty, "level %s",
d0bfb22c 1666 zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]);
274a4a44 1667 vty_out (vty, "%s", VTY_NEWLINE);
1668
1669 vty_out (vty, "Monitor logging: ");
1670 if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
1671 vty_out (vty, "disabled");
1672 else
1673 vty_out (vty, "level %s",
d0bfb22c 1674 zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]);
274a4a44 1675 vty_out (vty, "%s", VTY_NEWLINE);
1676
1677 vty_out (vty, "File logging: ");
1678 if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) ||
1679 !zl->fp)
1680 vty_out (vty, "disabled");
1681 else
1682 vty_out (vty, "level %s, filename %s",
d0bfb22c
QY
1683 zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]],
1684 zl->filename);
274a4a44 1685 vty_out (vty, "%s", VTY_NEWLINE);
1686
1687 vty_out (vty, "Protocol name: %s%s",
d0bfb22c 1688 zlog_proto_names[zl->protocol], VTY_NEWLINE);
274a4a44 1689 vty_out (vty, "Record priority: %s%s",
d0bfb22c 1690 (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE);
1ed72e0b 1691 vty_out (vty, "Timestamp precision: %d%s",
d0bfb22c 1692 zl->timestamp_precision, VTY_NEWLINE);
274a4a44 1693
1694 return CMD_SUCCESS;
1695}
1696
718e3744 1697DEFUN (config_log_stdout,
1698 config_log_stdout_cmd,
6de69f83 1699 "log stdout [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
274a4a44 1700 "Logging control\n"
1701 "Set stdout logging level\n"
1702 LOG_LEVEL_DESC)
1703{
c349116d 1704 int idx_log_level = 2;
58749582
DW
1705
1706 if (argc == idx_log_level)
d0bfb22c
QY
1707 {
1708 zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl);
1709 return CMD_SUCCESS;
1710 }
274a4a44 1711 int level;
1712
c349116d 1713 if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED)
274a4a44 1714 return CMD_ERR_NO_MATCH;
1715 zlog_set_level (NULL, ZLOG_DEST_STDOUT, level);
718e3744 1716 return CMD_SUCCESS;
1717}
1718
1719DEFUN (no_config_log_stdout,
1720 no_config_log_stdout_cmd,
6de69f83 1721 "no log stdout [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
718e3744 1722 NO_STR
1723 "Logging control\n"
274a4a44 1724 "Cancel logging to stdout\n"
d0bfb22c 1725 LOG_LEVEL_DESC)
718e3744 1726{
274a4a44 1727 zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
718e3744 1728 return CMD_SUCCESS;
1729}
1730
274a4a44 1731DEFUN (config_log_monitor,
1732 config_log_monitor_cmd,
6de69f83 1733 "log monitor [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
274a4a44 1734 "Logging control\n"
1735 "Set terminal line (monitor) logging level\n"
1736 LOG_LEVEL_DESC)
1737{
c349116d 1738 int idx_log_level = 2;
58749582
DW
1739
1740 if (argc == idx_log_level)
d0bfb22c
QY
1741 {
1742 zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl);
1743 return CMD_SUCCESS;
1744 }
274a4a44 1745 int level;
1746
c349116d 1747 if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED)
274a4a44 1748 return CMD_ERR_NO_MATCH;
1749 zlog_set_level (NULL, ZLOG_DEST_MONITOR, level);
1750 return CMD_SUCCESS;
1751}
1752
1753DEFUN (no_config_log_monitor,
1754 no_config_log_monitor_cmd,
6de69f83 1755 "no log monitor [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
274a4a44 1756 NO_STR
1757 "Logging control\n"
1758 "Disable terminal line (monitor) logging\n"
d0bfb22c 1759 LOG_LEVEL_DESC)
274a4a44 1760{
1761 zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
1762 return CMD_SUCCESS;
1763}
1764
1765static int
1766set_log_file(struct vty *vty, const char *fname, int loglevel)
718e3744 1767{
1768 int ret;
9035efaa 1769 char *p = NULL;
1770 const char *fullpath;
d0bfb22c 1771
718e3744 1772 /* Path detection. */
274a4a44 1773 if (! IS_DIRECTORY_SEP (*fname))
718e3744 1774 {
9035efaa 1775 char cwd[MAXPATHLEN+1];
1776 cwd[MAXPATHLEN] = '\0';
d0bfb22c 1777
9035efaa 1778 if (getcwd (cwd, MAXPATHLEN) == NULL)
1779 {
1780 zlog_err ("config_log_file: Unable to alloc mem!");
1781 return CMD_WARNING;
1782 }
d0bfb22c 1783
274a4a44 1784 if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2))
9035efaa 1785 == NULL)
1786 {
1787 zlog_err ("config_log_file: Unable to alloc mem!");
1788 return CMD_WARNING;
1789 }
274a4a44 1790 sprintf (p, "%s/%s", cwd, fname);
9035efaa 1791 fullpath = p;
718e3744 1792 }
1793 else
274a4a44 1794 fullpath = fname;
718e3744 1795
274a4a44 1796 ret = zlog_set_file (NULL, fullpath, loglevel);
718e3744 1797
9035efaa 1798 if (p)
1799 XFREE (MTYPE_TMP, p);
1800
718e3744 1801 if (!ret)
1802 {
274a4a44 1803 vty_out (vty, "can't open logfile %s\n", fname);
718e3744 1804 return CMD_WARNING;
1805 }
1806
1807 if (host.logfile)
05865c90 1808 XFREE (MTYPE_HOST, host.logfile);
718e3744 1809
05865c90 1810 host.logfile = XSTRDUP (MTYPE_HOST, fname);
718e3744 1811
c05795b1
SK
1812#if defined(HAVE_CUMULUS)
1813 if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
1814 zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED;
1815#endif
718e3744 1816 return CMD_SUCCESS;
1817}
1818
274a4a44 1819DEFUN (config_log_file,
1820 config_log_file_cmd,
6de69f83 1821 "log file FILENAME [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
274a4a44 1822 "Logging control\n"
1823 "Logging to file\n"
1824 "Logging filename\n"
1825 LOG_LEVEL_DESC)
1826{
c349116d
DW
1827 int idx_filename = 2;
1828 int idx_log_levels = 3;
d0bfb22c
QY
1829 if (argc == 4)
1830 {
1831 int level;
c349116d 1832 if ((level = level_match(argv[idx_log_levels]->arg)) == ZLOG_DISABLED)
d0bfb22c 1833 return CMD_ERR_NO_MATCH;
c349116d 1834 return set_log_file(vty, argv[idx_filename]->arg, level);
d0bfb22c
QY
1835 }
1836 else
c349116d 1837 return set_log_file(vty, argv[idx_filename]->arg, zlog_default->default_lvl);
274a4a44 1838}
1839
718e3744 1840DEFUN (no_config_log_file,
1841 no_config_log_file_cmd,
d0bfb22c 1842 "no log file [FILENAME [LEVEL]]",
718e3744 1843 NO_STR
1844 "Logging control\n"
1845 "Cancel logging to file\n"
d0bfb22c
QY
1846 "Logging file name\n"
1847 "Logging file name\n"
1848 "Logging level\n")
718e3744 1849{
1850 zlog_reset_file (NULL);
1851
1852 if (host.logfile)
05865c90 1853 XFREE (MTYPE_HOST, host.logfile);
718e3744 1854
1855 host.logfile = NULL;
1856
1857 return CMD_SUCCESS;
1858}
1859
1860DEFUN (config_log_syslog,
1861 config_log_syslog_cmd,
6de69f83 1862 "log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
12ab19f1 1863 "Logging control\n"
274a4a44 1864 "Set syslog logging level\n"
1865 LOG_LEVEL_DESC)
1866{
c349116d 1867 int idx_log_levels = 2;
d0bfb22c
QY
1868 if (argc == 3)
1869 {
1870 int level;
c349116d 1871 if ((level = level_match (argv[idx_log_levels]->arg)) == ZLOG_DISABLED)
d0bfb22c
QY
1872 return CMD_ERR_NO_MATCH;
1873 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, level);
1874 return CMD_SUCCESS;
1875 }
1876 else
1877 {
1878 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
1879 return CMD_SUCCESS;
1880 }
274a4a44 1881}
1882
1883DEFUN_DEPRECATED (config_log_syslog_facility,
d0bfb22c 1884 config_log_syslog_facility_cmd,
199d90a1 1885 "log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)",
d0bfb22c
QY
1886 "Logging control\n"
1887 "Logging goes to syslog\n"
1888 "(Deprecated) Facility parameter for syslog messages\n"
1889 LOG_FACILITY_DESC)
274a4a44 1890{
d0bfb22c 1891 int facility = facility_match(argv[3]->arg);
12ab19f1 1892
274a4a44 1893 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
1894 zlog_default->facility = facility;
718e3744 1895 return CMD_SUCCESS;
1896}
1897
1898DEFUN (no_config_log_syslog,
1899 no_config_log_syslog_cmd,
6de69f83 1900 "no log syslog [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>] [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
718e3744 1901 NO_STR
1902 "Logging control\n"
274a4a44 1903 "Cancel logging to syslog\n"
d0bfb22c
QY
1904 LOG_FACILITY_DESC
1905 LOG_LEVEL_DESC)
718e3744 1906{
274a4a44 1907 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
718e3744 1908 return CMD_SUCCESS;
1909}
1910
274a4a44 1911DEFUN (config_log_facility,
1912 config_log_facility_cmd,
9ccf14f7 1913 "log facility <kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>",
718e3744 1914 "Logging control\n"
274a4a44 1915 "Facility parameter for syslog messages\n"
1916 LOG_FACILITY_DESC)
718e3744 1917{
c349116d
DW
1918 int idx_target = 2;
1919 int facility = facility_match(argv[idx_target]->arg);
274a4a44 1920
274a4a44 1921 zlog_default->facility = facility;
1922 return CMD_SUCCESS;
718e3744 1923}
1924
274a4a44 1925DEFUN (no_config_log_facility,
1926 no_config_log_facility_cmd,
9ccf14f7 1927 "no log facility [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>]",
718e3744 1928 NO_STR
1929 "Logging control\n"
274a4a44 1930 "Reset syslog facility to default (daemon)\n"
d0bfb22c 1931 LOG_FACILITY_DESC)
274a4a44 1932{
1933 zlog_default->facility = LOG_DAEMON;
1934 return CMD_SUCCESS;
1935}
1936
1937DEFUN_DEPRECATED (config_log_trap,
d0bfb22c 1938 config_log_trap_cmd,
199d90a1 1939 "log trap <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>",
d0bfb22c
QY
1940 "Logging control\n"
1941 "(Deprecated) Set logging level and default for all destinations\n"
1942 LOG_LEVEL_DESC)
274a4a44 1943{
1944 int new_level ;
1945 int i;
d0bfb22c
QY
1946
1947 if ((new_level = level_match(argv[2]->arg)) == ZLOG_DISABLED)
274a4a44 1948 return CMD_ERR_NO_MATCH;
1949
1950 zlog_default->default_lvl = new_level;
1951 for (i = 0; i < ZLOG_NUM_DESTS; i++)
1952 if (zlog_default->maxlvl[i] != ZLOG_DISABLED)
1953 zlog_default->maxlvl[i] = new_level;
1954 return CMD_SUCCESS;
1955}
1956
1957DEFUN_DEPRECATED (no_config_log_trap,
d0bfb22c 1958 no_config_log_trap_cmd,
199d90a1 1959 "no log trap [emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]",
d0bfb22c
QY
1960 NO_STR
1961 "Logging control\n"
1962 "Permit all logging information\n"
1963 LOG_LEVEL_DESC)
718e3744 1964{
274a4a44 1965 zlog_default->default_lvl = LOG_DEBUG;
718e3744 1966 return CMD_SUCCESS;
1967}
1968
1969DEFUN (config_log_record_priority,
1970 config_log_record_priority_cmd,
1971 "log record-priority",
1972 "Logging control\n"
1973 "Log the priority of the message within the message\n")
1974{
1975 zlog_default->record_priority = 1 ;
1976 return CMD_SUCCESS;
1977}
1978
1979DEFUN (no_config_log_record_priority,
1980 no_config_log_record_priority_cmd,
1981 "no log record-priority",
1982 NO_STR
1983 "Logging control\n"
1984 "Do not log the priority of the message within the message\n")
1985{
1986 zlog_default->record_priority = 0 ;
1987 return CMD_SUCCESS;
1988}
1989
1ed72e0b
AS
1990DEFUN (config_log_timestamp_precision,
1991 config_log_timestamp_precision_cmd,
6147e2c6 1992 "log timestamp precision (0-6)",
1ed72e0b
AS
1993 "Logging control\n"
1994 "Timestamp configuration\n"
1995 "Set the timestamp precision\n"
1996 "Number of subsecond digits\n")
1997{
c349116d 1998 int idx_number = 3;
1ed72e0b 1999 VTY_GET_INTEGER_RANGE("Timestamp Precision",
c349116d 2000 zlog_default->timestamp_precision, argv[idx_number]->arg, 0, 6);
1ed72e0b
AS
2001 return CMD_SUCCESS;
2002}
2003
2004DEFUN (no_config_log_timestamp_precision,
2005 no_config_log_timestamp_precision_cmd,
2006 "no log timestamp precision",
2007 NO_STR
2008 "Logging control\n"
2009 "Timestamp configuration\n"
2010 "Reset the timestamp precision to the default value of 0\n")
2011{
2012 zlog_default->timestamp_precision = 0 ;
2013 return CMD_SUCCESS;
2014}
2015
7cfc61d3
DS
2016int
2017cmd_banner_motd_file (const char *file)
2018{
1ee08155
DS
2019 int success = CMD_SUCCESS;
2020 char p[PATH_MAX];
2021 char *rpath;
2022 char *in;
7cfc61d3 2023
1ee08155
DS
2024 rpath = realpath (file, p);
2025 if (!rpath)
2026 return CMD_ERR_NO_FILE;
2027 in = strstr (rpath, SYSCONFDIR);
2028 if (in == rpath)
2029 {
2030 if (host.motdfile)
844ec28c 2031 XFREE (MTYPE_HOST, host.motdfile);
1ee08155
DS
2032 host.motdfile = XSTRDUP (MTYPE_HOST, file);
2033 }
2034 else
2035 success = CMD_WARNING;
2036
2037 return success;
7cfc61d3
DS
2038}
2039
3b0c5d9a 2040DEFUN (banner_motd_file,
2041 banner_motd_file_cmd,
4d833e55 2042 "banner motd file FILE",
3b0c5d9a 2043 "Set banner\n"
2044 "Banner for motd\n"
2045 "Banner from a file\n"
2046 "Filename\n")
2047{
c349116d
DW
2048 int idx_file = 3;
2049 const char *filename = argv[idx_file]->arg;
97e5b7c0 2050 int cmd = cmd_banner_motd_file (filename);
1ee08155
DS
2051
2052 if (cmd == CMD_ERR_NO_FILE)
97e5b7c0 2053 vty_out (vty, "%s does not exist", filename);
1ee08155 2054 else if (cmd == CMD_WARNING)
97e5b7c0 2055 vty_out (vty, "%s must be in %s", filename, SYSCONFDIR);
1ee08155
DS
2056
2057 return cmd;
3b0c5d9a 2058}
718e3744 2059
2060DEFUN (banner_motd_default,
2061 banner_motd_default_cmd,
2062 "banner motd default",
2063 "Set banner string\n"
2064 "Strings for motd\n"
2065 "Default string\n")
2066{
2067 host.motd = default_motd;
2068 return CMD_SUCCESS;
2069}
2070
2071DEFUN (no_banner_motd,
2072 no_banner_motd_cmd,
2073 "no banner motd",
2074 NO_STR
2075 "Set banner string\n"
2076 "Strings for motd\n")
2077{
2078 host.motd = NULL;
d0bfb22c 2079 if (host.motdfile)
05865c90 2080 XFREE (MTYPE_HOST, host.motdfile);
3b0c5d9a 2081 host.motdfile = NULL;
718e3744 2082 return CMD_SUCCESS;
2083}
2084
bcd9fa7f
LB
2085DEFUN (show_commandtree,
2086 show_commandtree_cmd,
2087 "show commandtree",
2088 NO_STR
2089 "Show command tree\n")
2090{
2091 /* TBD */
2092 vector cmd_vector;
2093 unsigned int i;
2094
2095 vty_out (vty, "Current node id: %d%s", vty->node, VTY_NEWLINE);
2096
2097 /* vector of all commands installed at this node */
2098 cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
2099
2100 /* loop over all commands at this node */
2101 for (i = 0; i < vector_active(cmd_vector); ++i)
2102 {
2103 struct cmd_element *cmd_element;
2104
2105 /* A cmd_element (seems to be) is an individual command */
2106 if ((cmd_element = vector_slot (cmd_vector, i)) == NULL)
2107 continue;
2108
2109 vty_out (vty, " %s%s", cmd_element->string, VTY_NEWLINE);
2110 }
2111
2112 vector_free (cmd_vector);
2113 return CMD_SUCCESS;
2114}
2115
718e3744 2116/* Set config filename. Called from vty.c */
2117void
c0e8c16f 2118host_config_set (const char *filename)
718e3744 2119{
228da428
CC
2120 if (host.config)
2121 XFREE (MTYPE_HOST, host.config);
05865c90 2122 host.config = XSTRDUP (MTYPE_HOST, filename);
718e3744 2123}
2124
2125void
2126install_default (enum node_type node)
2127{
2128 install_element (node, &config_exit_cmd);
d862bffb 2129 install_element (node, &config_quit_cmd);
718e3744 2130 install_element (node, &config_end_cmd);
2131 install_element (node, &config_help_cmd);
2132 install_element (node, &config_list_cmd);
2133
718e3744 2134 install_element (node, &config_write_cmd);
d862bffb 2135 install_element (node, &show_running_config_cmd);
718e3744 2136}
2137
2138/* Initialize command interface. Install basic nodes and commands. */
2139void
2140cmd_init (int terminal)
2141{
2142 /* Allocate initial top vector of commands. */
2143 cmdvec = vector_init (VECTOR_MIN_SIZE);
2144
2145 /* Default host value settings. */
2146 host.name = NULL;
2147 host.password = NULL;
2148 host.enable = NULL;
2149 host.logfile = NULL;
2150 host.config = NULL;
2151 host.lines = -1;
2152 host.motd = default_motd;
3b0c5d9a 2153 host.motdfile = NULL;
718e3744 2154
2155 /* Install top nodes. */
2156 install_node (&view_node, NULL);
2157 install_node (&enable_node, NULL);
2158 install_node (&auth_node, NULL);
2159 install_node (&auth_enable_node, NULL);
62687ff1 2160 install_node (&restricted_node, NULL);
718e3744 2161 install_node (&config_node, config_write_host);
2162
2163 /* Each node's basic commands. */
2164 install_element (VIEW_NODE, &show_version_cmd);
2165 if (terminal)
2166 {
2167 install_element (VIEW_NODE, &config_list_cmd);
2168 install_element (VIEW_NODE, &config_exit_cmd);
d862bffb 2169 install_element (VIEW_NODE, &config_quit_cmd);
718e3744 2170 install_element (VIEW_NODE, &config_help_cmd);
2171 install_element (VIEW_NODE, &config_enable_cmd);
2172 install_element (VIEW_NODE, &config_terminal_length_cmd);
2173 install_element (VIEW_NODE, &config_terminal_no_length_cmd);
274a4a44 2174 install_element (VIEW_NODE, &show_logging_cmd);
bcd9fa7f 2175 install_element (VIEW_NODE, &show_commandtree_cmd);
2885f72d 2176 install_element (VIEW_NODE, &echo_cmd);
62687ff1
PJ
2177
2178 install_element (RESTRICTED_NODE, &config_list_cmd);
2179 install_element (RESTRICTED_NODE, &config_exit_cmd);
f667a580 2180 install_element (RESTRICTED_NODE, &config_quit_cmd);
62687ff1
PJ
2181 install_element (RESTRICTED_NODE, &config_help_cmd);
2182 install_element (RESTRICTED_NODE, &config_enable_cmd);
2183 install_element (RESTRICTED_NODE, &config_terminal_length_cmd);
2184 install_element (RESTRICTED_NODE, &config_terminal_no_length_cmd);
2185 install_element (RESTRICTED_NODE, &echo_cmd);
718e3744 2186 }
2187
2188 if (terminal)
2189 {
2190 install_default (ENABLE_NODE);
2191 install_element (ENABLE_NODE, &config_disable_cmd);
2192 install_element (ENABLE_NODE, &config_terminal_cmd);
d862bffb 2193 install_element (ENABLE_NODE, &copy_runningconf_startupconf_cmd);
718e3744 2194 }
2195 install_element (ENABLE_NODE, &show_startup_config_cmd);
2196 install_element (ENABLE_NODE, &show_version_cmd);
bcd9fa7f 2197 install_element (ENABLE_NODE, &show_commandtree_cmd);
718e3744 2198
718e3744 2199 if (terminal)
2200 {
e7168df4 2201 install_element (ENABLE_NODE, &config_terminal_length_cmd);
2202 install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
274a4a44 2203 install_element (ENABLE_NODE, &show_logging_cmd);
2885f72d 2204 install_element (ENABLE_NODE, &echo_cmd);
274a4a44 2205 install_element (ENABLE_NODE, &config_logmsg_cmd);
e7168df4 2206
2207 install_default (CONFIG_NODE);
ea8e9d97 2208 }
d0bfb22c 2209
ea8e9d97 2210 install_element (CONFIG_NODE, &hostname_cmd);
2211 install_element (CONFIG_NODE, &no_hostname_cmd);
e7168df4 2212
ea8e9d97 2213 if (terminal)
2214 {
e7168df4 2215 install_element (CONFIG_NODE, &password_cmd);
e7168df4 2216 install_element (CONFIG_NODE, &enable_password_cmd);
e7168df4 2217 install_element (CONFIG_NODE, &no_enable_password_cmd);
2218
718e3744 2219 install_element (CONFIG_NODE, &config_log_stdout_cmd);
2220 install_element (CONFIG_NODE, &no_config_log_stdout_cmd);
274a4a44 2221 install_element (CONFIG_NODE, &config_log_monitor_cmd);
274a4a44 2222 install_element (CONFIG_NODE, &no_config_log_monitor_cmd);
718e3744 2223 install_element (CONFIG_NODE, &config_log_file_cmd);
2224 install_element (CONFIG_NODE, &no_config_log_file_cmd);
2225 install_element (CONFIG_NODE, &config_log_syslog_cmd);
2226 install_element (CONFIG_NODE, &no_config_log_syslog_cmd);
274a4a44 2227 install_element (CONFIG_NODE, &config_log_facility_cmd);
2228 install_element (CONFIG_NODE, &no_config_log_facility_cmd);
718e3744 2229 install_element (CONFIG_NODE, &config_log_trap_cmd);
2230 install_element (CONFIG_NODE, &no_config_log_trap_cmd);
2231 install_element (CONFIG_NODE, &config_log_record_priority_cmd);
2232 install_element (CONFIG_NODE, &no_config_log_record_priority_cmd);
1ed72e0b
AS
2233 install_element (CONFIG_NODE, &config_log_timestamp_precision_cmd);
2234 install_element (CONFIG_NODE, &no_config_log_timestamp_precision_cmd);
718e3744 2235 install_element (CONFIG_NODE, &service_password_encrypt_cmd);
2236 install_element (CONFIG_NODE, &no_service_password_encrypt_cmd);
2237 install_element (CONFIG_NODE, &banner_motd_default_cmd);
3b0c5d9a 2238 install_element (CONFIG_NODE, &banner_motd_file_cmd);
718e3744 2239 install_element (CONFIG_NODE, &no_banner_motd_cmd);
2240 install_element (CONFIG_NODE, &service_terminal_length_cmd);
2241 install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
718e3744 2242
354d119a 2243 install_element (VIEW_NODE, &show_thread_cpu_cmd);
2244 install_element (ENABLE_NODE, &show_thread_cpu_cmd);
62687ff1 2245 install_element (RESTRICTED_NODE, &show_thread_cpu_cmd);
d0bfb22c 2246
e276eb82 2247 install_element (ENABLE_NODE, &clear_thread_cpu_cmd);
354d119a 2248 install_element (VIEW_NODE, &show_work_queues_cmd);
2249 install_element (ENABLE_NODE, &show_work_queues_cmd);
19dc275e
DS
2250
2251 vrf_install_commands ();
9ab6812d 2252 }
b06fd125 2253 srandom(time(NULL));
718e3744 2254}
228da428 2255
d0bfb22c
QY
2256struct cmd_token *
2257new_cmd_token (enum cmd_token_type type, char *text, char *desc)
cd40b329 2258{
d0bfb22c
QY
2259 struct cmd_token *token = XMALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token));
2260 token->type = type;
2261 token->text = text;
2262 token->desc = desc;
2263 token->arg = NULL;
cd40b329 2264
d0bfb22c
QY
2265 return token;
2266}
cd40b329 2267
d0bfb22c
QY
2268void
2269del_cmd_token (struct cmd_token *token)
2270{
2271 if (!token) return;
cd40b329 2272
d0bfb22c 2273 if (token->text)
97e5b7c0 2274 free (token->text);
d0bfb22c 2275 if (token->desc)
97e5b7c0 2276 free (token->desc);
d0bfb22c 2277 if (token->arg)
97e5b7c0 2278 free (token->arg);
cd40b329 2279
97e5b7c0 2280 free (token);
cd40b329
CF
2281}
2282
d0bfb22c
QY
2283struct cmd_token *
2284copy_cmd_token (struct cmd_token *token)
cd40b329 2285{
d0bfb22c 2286 struct cmd_token *copy = new_cmd_token (token->type, NULL, NULL);
d0bfb22c
QY
2287 copy->max = token->max;
2288 copy->min = token->min;
2289 copy->text = token->text ? XSTRDUP (MTYPE_CMD_TOKENS, token->text) : NULL;
2290 copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_TOKENS, token->desc) : NULL;
2291 copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_TOKENS, token->arg) : NULL;
cd40b329 2292
d0bfb22c 2293 return copy;
cd40b329
CF
2294}
2295
de9d7e4f 2296void
1eb5e8dc 2297del_cmd_element(struct cmd_element *cmd)
de9d7e4f
QY
2298{
2299 if (!cmd) return;
97e5b7c0
QY
2300 free ((char *) cmd->string);
2301 free ((char *) cmd->doc);
2302 free (cmd);
de9d7e4f
QY
2303}
2304
2305struct cmd_element *
2306copy_cmd_element(struct cmd_element *cmd)
2307{
2308 struct cmd_element *el = XMALLOC(MTYPE_CMD_TOKENS, sizeof (struct cmd_element));
2309 el->string = cmd->string ? XSTRDUP(MTYPE_CMD_TOKENS, cmd->string) : NULL;
2310 el->func = cmd->func;
2311 el->doc = cmd->doc ? XSTRDUP(MTYPE_CMD_TOKENS, cmd->doc) : NULL;
2312 el->daemon = cmd->daemon;
de9d7e4f 2313 el->attr = cmd->attr;
de9d7e4f
QY
2314 return el;
2315}
2316
228da428
CC
2317void
2318cmd_terminate ()
2319{
228da428 2320 struct cmd_node *cmd_node;
228da428
CC
2321
2322 if (cmdvec)
2323 {
d0bfb22c 2324 for (unsigned int i = 0; i < vector_active (cmdvec); i++)
228da428 2325 if ((cmd_node = vector_slot (cmdvec, i)) != NULL)
d0bfb22c
QY
2326 {
2327 // deleting the graph delets the cmd_element as well
2328 graph_delete_graph (cmd_node->cmdgraph);
2329 vector_free (cmd_node->cmd_vector);
2330 }
228da428
CC
2331
2332 vector_free (cmdvec);
2333 cmdvec = NULL;
2334 }
2335
228da428
CC
2336 if (host.name)
2337 XFREE (MTYPE_HOST, host.name);
2338 if (host.password)
2339 XFREE (MTYPE_HOST, host.password);
2340 if (host.password_encrypt)
2341 XFREE (MTYPE_HOST, host.password_encrypt);
2342 if (host.enable)
2343 XFREE (MTYPE_HOST, host.enable);
2344 if (host.enable_encrypt)
2345 XFREE (MTYPE_HOST, host.enable_encrypt);
2346 if (host.logfile)
2347 XFREE (MTYPE_HOST, host.logfile);
2348 if (host.motdfile)
2349 XFREE (MTYPE_HOST, host.motdfile);
2350 if (host.config)
2351 XFREE (MTYPE_HOST, host.config);
2352}