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