vtysh.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:42k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* Virtual terminal interface shell.
  2.  * Copyright (C) 2000 Kunihiro Ishiguro
  3.  *
  4.  * This file is part of GNU Zebra.
  5.  *
  6.  * GNU Zebra is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation; either version 2, or (at your option) any
  9.  * later version.
  10.  *
  11.  * GNU Zebra is distributed in the hope that it will be useful, but
  12.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
  18.  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19.  * 02111-1307, USA.  
  20.  */
  21. #include <zebra.h>
  22. #include <sys/un.h>
  23. #include <setjmp.h>
  24. #include <sys/wait.h>
  25. #include <sys/resource.h>
  26. #include <sys/stat.h>
  27. #include <readline/readline.h>
  28. #include <readline/history.h>
  29. #include "command.h"
  30. #include "memory.h"
  31. #include "vtysh/vtysh.h"
  32. /* Struct VTY. */
  33. struct vty *vty;
  34. /* VTY shell pager name. */
  35. char *vtysh_pager_name = NULL;
  36. /* VTY shell client structure. */
  37. struct vtysh_client
  38. {
  39.   int fd;
  40. } vtysh_client[VTYSH_INDEX_MAX];
  41. /* When '^Z' is received from vty, move down to the enable mode. */
  42. int
  43. vtysh_end ()
  44. {
  45.   switch (vty->node)
  46.     {
  47.     case VIEW_NODE:
  48.     case ENABLE_NODE:
  49.       /* Nothing to do. */
  50.       break;
  51.     default:
  52.       vty->node = ENABLE_NODE;
  53.       break;
  54.     }
  55.   return CMD_SUCCESS;
  56. }
  57. DEFUNSH (VTYSH_ALL,
  58.  vtysh_end_all,
  59.  vtysh_end_all_cmd,
  60.  "end",
  61.  "End current mode and down to previous moden")
  62. {
  63.   return vtysh_end (vty);
  64. }
  65. DEFUNSH (VTYSH_ALL,
  66.  vtysh_log_stdout,
  67.  vtysh_log_stdout_cmd,
  68.  "log stdout",
  69.  "Logging controln"
  70.  "Logging goes to stdoutn")
  71. {
  72.   return CMD_SUCCESS;
  73. }
  74. DEFUNSH (VTYSH_ALL,
  75.  no_vtysh_log_stdout,
  76.  no_vtysh_log_stdout_cmd,
  77.  "no log stdout",
  78.  NO_STR
  79.  "Logging controln"
  80.  "Logging goes to stdoutn")
  81. {
  82.   return CMD_SUCCESS;
  83. }
  84. DEFUNSH (VTYSH_ALL,
  85.        vtysh_log_file,
  86.        vtysh_log_file_cmd,
  87.        "log file FILENAME",
  88.        "Logging controln"
  89.        "Logging to filen"
  90.        "Logging filenamen")
  91. {
  92.   return CMD_SUCCESS;
  93. }
  94. DEFUNSH (VTYSH_ALL,
  95.        no_vtysh_log_file,
  96.        no_vtysh_log_file_cmd,
  97.        "no log file [FILENAME]",
  98.        NO_STR
  99.        "Logging controln"
  100.        "Cancel logging to filen"
  101.        "Logging file namen")
  102. {
  103.   return CMD_SUCCESS;
  104. }
  105. DEFUNSH (VTYSH_ALL,
  106.  vtysh_log_syslog,
  107.  vtysh_log_syslog_cmd,
  108.  "log syslog",
  109.  "Logging controln"
  110.  "Logging goes to syslogn")
  111. {
  112.   return CMD_SUCCESS;
  113. }
  114. DEFUNSH (VTYSH_ALL,
  115.  no_vtysh_log_syslog,
  116.  no_vtysh_log_syslog_cmd,
  117.  "no log syslog",
  118.  NO_STR
  119.  "Logging controln"
  120.  "Cancel logging to syslogn")
  121. {
  122.   return CMD_SUCCESS;
  123. }
  124. DEFUNSH (VTYSH_ALL,
  125.  vtysh_log_trap,
  126.  vtysh_log_trap_cmd,
  127.  "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)",
  128.  "Logging controln"
  129.  "Limit logging to specifed leveln")
  130. {
  131.   return CMD_SUCCESS;
  132. }
  133. DEFUNSH (VTYSH_ALL,
  134.  no_vtysh_log_trap,
  135.  no_vtysh_log_trap_cmd,
  136.  "no log trap",
  137.  NO_STR
  138.  "Logging controln"
  139.  "Permit all logging informationn")
  140. {
  141.   return CMD_SUCCESS;
  142. }
  143. DEFUNSH (VTYSH_ALL,
  144.  vtysh_log_record_priority,
  145.  vtysh_log_record_priority_cmd,
  146.  "log record-priority",
  147.  "Logging controln"
  148.  "Log the priority of the message within the messagen")
  149. {
  150.   return CMD_SUCCESS;
  151. }
  152. DEFUNSH (VTYSH_ALL,
  153.  no_vtysh_log_record_priority,
  154.  no_vtysh_log_record_priority_cmd,
  155.  "no log record-priority",
  156.  NO_STR
  157.  "Logging controln"
  158.  "Do not log the priority of the message within the messagen")
  159. {
  160.   return CMD_SUCCESS;
  161. }
  162. void
  163. vclient_close (struct vtysh_client *vclient)
  164. {
  165.   if (vclient->fd > 0)
  166.     close (vclient->fd);
  167.   vclient->fd = -1;
  168. }
  169. /* Following filled with debug code to trace a problematic condition
  170.    under load - it SHOULD handle it.
  171. */
  172. #define ERR_WHERE_STRING "vtysh(): vtysh_client_config(): "
  173. int
  174. vtysh_client_config (struct vtysh_client *vclient, char *line)
  175. {
  176.   int ret;
  177.   char *buf;
  178.   size_t bufsz;
  179.   char *pbuf;
  180.   size_t left;
  181.   char *eoln;
  182.   int nbytes;
  183.   int i;
  184.   int readln;
  185.   if (vclient->fd < 0)
  186.     return CMD_SUCCESS;
  187.   ret = write (vclient->fd, line, strlen (line) + 1);
  188.   if (ret <= 0)
  189.     {
  190.       vclient_close (vclient);
  191.       return CMD_SUCCESS;
  192.     }
  193.   /* Allow enough room for buffer to read more than a few pages from socket
  194.    */
  195.   bufsz = 5 * sysconf(_SC_PAGESIZE) + 1;
  196.   buf = XMALLOC(MTYPE_TMP, bufsz);
  197.   memset(buf, 0, bufsz);
  198.   pbuf = buf;
  199.   while (1)
  200.     {
  201.       if (pbuf >= ((buf + bufsz) -1))
  202. {
  203.   fprintf (stderr, ERR_WHERE_STRING 
  204.    "warning - pbuf beyond buffer end.n");
  205.   return CMD_WARNING;
  206. }
  207.       readln = (buf + bufsz) - pbuf - 1;
  208.       nbytes = read (vclient->fd, pbuf, readln);
  209.       if (nbytes <= 0)
  210. {
  211.   if (errno == EINTR)
  212.     continue;
  213.   fprintf(stderr, ERR_WHERE_STRING "(%u)", errno);
  214.   perror("");
  215.   if (errno == EAGAIN || errno == EIO)
  216.     continue;
  217.   vclient_close (vclient);
  218.   XFREE(MTYPE_TMP, buf);
  219.   return CMD_SUCCESS;
  220. }
  221.       pbuf[nbytes] = '';
  222.       if (nbytes >= 4)
  223. {
  224.   i = nbytes - 4;
  225.   if (pbuf[i] == '' && pbuf[i + 1] == '' && pbuf[i + 2] == '')
  226.     {
  227.       ret = pbuf[i + 3];
  228.       break;
  229.     }
  230. }
  231.       pbuf += nbytes;
  232.       /* See if a line exists in buffer, if so parse and consume it, and
  233.  reset read position */
  234.       if ((eoln = strrchr(buf, 'n')) == NULL)
  235. continue;
  236.       if (eoln >= ((buf + bufsz) - 1))
  237. {
  238.   fprintf (stderr, ERR_WHERE_STRING 
  239.    "warning - eoln beyond buffer end.n");
  240. }
  241.       vtysh_config_parse(buf);
  242.       eoln++;
  243.       left = (size_t)(buf + bufsz - eoln);
  244.       memmove(buf, eoln, left);
  245.       buf[bufsz-1] = '';
  246.       pbuf = buf + strlen(buf);
  247.     }
  248.   /* parse anything left in the buffer */
  249.   vtysh_config_parse (buf);
  250.   XFREE(MTYPE_TMP, buf);
  251.   return ret;
  252. }
  253. int
  254. vtysh_client_execute (struct vtysh_client *vclient, char *line, FILE *fp)
  255. {
  256.   int ret;
  257.   char buf[1001];
  258.   int nbytes;
  259.   int i;
  260.   if (vclient->fd < 0)
  261.     return CMD_SUCCESS;
  262.   ret = write (vclient->fd, line, strlen (line) + 1);
  263.   if (ret <= 0)
  264.     {
  265.       vclient_close (vclient);
  266.       return CMD_SUCCESS;
  267.     }
  268.   while (1)
  269.     {
  270.       nbytes = read (vclient->fd, buf, sizeof(buf)-1);
  271.       if (nbytes <= 0 && errno != EINTR)
  272. {
  273.   vclient_close (vclient);
  274.   return CMD_SUCCESS;
  275. }
  276.       if (nbytes > 0)
  277. {
  278.   buf[nbytes] = '';
  279.   fprintf (fp, "%s", buf);
  280.   fflush (fp);
  281.   if (nbytes >= 4)
  282.     {
  283.       i = nbytes - 4;
  284.       if (buf[i] == '' && buf[i + 1] == '' && buf[i + 2] == '')
  285. {
  286.   ret = buf[i + 3];
  287.   break;
  288. }
  289.     }
  290. }
  291.     }
  292.   return ret;
  293. }
  294. void
  295. vtysh_exit_ripd_only ()
  296. {
  297.   vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP], "exit", stdout);
  298. }
  299. void
  300. vtysh_pager_init ()
  301. {
  302.   vtysh_pager_name = getenv ("VTYSH_PAGER");
  303.   if (! vtysh_pager_name)
  304.     vtysh_pager_name = "more";
  305. }
  306. /* Command execution over the vty interface. */
  307. void
  308. vtysh_execute_func (char *line, int pager)
  309. {
  310.   int ret, cmd_stat;
  311.   vector vline;
  312.   struct cmd_element *cmd;
  313.   FILE *fp = NULL;
  314.   /* Split readline string up into the vector */
  315.   vline = cmd_make_strvec (line);
  316.   if (vline == NULL)
  317.     return;
  318.   ret = cmd_execute_command (vline, vty, &cmd);
  319.   cmd_free_strvec (vline);
  320.   switch (ret)
  321.     {
  322.     case CMD_WARNING:
  323.       if (vty->type == VTY_FILE)
  324. printf ("Warning...n");
  325.       break;
  326.     case CMD_ERR_AMBIGUOUS:
  327.       printf ("%% Ambiguous command.n");
  328.       break;
  329.     case CMD_ERR_NO_MATCH:
  330.       printf ("%% Unknown command.n");
  331.       break;
  332.     case CMD_ERR_INCOMPLETE:
  333.       printf ("%% Command incomplete.n");
  334.       break;
  335.     case CMD_SUCCESS_DAEMON:
  336.       {
  337. if (pager && vtysh_pager_name)
  338.   {
  339.     fp = popen ("more", "w");
  340.     if (fp == NULL)
  341.       {
  342. perror ("popen");
  343. exit (1);
  344.       }
  345.   }
  346. else
  347.   fp = stdout;
  348. if (! strcmp(cmd->string,"configure terminal"))
  349.   {
  350.     cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA],
  351.      line, fp);
  352.     if (cmd_stat != CMD_WARNING)
  353.       cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP],
  354.        line, fp);
  355.     if (cmd_stat != CMD_WARNING)
  356.       cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG], line, fp);
  357.     if (cmd_stat != CMD_WARNING)
  358.       cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF],
  359.        line, fp);
  360.     if (cmd_stat != CMD_WARNING)
  361.       cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6], line, fp);
  362.     if (cmd_stat != CMD_WARNING)
  363.       cmd_stat = vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP],
  364.        line, fp);
  365.     if (cmd_stat)
  366.       {
  367.                 line = "end";
  368.                 vline = cmd_make_strvec (line);
  369.                 if (vline == NULL)
  370.   {
  371.     if (pager && vtysh_pager_name && fp)
  372.       {
  373. if (pclose (fp) == -1)
  374.   {
  375.     perror ("pclose");
  376.     exit (1);
  377.   }
  378. fp = NULL;
  379.       }
  380.     return;
  381.   }
  382.                 ret = cmd_execute_command (vline, vty, &cmd);
  383.                 cmd_free_strvec (vline);
  384.                 if (ret != CMD_SUCCESS_DAEMON)
  385.                   break;
  386.       }
  387.     else
  388.       if (cmd->func)
  389. {
  390.   (*cmd->func) (cmd, vty, 0, NULL);
  391.   break;
  392.                 }
  393.   }
  394. if (cmd->daemon & VTYSH_ZEBRA)
  395.   if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA], line, fp)
  396.       != CMD_SUCCESS)
  397.     break;
  398. if (cmd->daemon & VTYSH_RIPD)
  399.   if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP], line, fp)
  400.       != CMD_SUCCESS)
  401.     break;
  402. if (cmd->daemon & VTYSH_RIPNGD)
  403.   if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG], line, fp)
  404.       != CMD_SUCCESS)
  405.     break;
  406. if (cmd->daemon & VTYSH_OSPFD)
  407.   if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF], line, fp)
  408.       != CMD_SUCCESS)
  409.     break;
  410. if (cmd->daemon & VTYSH_OSPF6D)
  411.   if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6], line, fp)
  412.       != CMD_SUCCESS)
  413.     break;
  414. if (cmd->daemon & VTYSH_BGPD)
  415.   if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP], line, fp)
  416.       != CMD_SUCCESS)
  417.     break;
  418. if (cmd->func)
  419.   (*cmd->func) (cmd, vty, 0, NULL);
  420.       }
  421.     }
  422.   if (pager && vtysh_pager_name && fp)
  423.     {
  424.       if (pclose (fp) == -1)
  425. {
  426.   perror ("pclose");
  427.   exit (1);
  428. }
  429.       fp = NULL;
  430.     }
  431. }
  432. void
  433. vtysh_execute_no_pager (char *line)
  434. {
  435.   vtysh_execute_func (line, 0);
  436. }
  437. void
  438. vtysh_execute (char *line)
  439. {
  440.   vtysh_execute_func (line, 1);
  441. }
  442. /* Configration make from file. */
  443. int
  444. vtysh_config_from_file (struct vty *vty, FILE *fp)
  445. {
  446.   int ret;
  447.   vector vline;
  448.   struct cmd_element *cmd;
  449.   while (fgets (vty->buf, VTY_BUFSIZ, fp))
  450.     {
  451.       if (vty->buf[0] == '!' || vty->buf[1] == '#')
  452. continue;
  453.       vline = cmd_make_strvec (vty->buf);
  454.       /* In case of comment line */
  455.       if (vline == NULL)
  456. continue;
  457.       /* Execute configuration command : this is strict match */
  458.       ret = cmd_execute_command_strict (vline, vty, &cmd);
  459.       /* Try again with setting node to CONFIG_NODE */
  460.       if (ret != CMD_SUCCESS 
  461.   && ret != CMD_SUCCESS_DAEMON
  462.   && ret != CMD_WARNING)
  463. {
  464.   if (vty->node == KEYCHAIN_KEY_NODE)
  465.     {
  466.       vty->node = KEYCHAIN_NODE;
  467.       vtysh_exit_ripd_only ();
  468.       ret = cmd_execute_command_strict (vline, vty, &cmd);
  469.       if (ret != CMD_SUCCESS 
  470.   && ret != CMD_SUCCESS_DAEMON 
  471.   && ret != CMD_WARNING)
  472. {
  473.   vtysh_exit_ripd_only ();
  474.   vty->node = CONFIG_NODE;
  475.   ret = cmd_execute_command_strict (vline, vty, &cmd);
  476. }
  477.     }
  478.   else
  479.     {
  480.       vtysh_execute ("end");
  481.       vtysh_execute ("configure terminal");
  482.       vty->node = CONFIG_NODE;
  483.       ret = cmd_execute_command_strict (vline, vty, &cmd);
  484.     }
  485. }   
  486.       cmd_free_strvec (vline);
  487.       switch (ret)
  488. {
  489. case CMD_WARNING:
  490.   if (vty->type == VTY_FILE)
  491.     printf ("Warning...n");
  492.   break;
  493. case CMD_ERR_AMBIGUOUS:
  494.   printf ("%% Ambiguous command.n");
  495.   break;
  496. case CMD_ERR_NO_MATCH:
  497.   printf ("%% Unknown command: %s", vty->buf);
  498.   break;
  499. case CMD_ERR_INCOMPLETE:
  500.   printf ("%% Command incomplete.n");
  501.   break;
  502. case CMD_SUCCESS_DAEMON:
  503.   {
  504.     if (cmd->daemon & VTYSH_ZEBRA)
  505.       if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_ZEBRA],
  506. vty->buf, stdout) != CMD_SUCCESS)
  507. break;
  508.     if (cmd->daemon & VTYSH_RIPD)
  509.       if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIP],
  510. vty->buf, stdout) != CMD_SUCCESS)
  511. break;
  512.     if (cmd->daemon & VTYSH_RIPNGD)
  513.       if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_RIPNG],
  514. vty->buf, stdout) != CMD_SUCCESS)
  515. break;
  516.     if (cmd->daemon & VTYSH_OSPFD)
  517.       if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF],
  518. vty->buf, stdout) != CMD_SUCCESS)
  519. break;
  520.     if (cmd->daemon & VTYSH_OSPF6D)
  521.       if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_OSPF6],
  522. vty->buf, stdout) != CMD_SUCCESS)
  523. break;
  524.     if (cmd->daemon & VTYSH_BGPD)
  525.       if (vtysh_client_execute (&vtysh_client[VTYSH_INDEX_BGP],
  526. vty->buf, stdout) != CMD_SUCCESS)
  527. break;
  528.     if (cmd->func)
  529.       (*cmd->func) (cmd, vty, 0, NULL);
  530.   }
  531. }
  532.     }
  533.   return CMD_SUCCESS;
  534. }
  535. /* We don't care about the point of the cursor when '?' is typed. */
  536. int
  537. vtysh_rl_describe ()
  538. {
  539.   int ret;
  540.   int i;
  541.   vector vline;
  542.   vector describe;
  543.   int width;
  544.   struct desc *desc;
  545.   vline = cmd_make_strvec (rl_line_buffer);
  546.   /* In case of '> ?'. */
  547.   if (vline == NULL)
  548.     {
  549.       vline = vector_init (1);
  550.       vector_set (vline, '');
  551.     }
  552.   else 
  553.     if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
  554.       vector_set (vline, '');
  555.   describe = cmd_describe_command (vline, vty, &ret);
  556.   printf ("n");
  557.   /* Ambiguous and no match error. */
  558.   switch (ret)
  559.     {
  560.     case CMD_ERR_AMBIGUOUS:
  561.       cmd_free_strvec (vline);
  562.       printf ("%% Ambiguous command.n");
  563.       rl_on_new_line ();
  564.       return 0;
  565.       break;
  566.     case CMD_ERR_NO_MATCH:
  567.       cmd_free_strvec (vline);
  568.       printf ("%% There is no matched command.n");
  569.       rl_on_new_line ();
  570.       return 0;
  571.       break;
  572.     }  
  573.   /* Get width of command string. */
  574.   width = 0;
  575.   for (i = 0; i < vector_max (describe); i++)
  576.     if ((desc = vector_slot (describe, i)) != NULL)
  577.       {
  578. int len;
  579. if (desc->cmd[0] == '')
  580.   continue;
  581. len = strlen (desc->cmd);
  582. if (desc->cmd[0] == '.')
  583.   len--;
  584. if (width < len)
  585.   width = len;
  586.       }
  587.   for (i = 0; i < vector_max (describe); i++)
  588.     if ((desc = vector_slot (describe, i)) != NULL)
  589.       {
  590. if (desc->cmd[0] == '')
  591.   continue;
  592. if (! desc->str)
  593.   printf ("  %-sn",
  594.   desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd);
  595. else
  596.   printf ("  %-*s  %sn",
  597.   width,
  598.   desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
  599.   desc->str);
  600.       }
  601.   cmd_free_strvec (vline);
  602.   vector_free (describe);
  603.   rl_on_new_line();
  604.   return 0;
  605. }
  606. /* result of cmd_complete_command() call will be stored here
  607.    and used in new_completion() in order to put the space in
  608.    correct places only */
  609. int complete_status;
  610. char *
  611. command_generator (char *text, int state)
  612. {
  613.   vector vline;
  614.   static char **matched = NULL;
  615.   static int index = 0;
  616.   /* First call. */
  617.   if (! state)
  618.     {
  619.       index = 0;
  620.       if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
  621. return NULL;
  622.       vline = cmd_make_strvec (rl_line_buffer);
  623.       if (vline == NULL)
  624. return NULL;
  625.       if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
  626. vector_set (vline, '');
  627.       matched = cmd_complete_command (vline, vty, &complete_status);
  628.     }
  629.   if (matched && matched[index])
  630.     return matched[index++];
  631.   return NULL;
  632. }
  633. char **
  634. new_completion (char *text, int start, int end)
  635. {
  636.   char **matches;
  637.   matches = completion_matches (text, command_generator);
  638.   if (matches)
  639.     {
  640.       rl_point = rl_end;
  641.       if (complete_status == CMD_COMPLETE_FULL_MATCH)
  642. rl_pending_input = ' ';
  643.     }
  644.   return matches;
  645. }
  646. char **
  647. vtysh_completion (char *text, int start, int end)
  648. {
  649.   int ret;
  650.   vector vline;
  651.   char **matched = NULL;
  652.   if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
  653.     return NULL;
  654.   vline = cmd_make_strvec (rl_line_buffer);
  655.   if (vline == NULL)
  656.     return NULL;
  657.   /* In case of 'help t'. */
  658.   if (rl_end && isspace ((int) rl_line_buffer[rl_end - 1]))
  659.     vector_set (vline, '');
  660.   matched = cmd_complete_command (vline, vty, &ret);
  661.   cmd_free_strvec (vline);
  662.   return (char **) matched;
  663. }
  664. /* BGP node structure. */
  665. struct cmd_node bgp_node =
  666. {
  667.   BGP_NODE,
  668.   "%s(config-router)# ",
  669. };
  670. /* BGP node structure. */
  671. struct cmd_node rip_node =
  672. {
  673.   RIP_NODE,
  674.   "%s(config-router)# ",
  675. };
  676. struct cmd_node interface_node =
  677. {
  678.   INTERFACE_NODE,
  679.   "%s(config-if)# ",
  680. };
  681. DEFUNSH (VTYSH_BGPD,
  682.  router_bgp,
  683.  router_bgp_cmd,
  684.  "router bgp <1-65535>",
  685.  ROUTER_STR
  686.  BGP_STR
  687.  AS_STR)
  688. {
  689.   vty->node = BGP_NODE;
  690.   return CMD_SUCCESS;
  691. }
  692. DEFUNSH (VTYSH_BGPD,
  693.  address_family_vpnv4,
  694.  address_family_vpnv4_cmd,
  695.  "address-family vpnv4",
  696.  "Enter Address Family command moden"
  697.  "Address familyn")
  698. {
  699.   vty->node = BGP_VPNV4_NODE;
  700.   return CMD_SUCCESS;
  701. }
  702. DEFUNSH (VTYSH_BGPD,
  703.  address_family_vpnv4_unicast,
  704.  address_family_vpnv4_unicast_cmd,
  705.  "address-family vpnv4 unicast",
  706.  "Enter Address Family command moden"
  707.  "Address familyn"
  708.  "Address Family Modifiern")
  709. {
  710.   vty->node = BGP_VPNV4_NODE;
  711.   return CMD_SUCCESS;
  712. }
  713. DEFUNSH (VTYSH_BGPD,
  714.  address_family_ipv4_unicast,
  715.  address_family_ipv4_unicast_cmd,
  716.  "address-family ipv4 unicast",
  717.  "Enter Address Family command moden"
  718.  "Address familyn"
  719.  "Address Family Modifiern")
  720. {
  721.   vty->node = BGP_IPV4_NODE;
  722.   return CMD_SUCCESS;
  723. }
  724. DEFUNSH (VTYSH_BGPD,
  725.  address_family_ipv4,
  726.  address_family_ipv4_cmd,
  727.  "address-family ipv4",
  728.  "Enter Address Family command moden"
  729.  "Address familyn")
  730. {
  731.   vty->node = BGP_IPV4_NODE;
  732.   return CMD_SUCCESS;
  733. }
  734. DEFUNSH (VTYSH_BGPD,
  735.  address_family_ipv4_multicast,
  736.  address_family_ipv4_multicast_cmd,
  737.  "address-family ipv4 multicast",
  738.  "Enter Address Family command moden"
  739.  "Address familyn"
  740.  "Address Family Modifiern")
  741. {
  742.   vty->node = BGP_IPV4M_NODE;
  743.   return CMD_SUCCESS;
  744. }
  745. DEFUNSH (VTYSH_BGPD,
  746.  address_family_ipv6,
  747.  address_family_ipv6_cmd,
  748.  "address-family ipv6",
  749.  "Enter Address Family command moden"
  750.  "Address familyn")
  751. {
  752.   vty->node = BGP_IPV6_NODE;
  753.   return CMD_SUCCESS;
  754. }
  755. DEFUNSH (VTYSH_BGPD,
  756.  address_family_ipv6_unicast,
  757.  address_family_ipv6_unicast_cmd,
  758.  "address-family ipv6 unicast",
  759.  "Enter Address Family command moden"
  760.  "Address familyn"
  761.  "Address Family Modifiern")
  762. {
  763.   vty->node = BGP_IPV6_NODE;
  764.   return CMD_SUCCESS;
  765. }
  766. DEFUNSH (VTYSH_RIPD,
  767.  key_chain,
  768.  key_chain_cmd,
  769.  "key chain WORD",
  770.  "Authentication key managementn"
  771.  "Key-chain managementn"
  772.  "Key-chain namen")
  773. {
  774.   vty->node = KEYCHAIN_NODE;
  775.   return CMD_SUCCESS;
  776. }  
  777. DEFUNSH (VTYSH_RIPD,
  778.  key,
  779.  key_cmd,
  780.  "key <0-2147483647>",
  781.  "Configure a keyn"
  782.  "Key identifier numbern")
  783. {
  784.   vty->node = KEYCHAIN_KEY_NODE;
  785.   return CMD_SUCCESS;
  786. }
  787. DEFUNSH (VTYSH_RIPD,
  788.  router_rip,
  789.  router_rip_cmd,
  790.  "router rip",
  791.  ROUTER_STR
  792.  "RIP")
  793. {
  794.   vty->node = RIP_NODE;
  795.   return CMD_SUCCESS;
  796. }
  797. DEFUNSH (VTYSH_RIPNGD,
  798.  router_ripng,
  799.  router_ripng_cmd,
  800.  "router ripng",
  801.  ROUTER_STR
  802.  "RIPng")
  803. {
  804.   vty->node = RIPNG_NODE;
  805.   return CMD_SUCCESS;
  806. }
  807. DEFUNSH (VTYSH_OSPFD,
  808.  router_ospf,
  809.  router_ospf_cmd,
  810.  "router ospf",
  811.  "Enable a routing processn"
  812.  "Start OSPF configurationn")
  813. {
  814.   vty->node = OSPF_NODE;
  815.   return CMD_SUCCESS;
  816. }
  817. DEFUNSH (VTYSH_OSPF6D,
  818.  router_ospf6,
  819.  router_ospf6_cmd,
  820.  "router ospf6",
  821.  OSPF6_ROUTER_STR
  822.  OSPF6_STR)
  823. {
  824.   vty->node = OSPF6_NODE;
  825.   return CMD_SUCCESS;
  826. }
  827. DEFUNSH (VTYSH_RMAP,
  828.  route_map,
  829.  route_map_cmd,
  830.  "route-map WORD (deny|permit) <1-65535>",
  831.  "Create route-map or enter route-map command moden"
  832.  "Route map tagn"
  833.  "Route map denies set operationsn"
  834.  "Route map permits set operationsn"
  835.  "Sequence to insert to/delete from existing route-map entryn")
  836. {
  837.   vty->node = RMAP_NODE;
  838.   return CMD_SUCCESS;
  839. }
  840. /* Enable command */
  841. DEFUNSH (VTYSH_ALL,
  842.  vtysh_enable, 
  843.  vtysh_enable_cmd,
  844.  "enable",
  845.  "Turn on privileged mode commandn")
  846. {
  847.   vty->node = ENABLE_NODE;
  848.   return CMD_SUCCESS;
  849. }
  850. /* Disable command */
  851. DEFUNSH (VTYSH_ALL,
  852.  vtysh_disable, 
  853.  vtysh_disable_cmd,
  854.  "disable",
  855.  "Turn off privileged mode commandn")
  856. {
  857.   if (vty->node == ENABLE_NODE)
  858.     vty->node = VIEW_NODE;
  859.   return CMD_SUCCESS;
  860. }
  861. /* Configration from terminal */
  862. DEFUNSH (VTYSH_ALL,
  863.  vtysh_config_terminal,
  864.  vtysh_config_terminal_cmd,
  865.  "configure terminal",
  866.  "Configuration from vty interfacen"
  867.  "Configuration terminaln")
  868. {
  869.   vty->node = CONFIG_NODE;
  870.   return CMD_SUCCESS;
  871. }
  872. int
  873. vtysh_exit (struct vty *vty)
  874. {
  875.   switch (vty->node)
  876.     {
  877.     case VIEW_NODE:
  878.     case ENABLE_NODE:
  879.       exit (0);
  880.       break;
  881.     case CONFIG_NODE:
  882.       vty->node = ENABLE_NODE;
  883.       break;
  884.     case INTERFACE_NODE:
  885.     case ZEBRA_NODE:
  886.     case BGP_NODE:
  887.     case RIP_NODE:
  888.     case RIPNG_NODE:
  889.     case OSPF_NODE:
  890.     case OSPF6_NODE:
  891.     case MASC_NODE:
  892.     case RMAP_NODE:
  893.     case VTY_NODE:
  894.     case KEYCHAIN_NODE:
  895.       vty->node = CONFIG_NODE;
  896.       break;
  897.     case BGP_VPNV4_NODE:
  898.     case BGP_IPV4_NODE:
  899.     case BGP_IPV4M_NODE:
  900.     case BGP_IPV6_NODE:
  901.       vty->node = BGP_NODE;
  902.       break;
  903.     case KEYCHAIN_KEY_NODE:
  904.       vty->node = KEYCHAIN_NODE;
  905.       break;
  906.     default:
  907.       break;
  908.     }
  909.   return CMD_SUCCESS;
  910. }
  911. DEFUNSH (VTYSH_ALL,
  912.  vtysh_exit_all,
  913.  vtysh_exit_all_cmd,
  914.  "exit",
  915.  "Exit current mode and down to previous moden")
  916. {
  917.   return vtysh_exit (vty);
  918. }
  919. ALIAS (vtysh_exit_all,
  920.        vtysh_quit_all_cmd,
  921.        "quit",
  922.        "Exit current mode and down to previous moden");
  923. DEFUNSH (VTYSH_BGPD,
  924.  exit_address_family,
  925.  exit_address_family_cmd,
  926.  "exit-address-family",
  927.  "Exit from Address Family configuration moden")
  928. {
  929.   if (vty->node == BGP_IPV4_NODE
  930.       || vty->node == BGP_IPV4M_NODE
  931.       || vty->node == BGP_VPNV4_NODE
  932.       || vty->node == BGP_IPV6_NODE)
  933.     vty->node = BGP_NODE;
  934.   return CMD_SUCCESS;
  935. }
  936. DEFUNSH (VTYSH_ZEBRA,
  937.  vtysh_exit_zebra,
  938.  vtysh_exit_zebra_cmd,
  939.  "exit",
  940.  "Exit current mode and down to previous moden")
  941. {
  942.   return vtysh_exit (vty);
  943. }
  944. ALIAS (vtysh_exit_zebra,
  945.        vtysh_quit_zebra_cmd,
  946.        "quit",
  947.        "Exit current mode and down to previous moden");
  948. DEFUNSH (VTYSH_RIPD,
  949.  vtysh_exit_ripd,
  950.  vtysh_exit_ripd_cmd,
  951.  "exit",
  952.  "Exit current mode and down to previous moden")
  953. {
  954.   return vtysh_exit (vty);
  955. }
  956. ALIAS (vtysh_exit_ripd,
  957.        vtysh_quit_ripd_cmd,
  958.        "quit",
  959.        "Exit current mode and down to previous moden");
  960. DEFUNSH (VTYSH_RIPNGD,
  961.     vtysh_exit_ripngd,
  962.     vtysh_exit_ripngd_cmd,
  963.     "exit",
  964.     "Exit current mode and down to previous moden")
  965. {
  966.   return vtysh_exit (vty);
  967. }
  968. ALIAS (vtysh_exit_ripngd,
  969.        vtysh_quit_ripngd_cmd,
  970.        "quit",
  971.        "Exit current mode and down to previous moden");
  972. DEFUNSH (VTYSH_RMAP,
  973.  vtysh_exit_rmap,
  974.  vtysh_exit_rmap_cmd,
  975.  "exit",
  976.  "Exit current mode and down to previous moden")
  977. {
  978.   return vtysh_exit (vty);
  979. }
  980. ALIAS (vtysh_exit_rmap,
  981.        vtysh_quit_rmap_cmd,
  982.        "quit",
  983.        "Exit current mode and down to previous moden");
  984. DEFUNSH (VTYSH_BGPD,
  985.  vtysh_exit_bgpd,
  986.  vtysh_exit_bgpd_cmd,
  987.  "exit",
  988.  "Exit current mode and down to previous moden")
  989. {
  990.   return vtysh_exit (vty);
  991. }
  992. ALIAS (vtysh_exit_bgpd,
  993.        vtysh_quit_bgpd_cmd,
  994.        "quit",
  995.        "Exit current mode and down to previous moden");
  996. DEFUNSH (VTYSH_OSPFD,
  997.  vtysh_exit_ospfd,
  998.  vtysh_exit_ospfd_cmd,
  999.  "exit",
  1000.  "Exit current mode and down to previous moden")
  1001. {
  1002.   return vtysh_exit (vty);
  1003. }
  1004. ALIAS (vtysh_exit_ospfd,
  1005.        vtysh_quit_ospfd_cmd,
  1006.        "quit",
  1007.        "Exit current mode and down to previous moden");
  1008. DEFUNSH (VTYSH_OSPF6D,
  1009.     vtysh_exit_ospf6d,
  1010.     vtysh_exit_ospf6d_cmd,
  1011.     "exit",
  1012.     "Exit current mode and down to previous moden")
  1013. {
  1014.   return vtysh_exit (vty);
  1015. }
  1016. ALIAS (vtysh_exit_ospf6d,
  1017.        vtysh_quit_ospf6d_cmd,
  1018.        "quit",
  1019.        "Exit current mode and down to previous moden");
  1020. DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D,
  1021.  vtysh_interface,
  1022.  vtysh_interface_cmd,
  1023.  "interface IFNAME",
  1024.  "Select an interface to configuren"
  1025.  "Interface's namen")
  1026. {
  1027.   vty->node = INTERFACE_NODE;
  1028.   return CMD_SUCCESS;
  1029. }
  1030. DEFUNSH (VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D,
  1031.  vtysh_exit_interface,
  1032.  vtysh_exit_interface_cmd,
  1033.  "exit",
  1034.  "Exit current mode and down to previous moden")
  1035. {
  1036.   return vtysh_exit (vty);
  1037. }
  1038. ALIAS (vtysh_exit_interface,
  1039.        vtysh_quit_interface_cmd,
  1040.        "quit",
  1041.        "Exit current mode and down to previous moden");
  1042. DEFUN (vtysh_write_terminal,
  1043.        vtysh_write_terminal_cmd,
  1044.        "write terminal",
  1045.        "Write running configuration to memory, network, or terminaln"
  1046.        "Write to terminaln")
  1047. {
  1048.   int ret;
  1049.   char line[] = "write terminaln";
  1050.   FILE *fp = NULL;
  1051.   if (vtysh_pager_name)
  1052.     {
  1053.       fp = popen ("more", "w");
  1054.       if (fp == NULL)
  1055. {
  1056.   perror ("popen");
  1057.   exit (1);
  1058. }
  1059.     }
  1060.   else
  1061.     fp = stdout;
  1062.   vty_out (vty, "Building configuration...%s", VTY_NEWLINE);
  1063.   vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
  1064.    VTY_NEWLINE);
  1065.   vtysh_config_write (fp);
  1066.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_ZEBRA], line);
  1067.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIP], line);
  1068.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIPNG], line);
  1069.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF], line);
  1070.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF6], line);
  1071.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_BGP], line);
  1072.   vtysh_config_dump (fp);
  1073.   if (vtysh_pager_name && fp)
  1074.     {
  1075.       fflush (fp);
  1076.       if (pclose (fp) == -1)
  1077. {
  1078.   perror ("pclose");
  1079.   exit (1);
  1080. }
  1081.       fp = NULL;
  1082.     }
  1083.   return CMD_SUCCESS;
  1084. }
  1085. DEFUN (vtysh_write_memory,
  1086.        vtysh_write_memory_cmd,
  1087.        "write memory",
  1088.        "Write running configuration to memory, network, or terminaln"
  1089.        "Write configuration to the file (same as write file)n")
  1090. {
  1091.   int ret;
  1092.   mode_t old_umask;
  1093.   char line[] = "write terminaln";
  1094.   FILE *fp;
  1095.   char *integrate_sav = NULL;
  1096.   /* config files have 0600 perms... */ 
  1097.   old_umask = umask (0077);
  1098.   integrate_sav = malloc (strlen (integrate_default) 
  1099.     + strlen (CONF_BACKUP_EXT) + 1);
  1100.   strcpy (integrate_sav, integrate_default);
  1101.   strcat (integrate_sav, CONF_BACKUP_EXT);
  1102.   printf ("Building Configuration...n");
  1103.   /* Move current configuration file to backup config file */
  1104.   unlink (integrate_sav);
  1105.   rename (integrate_default, integrate_sav);
  1106.   fp = fopen (integrate_default, "w");
  1107.   if (fp == NULL)
  1108.     {
  1109.       printf ("%% Can't open configuration file %s.n", integrate_default);
  1110.       umask (old_umask);
  1111.       return CMD_SUCCESS;
  1112.     }
  1113.   else
  1114.     printf ("[OK]n");
  1115.   
  1116.   vtysh_config_write (fp);
  1117.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_ZEBRA], line);
  1118.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIP], line);
  1119.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_RIPNG], line);
  1120.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF], line);
  1121.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_OSPF6], line);
  1122.   ret = vtysh_client_config (&vtysh_client[VTYSH_INDEX_BGP], line);
  1123.   vtysh_config_dump (fp);
  1124.   fclose (fp);
  1125.   umask (old_umask);
  1126.   return CMD_SUCCESS;
  1127. }
  1128. ALIAS (vtysh_write_memory,
  1129.        vtysh_copy_runningconfig_startupconfig_cmd,
  1130.        "copy running-config startup-config",  
  1131.        "Copy from one file to anothern"
  1132.        "Copy from current system configurationn"
  1133.        "Copy to startup configurationn");
  1134. ALIAS (vtysh_write_memory,
  1135.        vtysh_write_file_cmd,
  1136.        "write file",
  1137.        "Write running configuration to memory, network, or terminaln"
  1138.        "Write configuration to the file (same as write memory)n");
  1139. ALIAS (vtysh_write_terminal,
  1140.        vtysh_show_running_config_cmd,
  1141.        "show running-config",
  1142.        SHOW_STR
  1143.        "Current operating configurationn");
  1144. /* Execute command in child process. */
  1145. int
  1146. execute_command (char *command, int argc, char *arg1, char *arg2)
  1147. {
  1148.   int ret;
  1149.   pid_t pid;
  1150.   int status;
  1151.   /* Call fork(). */
  1152.   pid = fork ();
  1153.   if (pid < 0)
  1154.     {
  1155.       /* Failure of fork(). */
  1156.       fprintf (stderr, "Can't fork: %sn", strerror (errno));
  1157.       exit (1);
  1158.     }
  1159.   else if (pid == 0)
  1160.     {
  1161.       /* This is child process. */
  1162.       switch (argc)
  1163. {
  1164. case 0:
  1165.   ret = execlp (command, command, NULL);
  1166.   break;
  1167. case 1:
  1168.   ret = execlp (command, command, arg1, NULL);
  1169.   break;
  1170. case 2:
  1171.   ret = execlp (command, command, arg1, arg2, NULL);
  1172.   break;
  1173. }
  1174.       /* When execlp suceed, this part is not executed. */
  1175.       fprintf (stderr, "Can't execute %s: %sn", command, strerror (errno));
  1176.       exit (1);
  1177.     }
  1178.   else
  1179.     {
  1180.       /* This is parent. */
  1181.       execute_flag = 1;
  1182.       ret = wait4 (pid, &status, 0, NULL);
  1183.       execute_flag = 0;
  1184.     }
  1185.   return 0;
  1186. }
  1187. DEFUN (vtysh_ping,
  1188.        vtysh_ping_cmd,
  1189.        "ping WORD",
  1190.        "send echo messagesn"
  1191.        "Ping destination address or hostnamen")
  1192. {
  1193.   execute_command ("ping", 1, argv[0], NULL);
  1194.   return CMD_SUCCESS;
  1195. }
  1196. DEFUN (vtysh_traceroute,
  1197.        vtysh_traceroute_cmd,
  1198.        "traceroute WORD",
  1199.        "Trace route to destinationn"
  1200.        "Trace route to destination address or hostnamen")
  1201. {
  1202.   execute_command ("traceroute", 1, argv[0], NULL);
  1203.   return CMD_SUCCESS;
  1204. }
  1205. DEFUN (vtysh_telnet,
  1206.        vtysh_telnet_cmd,
  1207.        "telnet WORD",
  1208.        "Open a telnet connectionn"
  1209.        "IP address or hostname of a remote systemn")
  1210. {
  1211.   execute_command ("telnet", 1, argv[0], NULL);
  1212.   return CMD_SUCCESS;
  1213. }
  1214. DEFUN (vtysh_telnet_port,
  1215.        vtysh_telnet_port_cmd,
  1216.        "telnet WORD PORT",
  1217.        "Open a telnet connectionn"
  1218.        "IP address or hostname of a remote systemn"
  1219.        "TCP Port numbern")
  1220. {
  1221.   execute_command ("telnet", 2, argv[0], argv[1]);
  1222.   return CMD_SUCCESS;
  1223. }
  1224. DEFUN (vtysh_start_shell,
  1225.        vtysh_start_shell_cmd,
  1226.        "start-shell",
  1227.        "Start UNIX shelln")
  1228. {
  1229.   execute_command ("sh", 0, NULL, NULL);
  1230.   return CMD_SUCCESS;
  1231. }
  1232. DEFUN (vtysh_start_bash,
  1233.        vtysh_start_bash_cmd,
  1234.        "start-shell bash",
  1235.        "Start UNIX shelln"
  1236.        "Start bashn")
  1237. {
  1238.   execute_command ("bash", 0, NULL, NULL);
  1239.   return CMD_SUCCESS;
  1240. }
  1241. DEFUN (vtysh_start_zsh,
  1242.        vtysh_start_zsh_cmd,
  1243.        "start-shell zsh",
  1244.        "Start UNIX shelln"
  1245.        "Start Z shelln")
  1246. {
  1247.   execute_command ("zsh", 0, NULL, NULL);
  1248.   return CMD_SUCCESS;
  1249. }
  1250. /* Route map node structure. */
  1251. struct cmd_node rmap_node =
  1252. {
  1253.   RMAP_NODE,
  1254.   "%s(config-route-map)# "
  1255. };
  1256. /* Zebra node structure. */
  1257. struct cmd_node zebra_node =
  1258. {
  1259.   ZEBRA_NODE,
  1260.   "%s(config-router)# "
  1261. };
  1262. struct cmd_node bgp_vpnv4_node =
  1263. {
  1264.   BGP_VPNV4_NODE,
  1265.   "%s(config-router-af)# "
  1266. };
  1267. struct cmd_node bgp_ipv4_node =
  1268. {
  1269.   BGP_IPV4_NODE,
  1270.   "%s(config-router-af)# "
  1271. };
  1272. struct cmd_node bgp_ipv4m_node =
  1273. {
  1274.   BGP_IPV4M_NODE,
  1275.   "%s(config-router-af)# "
  1276. };
  1277. struct cmd_node bgp_ipv6_node =
  1278. {
  1279.   BGP_IPV6_NODE,
  1280.   "%s(config-router-af)# "
  1281. };
  1282. struct cmd_node ospf_node =
  1283. {
  1284.   OSPF_NODE,
  1285.   "%s(config-router)# "
  1286. };
  1287. /* RIPng node structure. */
  1288. struct cmd_node ripng_node =
  1289. {
  1290.   RIPNG_NODE,
  1291.   "%s(config-router)# "
  1292. };
  1293. /* OSPF6 node structure. */
  1294. struct cmd_node ospf6_node =
  1295. {
  1296.   OSPF6_NODE,
  1297.   "%s(config-ospf6)# "
  1298. };
  1299. struct cmd_node keychain_node =
  1300. {
  1301.   KEYCHAIN_NODE,
  1302.   "%s(config-keychain)# "
  1303. };
  1304. struct cmd_node keychain_key_node =
  1305. {
  1306.   KEYCHAIN_KEY_NODE,
  1307.   "%s(config-keychain-key)# "
  1308. };
  1309. void
  1310. vtysh_install_default (enum node_type node)
  1311. {
  1312.   install_element (node, &config_list_cmd);
  1313. }
  1314. /* Making connection to protocol daemon. */
  1315. int
  1316. vtysh_connect (struct vtysh_client *vclient, char *path)
  1317. {
  1318.   int ret;
  1319.   int sock, len;
  1320.   struct sockaddr_un addr;
  1321.   struct stat s_stat;
  1322.   uid_t euid;
  1323.   gid_t egid;
  1324.   memset (vclient, 0, sizeof (struct vtysh_client));
  1325.   vclient->fd = -1;
  1326.   /* Stat socket to see if we have permission to access it. */
  1327.   euid = geteuid();
  1328.   egid = getegid();
  1329.   ret = stat (path, &s_stat);
  1330.   if (ret < 0 && errno != ENOENT)
  1331.     {
  1332.       fprintf  (stderr, "vtysh_connect(%s): stat = %sn", 
  1333. path, strerror(errno)); 
  1334.       exit(1);
  1335.     }
  1336.   
  1337.   if (ret >= 0)
  1338.     {
  1339.       if (! S_ISSOCK(s_stat.st_mode))
  1340. {
  1341.   fprintf (stderr, "vtysh_connect(%s): Not a socketn",
  1342.    path);
  1343.   exit (1);
  1344. }
  1345.       
  1346.       if (euid != s_stat.st_uid 
  1347.   || !(s_stat.st_mode & S_IWUSR)
  1348.   || !(s_stat.st_mode & S_IRUSR))
  1349. {
  1350.   fprintf (stderr, "vtysh_connect(%s): No permission to access socketn",
  1351.    path);
  1352.   exit (1);
  1353. }
  1354.     }
  1355.   sock = socket (AF_UNIX, SOCK_STREAM, 0);
  1356.   if (sock < 0)
  1357.     {
  1358. #ifdef DEBUG
  1359.       fprintf(stderr, "vtysh_connect(%s): socket = %sn", path, strerror(errno));
  1360. #endif /* DEBUG */
  1361.       return -1;
  1362.     }
  1363.   memset (&addr, 0, sizeof (struct sockaddr_un));
  1364.   addr.sun_family = AF_UNIX;
  1365.   strncpy (addr.sun_path, path, strlen (path));
  1366. #ifdef HAVE_SUN_LEN
  1367.   len = addr.sun_len = SUN_LEN(&addr);
  1368. #else
  1369.   len = sizeof (addr.sun_family) + strlen (addr.sun_path);
  1370. #endif /* HAVE_SUN_LEN */
  1371.   ret = connect (sock, (struct sockaddr *) &addr, len);
  1372.   if (ret < 0)
  1373.     {
  1374. #ifdef DEBUG
  1375.       fprintf(stderr, "vtysh_connect(%s): connect = %sn", path, strerror(errno));
  1376. #endif /* DEBUG */
  1377.       close (sock);
  1378.       return -1;
  1379.     }
  1380.   vclient->fd = sock;
  1381.   return 0;
  1382. }
  1383. void
  1384. vtysh_connect_all()
  1385. {
  1386.   /* Clear each daemons client structure. */
  1387.   vtysh_connect (&vtysh_client[VTYSH_INDEX_ZEBRA], ZEBRA_PATH);
  1388.   vtysh_connect (&vtysh_client[VTYSH_INDEX_RIP], RIP_PATH);
  1389.   vtysh_connect (&vtysh_client[VTYSH_INDEX_RIPNG], RIPNG_PATH);
  1390.   vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF], OSPF_PATH);
  1391.   vtysh_connect (&vtysh_client[VTYSH_INDEX_OSPF6], OSPF6_PATH);
  1392.   vtysh_connect (&vtysh_client[VTYSH_INDEX_BGP], BGP_PATH);
  1393. }
  1394. /* To disable readline's filename completion */
  1395. int
  1396. vtysh_completion_entry_function (int ignore, int invoking_key)
  1397. {
  1398.   return 0;
  1399. }
  1400. void
  1401. vtysh_readline_init ()
  1402. {
  1403.   /* readline related settings. */
  1404.   rl_bind_key ('?', vtysh_rl_describe);
  1405.   rl_completion_entry_function = vtysh_completion_entry_function;
  1406.   rl_attempted_completion_function = (CPPFunction *)new_completion;
  1407.   /* do not append space after completion. It will be appended
  1408.      in new_completion() function explicitly */
  1409.   rl_completion_append_character = '';
  1410. }
  1411. char *
  1412. vtysh_prompt ()
  1413. {
  1414.   struct utsname names;
  1415.   static char buf[100];
  1416.   const char*hostname;
  1417.   extern struct host host;
  1418.   hostname = host.name;
  1419.   if (!hostname)
  1420.     {
  1421.       uname (&names);
  1422.       hostname = names.nodename;
  1423.     }
  1424.   snprintf (buf, sizeof buf, cmd_prompt (vty->node), hostname);
  1425.   return buf;
  1426. }
  1427. void
  1428. vtysh_init_vty ()
  1429. {
  1430.   /* Make vty structure. */
  1431.   vty = vty_new ();
  1432.   vty->type = VTY_SHELL;
  1433.   vty->node = VIEW_NODE;
  1434.   /* Initialize commands. */
  1435.   cmd_init (0);
  1436.   /* Install nodes. */
  1437.   install_node (&bgp_node, NULL);
  1438.   install_node (&rip_node, NULL);
  1439.   install_node (&interface_node, NULL);
  1440.   install_node (&rmap_node, NULL);
  1441.   install_node (&zebra_node, NULL);
  1442.   install_node (&bgp_vpnv4_node, NULL);
  1443.   install_node (&bgp_ipv4_node, NULL);
  1444.   install_node (&bgp_ipv4m_node, NULL);
  1445. /* #ifdef HAVE_IPV6 */
  1446.   install_node (&bgp_ipv6_node, NULL);
  1447. /* #endif */
  1448.   install_node (&ospf_node, NULL);
  1449. /* #ifdef HAVE_IPV6 */
  1450.   install_node (&ripng_node, NULL);
  1451.   install_node (&ospf6_node, NULL);
  1452. /* #endif */
  1453.   install_node (&keychain_node, NULL);
  1454.   install_node (&keychain_key_node, NULL);
  1455.   vtysh_install_default (VIEW_NODE);
  1456.   vtysh_install_default (ENABLE_NODE);
  1457.   vtysh_install_default (CONFIG_NODE);
  1458.   vtysh_install_default (BGP_NODE);
  1459.   vtysh_install_default (RIP_NODE);
  1460.   vtysh_install_default (INTERFACE_NODE);
  1461.   vtysh_install_default (RMAP_NODE);
  1462.   vtysh_install_default (ZEBRA_NODE);
  1463.   vtysh_install_default (BGP_VPNV4_NODE);
  1464.   vtysh_install_default (BGP_IPV4_NODE);
  1465.   vtysh_install_default (BGP_IPV4M_NODE);
  1466.   vtysh_install_default (BGP_IPV6_NODE);
  1467.   vtysh_install_default (OSPF_NODE);
  1468.   vtysh_install_default (RIPNG_NODE);
  1469.   vtysh_install_default (OSPF6_NODE);
  1470.   vtysh_install_default (KEYCHAIN_NODE);
  1471.   vtysh_install_default (KEYCHAIN_KEY_NODE);
  1472.   install_element (VIEW_NODE, &vtysh_enable_cmd);
  1473.   install_element (ENABLE_NODE, &vtysh_config_terminal_cmd);
  1474.   install_element (ENABLE_NODE, &vtysh_disable_cmd);
  1475.   /* "exit" command. */
  1476.   install_element (VIEW_NODE, &vtysh_exit_all_cmd);
  1477.   install_element (VIEW_NODE, &vtysh_quit_all_cmd);
  1478.   install_element (CONFIG_NODE, &vtysh_exit_all_cmd);
  1479.   /* install_element (CONFIG_NODE, &vtysh_quit_all_cmd); */
  1480.   install_element (ENABLE_NODE, &vtysh_exit_all_cmd);
  1481.   install_element (ENABLE_NODE, &vtysh_quit_all_cmd);
  1482.   install_element (RIP_NODE, &vtysh_exit_ripd_cmd);
  1483.   install_element (RIP_NODE, &vtysh_quit_ripd_cmd);
  1484.   install_element (RIPNG_NODE, &vtysh_exit_ripngd_cmd);
  1485.   install_element (RIPNG_NODE, &vtysh_quit_ripngd_cmd);
  1486.   install_element (OSPF_NODE, &vtysh_exit_ospfd_cmd);
  1487.   install_element (OSPF_NODE, &vtysh_quit_ospfd_cmd);
  1488.   install_element (OSPF6_NODE, &vtysh_exit_ospf6d_cmd);
  1489.   install_element (OSPF6_NODE, &vtysh_quit_ospf6d_cmd);
  1490.   install_element (BGP_NODE, &vtysh_exit_bgpd_cmd);
  1491.   install_element (BGP_NODE, &vtysh_quit_bgpd_cmd);
  1492.   install_element (BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd);
  1493.   install_element (BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd);
  1494.   install_element (BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd);
  1495.   install_element (BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd);
  1496.   install_element (BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd);
  1497.   install_element (BGP_IPV4M_NODE, &vtysh_quit_bgpd_cmd);
  1498.   install_element (BGP_IPV6_NODE, &vtysh_exit_bgpd_cmd);
  1499.   install_element (BGP_IPV6_NODE, &vtysh_quit_bgpd_cmd);
  1500.   install_element (KEYCHAIN_NODE, &vtysh_exit_ripd_cmd);
  1501.   install_element (KEYCHAIN_NODE, &vtysh_quit_ripd_cmd);
  1502.   install_element (KEYCHAIN_KEY_NODE, &vtysh_exit_ripd_cmd);
  1503.   install_element (KEYCHAIN_KEY_NODE, &vtysh_quit_ripd_cmd);
  1504.   install_element (RMAP_NODE, &vtysh_exit_rmap_cmd);
  1505.   install_element (RMAP_NODE, &vtysh_quit_rmap_cmd);
  1506.   /* "end" command. */
  1507.   install_element (CONFIG_NODE, &vtysh_end_all_cmd);
  1508.   install_element (ENABLE_NODE, &vtysh_end_all_cmd);
  1509.   install_element (RIP_NODE, &vtysh_end_all_cmd);
  1510.   install_element (RIPNG_NODE, &vtysh_end_all_cmd);
  1511.   install_element (OSPF_NODE, &vtysh_end_all_cmd);
  1512.   install_element (OSPF6_NODE, &vtysh_end_all_cmd);
  1513.   install_element (BGP_NODE, &vtysh_end_all_cmd);
  1514.   install_element (BGP_IPV4_NODE, &vtysh_end_all_cmd);
  1515.   install_element (BGP_IPV4M_NODE, &vtysh_end_all_cmd);
  1516.   install_element (BGP_VPNV4_NODE, &vtysh_end_all_cmd);
  1517.   install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd);
  1518.   install_element (KEYCHAIN_NODE, &vtysh_end_all_cmd);
  1519.   install_element (KEYCHAIN_KEY_NODE, &vtysh_end_all_cmd);
  1520.   install_element (RMAP_NODE, &vtysh_end_all_cmd);
  1521.   install_element (INTERFACE_NODE, &vtysh_end_all_cmd);
  1522.   install_element (INTERFACE_NODE, &vtysh_exit_interface_cmd);
  1523.   install_element (INTERFACE_NODE, &vtysh_quit_interface_cmd);
  1524.   install_element (CONFIG_NODE, &router_rip_cmd);
  1525. #ifdef HAVE_IPV6
  1526.   install_element (CONFIG_NODE, &router_ripng_cmd);
  1527. #endif
  1528.   install_element (CONFIG_NODE, &router_ospf_cmd);
  1529. #ifdef HAVE_IPV6
  1530.   install_element (CONFIG_NODE, &router_ospf6_cmd);
  1531. #endif
  1532.   install_element (CONFIG_NODE, &router_bgp_cmd);
  1533.   install_element (BGP_NODE, &address_family_vpnv4_cmd);
  1534.   install_element (BGP_NODE, &address_family_vpnv4_unicast_cmd);
  1535.   install_element (BGP_NODE, &address_family_ipv4_cmd);
  1536.   install_element (BGP_NODE, &address_family_ipv4_unicast_cmd);
  1537.   install_element (BGP_NODE, &address_family_ipv4_multicast_cmd);
  1538. #ifdef HAVE_IPV6
  1539.   install_element (BGP_NODE, &address_family_ipv6_cmd);
  1540.   install_element (BGP_NODE, &address_family_ipv6_unicast_cmd);
  1541. #endif
  1542.   install_element (BGP_VPNV4_NODE, &exit_address_family_cmd);
  1543.   install_element (BGP_IPV4_NODE, &exit_address_family_cmd);
  1544.   install_element (BGP_IPV4M_NODE, &exit_address_family_cmd);
  1545.   install_element (BGP_IPV6_NODE, &exit_address_family_cmd);
  1546.   install_element (CONFIG_NODE, &key_chain_cmd);
  1547.   install_element (CONFIG_NODE, &route_map_cmd);
  1548.   install_element (KEYCHAIN_NODE, &key_cmd);
  1549.   install_element (KEYCHAIN_NODE, &key_chain_cmd);
  1550.   install_element (KEYCHAIN_KEY_NODE, &key_chain_cmd);
  1551.   install_element (CONFIG_NODE, &vtysh_interface_cmd);
  1552.   install_element (ENABLE_NODE, &vtysh_show_running_config_cmd);
  1553.   install_element (ENABLE_NODE, &vtysh_copy_runningconfig_startupconfig_cmd);
  1554.   install_element (ENABLE_NODE, &vtysh_write_file_cmd);
  1555.   /* write terminal command */
  1556.   install_element (ENABLE_NODE, &vtysh_write_terminal_cmd);
  1557.   install_element (CONFIG_NODE, &vtysh_write_terminal_cmd);
  1558.   install_element (BGP_NODE, &vtysh_write_terminal_cmd);
  1559.   install_element (BGP_VPNV4_NODE, &vtysh_write_terminal_cmd);
  1560.   install_element (BGP_IPV4_NODE, &vtysh_write_terminal_cmd);
  1561.   install_element (BGP_IPV4M_NODE, &vtysh_write_terminal_cmd);
  1562.   install_element (BGP_IPV6_NODE, &vtysh_write_terminal_cmd);
  1563.   install_element (RIP_NODE, &vtysh_write_terminal_cmd);
  1564.   install_element (RIPNG_NODE, &vtysh_write_terminal_cmd);
  1565.   install_element (OSPF_NODE, &vtysh_write_terminal_cmd);
  1566.   install_element (OSPF6_NODE, &vtysh_write_terminal_cmd);
  1567.   install_element (INTERFACE_NODE, &vtysh_write_terminal_cmd);
  1568.   install_element (RMAP_NODE, &vtysh_write_terminal_cmd);
  1569.   install_element (KEYCHAIN_NODE, &vtysh_write_terminal_cmd);
  1570.   install_element (KEYCHAIN_KEY_NODE, &vtysh_write_terminal_cmd);
  1571.   /* write memory command */
  1572.   install_element (ENABLE_NODE, &vtysh_write_memory_cmd);
  1573.   install_element (CONFIG_NODE, &vtysh_write_memory_cmd);
  1574.   install_element (BGP_NODE, &vtysh_write_memory_cmd);
  1575.   install_element (BGP_VPNV4_NODE, &vtysh_write_memory_cmd);
  1576.   install_element (BGP_IPV4_NODE, &vtysh_write_memory_cmd);
  1577.   install_element (BGP_IPV4M_NODE, &vtysh_write_memory_cmd);
  1578.   install_element (BGP_IPV6_NODE, &vtysh_write_memory_cmd);
  1579.   install_element (RIP_NODE, &vtysh_write_memory_cmd);
  1580.   install_element (RIPNG_NODE, &vtysh_write_memory_cmd);
  1581.   install_element (OSPF_NODE, &vtysh_write_memory_cmd);
  1582.   install_element (OSPF6_NODE, &vtysh_write_memory_cmd);
  1583.   install_element (INTERFACE_NODE, &vtysh_write_memory_cmd);
  1584.   install_element (RMAP_NODE, &vtysh_write_memory_cmd);
  1585.   install_element (KEYCHAIN_NODE, &vtysh_write_memory_cmd);
  1586.   install_element (KEYCHAIN_KEY_NODE, &vtysh_write_memory_cmd);
  1587.   install_element (VIEW_NODE, &vtysh_ping_cmd);
  1588.   install_element (VIEW_NODE, &vtysh_traceroute_cmd);
  1589.   install_element (VIEW_NODE, &vtysh_telnet_cmd);
  1590.   install_element (VIEW_NODE, &vtysh_telnet_port_cmd);
  1591.   install_element (ENABLE_NODE, &vtysh_ping_cmd);
  1592.   install_element (ENABLE_NODE, &vtysh_traceroute_cmd);
  1593.   install_element (ENABLE_NODE, &vtysh_telnet_cmd);
  1594.   install_element (ENABLE_NODE, &vtysh_telnet_port_cmd);
  1595.   install_element (ENABLE_NODE, &vtysh_start_shell_cmd);
  1596.   install_element (ENABLE_NODE, &vtysh_start_bash_cmd);
  1597.   install_element (ENABLE_NODE, &vtysh_start_zsh_cmd);
  1598.   install_element (CONFIG_NODE, &vtysh_log_stdout_cmd);
  1599.   install_element (CONFIG_NODE, &no_vtysh_log_stdout_cmd);
  1600.   install_element (CONFIG_NODE, &vtysh_log_file_cmd);
  1601.   install_element (CONFIG_NODE, &no_vtysh_log_file_cmd);
  1602.   install_element (CONFIG_NODE, &vtysh_log_syslog_cmd);
  1603.   install_element (CONFIG_NODE, &no_vtysh_log_syslog_cmd);
  1604.   install_element (CONFIG_NODE, &vtysh_log_trap_cmd);
  1605.   install_element (CONFIG_NODE, &no_vtysh_log_trap_cmd);
  1606.   install_element (CONFIG_NODE, &vtysh_log_record_priority_cmd);
  1607.   install_element (CONFIG_NODE, &no_vtysh_log_record_priority_cmd);
  1608. }