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