2 * Virtual terminal [aka TeletYpe] interface routine.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29 #include "sockunion.h"
37 #if defined(BRCM_CMD_SUPPORT)
51 static void vty_event (enum event, int, struct vty *);
52 #endif /* BRCM_CMD_SUPPORT */
54 /* Extern host structure from command.c */
55 extern struct host host;
57 /* Vector which store each vty structure. */
60 #if defined(BRCM_CMD_SUPPORT)
61 /* Vty timeout value. */
62 static unsigned long vty_timeout_val = VTY_TIMEOUT_DEFAULT;
64 /* Vty access-class command */
65 static char *vty_accesslist_name = NULL;
66 #endif /* BRCM_CMD_SUPPORT */
69 /* Vty access-calss for IPv6. */
70 static char *vty_ipv6_accesslist_name = NULL;
73 /* VTY server thread. */
74 vector Vvty_serv_thread;
76 #if defined(BRCM_CMD_SUPPORT)
77 /* Current directory. */
82 static int vty_config;
83 #if defined(BRCM_CMD_SUPPORT)
84 /* Login password check. */
85 static int no_password_check = 0;
87 /* Integrated configuration file path */
88 char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
89 #endif /* BRCM_CMD_SUPPORT */
92 /* VTY standard output function. */
94 #if defined(BRCM_CMD_SUPPORT)
96 vty_out (struct vty *vty, const char *format, ...)
104 va_start (args, format);
107 vprintf (format, args);
110 /* Try to write to initial buffer. */
111 len = vsnprintf (buf, sizeof buf, format, args);
113 /* Initial buffer is not enough. */
114 if (len < 0 || len >= size)
123 p = XREALLOC (MTYPE_VTY_OUT_BUF, p, size);
127 len = vsnprintf (p, size, format, args);
129 if (len > -1 && len < size)
134 /* When initial buffer is enough to store all output. */
138 /* Pointer p must point out buffer. */
139 if (vty_shell_serv (vty))
140 write (vty->fd, (u_char *) p, len);
142 buffer_write (vty->obuf, (u_char *) p, len);
144 /* If p is not different with buf, it is allocated buffer. */
146 XFREE (MTYPE_VTY_OUT_BUF, p);
153 #else /* BRCM_CMD_SUPPORT */
155 vty_out (struct vty *vty, const char *format, ...)
159 #endif /* BRCM_CMD_SUPPORT */
161 #if defined(BRCM_RIP_DEBUG) || defined(BRCM_CMD_SUPPORT)
163 vvty_out (struct vty *vty, const char *format, va_list va)
166 /* XXX need overflow check */
169 len = vsnprintf (buf, sizeof buf, format, va);
173 #ifdef BRCM_RIP_DEBUG
174 zlog (NULL, LOG_INFO, "Vty closed due to vty output buffer shortage.");
179 buffer_write (vty->obuf, (u_char *)buf, len);
182 #endif /* defined(BRCM_RIP_DEBUG) || defined(BRCM_CMD_SUPPORT) */
184 #if defined(BRCM_CMD_SUPPORT) || defined(BRCM_RIP_DEBUG)
185 /* Output current time to the vty. */
187 vty_time_print (struct vty *vty, int cr)
196 tm = localtime (&clock);
198 ret = strftime (buf, TIME_BUF, "%Y/%m/%d %H:%M:%S", tm);
201 #ifdef BRCM_RIP_DEBUG
202 zlog (NULL, LOG_INFO, "strftime error");
207 vty_out (vty, "%s\n", buf);
209 vty_out (vty, "%s ", buf);
213 #endif /* || defined(BRCM_RIP_DEBUG) */
215 #if defined(BRCM_CMD_SUPPORT)
216 /* Say hello to vty interface. */
218 vty_hello (struct vty *vty)
221 vty_out (vty, host.motd);
224 /* Put out prompt and wait input from user. */
226 vty_prompt (struct vty *vty)
228 struct utsname names;
231 if (vty->type == VTY_TERM)
233 hostname = host.name;
237 hostname = names.nodename;
239 vty_out (vty, cmd_prompt (vty->node), hostname);
243 /* Send WILL TELOPT_ECHO to remote server. */
245 vty_will_echo (struct vty *vty)
247 char cmd[] = { IAC, WILL, TELOPT_ECHO, '\0' };
248 vty_out (vty, "%s", cmd);
251 /* Make suppress Go-Ahead telnet option. */
253 vty_will_suppress_go_ahead (struct vty *vty)
255 char cmd[] = { IAC, WILL, TELOPT_SGA, '\0' };
256 vty_out (vty, "%s", cmd);
259 /* Make don't use linemode over telnet. */
261 vty_dont_linemode (struct vty *vty)
263 char cmd[] = { IAC, DONT, TELOPT_LINEMODE, '\0' };
264 vty_out (vty, "%s", cmd);
267 /* Use window size. */
269 vty_do_window_size (struct vty *vty)
271 char cmd[] = { IAC, DO, TELOPT_NAWS, '\0' };
272 vty_out (vty, "%s", cmd);
275 #if 0 /* Currently not used. */
276 /* Make don't use lflow vty interface. */
278 vty_dont_lflow_ahead (struct vty *vty)
280 char cmd[] = { IAC, DONT, TELOPT_LFLOW, '\0' };
281 vty_out (vty, "%s", cmd);
284 #endif /* BRCM_CMD_SUPPORT */
286 /* Allocate new vty struct. */
290 struct vty *new = XCALLOC (MTYPE_VTY, sizeof (struct vty));
292 #if defined(BRCM_CMD_SUPPORT)
293 new->obuf = (struct buffer *) buffer_new (100);
295 new->buf = XCALLOC (MTYPE_VTY, VTY_BUFSIZ);
296 new->max = VTY_BUFSIZ;
297 new->sb_buffer = NULL;
302 #if defined(BRCM_CMD_SUPPORT)
303 /* Authentication of vty */
305 vty_auth (struct vty *vty, char *buf)
308 enum node_type next_node = 0;
310 char *crypt (const char *, const char *);
316 passwd = host.password_encrypt;
318 passwd = host.password;
320 next_node = host.enable ? VIEW_NODE : ENABLE_NODE;
322 next_node = VIEW_NODE;
324 case AUTH_ENABLE_NODE:
326 passwd = host.enable_encrypt;
328 passwd = host.enable;
329 next_node = ENABLE_NODE;
336 fail = strcmp (crypt(buf, passwd), passwd);
338 fail = strcmp (buf, passwd);
346 vty->node = next_node; /* Success ! */
353 if (vty->node == AUTH_NODE)
355 vty_out (vty, "%% Bad passwords, too many failures!%s", VTY_NEWLINE);
356 vty->status = VTY_CLOSE;
360 /* AUTH_ENABLE_NODE */
362 vty_out (vty, "%% Bad enable passwords, too many failures!%s", VTY_NEWLINE);
363 vty->node = VIEW_NODE;
369 /* Command execution over the vty interface. */
371 vty_command (struct vty *vty, char *buf)
376 /* Split readline string up into the vector */
377 vline = cmd_make_strvec (buf);
382 ret = cmd_execute_command (vline, vty, NULL);
384 if (ret != CMD_SUCCESS)
388 if (vty->type == VTY_FILE)
389 vty_out (vty, "Warning...%s", VTY_NEWLINE);
391 case CMD_ERR_AMBIGUOUS:
392 vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
394 case CMD_ERR_NO_MATCH:
395 vty_out (vty, "%% Unknown command.%s", VTY_NEWLINE);
397 case CMD_ERR_INCOMPLETE:
398 vty_out (vty, "%% Command incomplete.%s", VTY_NEWLINE);
401 cmd_free_strvec (vline);
406 char telnet_backward_char = 0x08;
407 char telnet_space_char = ' ';
409 /* Basic function to write buffer to vty. */
411 vty_write (struct vty *vty, char *buf, size_t nbytes)
413 if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
416 /* Should we do buffering here ? And make vty_flush (vty) ? */
417 buffer_write (vty->obuf, (u_char *)buf, nbytes);
420 /* Ensure length of input buffer. Is buffer is short, double it. */
422 vty_ensure (struct vty *vty, int length)
424 if (vty->max <= length)
427 vty->buf = XREALLOC (MTYPE_VTY, vty->buf, vty->max);
431 /* Basic function to insert character into vty. */
433 vty_self_insert (struct vty *vty, char c)
438 vty_ensure (vty, vty->length + 1);
439 length = vty->length - vty->cp;
440 memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
441 vty->buf[vty->cp] = c;
443 vty_write (vty, &vty->buf[vty->cp], length + 1);
444 for (i = 0; i < length; i++)
445 vty_write (vty, &telnet_backward_char, 1);
451 /* Self insert character 'c' in overwrite mode. */
453 vty_self_insert_overwrite (struct vty *vty, char c)
455 vty_ensure (vty, vty->length + 1);
456 vty->buf[vty->cp++] = c;
458 if (vty->cp > vty->length)
461 if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
464 vty_write (vty, &c, 1);
467 /* Insert a word into vty interface with overwrite mode. */
469 vty_insert_word_overwrite (struct vty *vty, char *str)
471 int len = strlen (str);
472 vty_write (vty, str, len);
473 strcpy (&vty->buf[vty->cp], str);
475 vty->length = vty->cp;
478 /* Forward character. */
480 vty_forward_char (struct vty *vty)
482 if (vty->cp < vty->length)
484 vty_write (vty, &vty->buf[vty->cp], 1);
489 /* Backward character. */
491 vty_backward_char (struct vty *vty)
496 vty_write (vty, &telnet_backward_char, 1);
500 /* Move to the beginning of the line. */
502 vty_beginning_of_line (struct vty *vty)
505 vty_backward_char (vty);
508 /* Move to the end of the line. */
510 vty_end_of_line (struct vty *vty)
512 while (vty->cp < vty->length)
513 vty_forward_char (vty);
516 static void vty_kill_line_from_beginning (struct vty *);
517 static void vty_redraw_line (struct vty *);
519 /* Print command line history. This function is called from
520 vty_next_line and vty_previous_line. */
522 vty_history_print (struct vty *vty)
526 vty_kill_line_from_beginning (vty);
528 /* Get previous line from history buffer */
529 length = strlen (vty->hist[vty->hp]);
530 memcpy (vty->buf, vty->hist[vty->hp], length);
531 vty->cp = vty->length = length;
533 /* Redraw current line */
534 vty_redraw_line (vty);
537 /* Show next command line history. */
539 vty_next_line (struct vty *vty)
543 if (vty->hp == vty->hindex)
546 /* Try is there history exist or not. */
548 if (try_index == (VTY_MAXHIST - 1))
553 /* If there is not history return. */
554 if (vty->hist[try_index] == NULL)
559 vty_history_print (vty);
562 /* Show previous command line history. */
564 vty_previous_line (struct vty *vty)
570 try_index = VTY_MAXHIST - 1;
574 if (vty->hist[try_index] == NULL)
579 vty_history_print (vty);
582 /* This function redraw all of the command line character. */
584 vty_redraw_line (struct vty *vty)
586 vty_write (vty, vty->buf, vty->length);
587 vty->cp = vty->length;
592 vty_forward_word (struct vty *vty)
594 while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
595 vty_forward_char (vty);
597 while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
598 vty_forward_char (vty);
601 /* Backward word without skipping training space. */
603 vty_backward_pure_word (struct vty *vty)
605 while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
606 vty_backward_char (vty);
611 vty_backward_word (struct vty *vty)
613 while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
614 vty_backward_char (vty);
616 while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
617 vty_backward_char (vty);
620 /* When '^D' is typed at the beginning of the line we move to the down
623 vty_down_level (struct vty *vty)
625 vty_out (vty, "%s", VTY_NEWLINE);
626 config_exit (NULL, vty, 0, NULL);
631 /* When '^Z' is received from vty, move down to the enable mode. */
633 vty_end_config (struct vty *vty)
635 vty_out (vty, "%s", VTY_NEWLINE);
657 case KEYCHAIN_KEY_NODE:
660 vty_config_unlock (vty);
661 vty->node = ENABLE_NODE;
664 /* Unknown node, we have to ignore it. */
672 /* Delete a charcter at the current point. */
674 vty_delete_char (struct vty *vty)
679 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
682 if (vty->length == 0)
684 vty_down_level (vty);
688 if (vty->cp == vty->length)
689 return; /* completion need here? */
691 size = vty->length - vty->cp;
694 memmove (&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1);
695 vty->buf[vty->length] = '\0';
697 vty_write (vty, &vty->buf[vty->cp], size - 1);
698 vty_write (vty, &telnet_space_char, 1);
700 for (i = 0; i < size; i++)
701 vty_write (vty, &telnet_backward_char, 1);
704 /* Delete a character before the point. */
706 vty_delete_backward_char (struct vty *vty)
711 vty_backward_char (vty);
712 vty_delete_char (vty);
715 /* Kill rest of line from current point. */
717 vty_kill_line (struct vty *vty)
722 size = vty->length - vty->cp;
727 for (i = 0; i < size; i++)
728 vty_write (vty, &telnet_space_char, 1);
729 for (i = 0; i < size; i++)
730 vty_write (vty, &telnet_backward_char, 1);
732 memset (&vty->buf[vty->cp], 0, size);
733 vty->length = vty->cp;
736 /* Kill line from the beginning. */
738 vty_kill_line_from_beginning (struct vty *vty)
740 vty_beginning_of_line (vty);
744 /* Delete a word before the point. */
746 vty_forward_kill_word (struct vty *vty)
748 while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
749 vty_delete_char (vty);
750 while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
751 vty_delete_char (vty);
754 /* Delete a word before the point. */
756 vty_backward_kill_word (struct vty *vty)
758 while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
759 vty_delete_backward_char (vty);
760 while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
761 vty_delete_backward_char (vty);
764 /* Transpose chars before or at the point. */
766 vty_transpose_chars (struct vty *vty)
770 /* If length is short or point is near by the beginning of line then
772 if (vty->length < 2 || vty->cp < 1)
775 /* In case of point is located at the end of the line. */
776 if (vty->cp == vty->length)
778 c1 = vty->buf[vty->cp - 1];
779 c2 = vty->buf[vty->cp - 2];
781 vty_backward_char (vty);
782 vty_backward_char (vty);
783 vty_self_insert_overwrite (vty, c1);
784 vty_self_insert_overwrite (vty, c2);
788 c1 = vty->buf[vty->cp];
789 c2 = vty->buf[vty->cp - 1];
791 vty_backward_char (vty);
792 vty_self_insert_overwrite (vty, c1);
793 vty_self_insert_overwrite (vty, c2);
797 /* Do completion at vty interface. */
799 vty_complete_command (struct vty *vty)
803 char **matched = NULL;
806 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
809 vline = cmd_make_strvec (vty->buf);
813 /* In case of 'help \t'. */
814 if (isspace ((int) vty->buf[vty->length - 1]))
815 vector_set (vline, '\0');
817 matched = cmd_complete_command (vline, vty, &ret);
819 cmd_free_strvec (vline);
821 vty_out (vty, "%s", VTY_NEWLINE);
824 case CMD_ERR_AMBIGUOUS:
825 vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
827 vty_redraw_line (vty);
829 case CMD_ERR_NO_MATCH:
830 /* vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); */
832 vty_redraw_line (vty);
834 case CMD_COMPLETE_FULL_MATCH:
836 vty_redraw_line (vty);
837 vty_backward_pure_word (vty);
838 vty_insert_word_overwrite (vty, matched[0]);
839 vty_self_insert (vty, ' ');
840 XFREE (MTYPE_TMP, matched[0]);
842 case CMD_COMPLETE_MATCH:
844 vty_redraw_line (vty);
845 vty_backward_pure_word (vty);
846 vty_insert_word_overwrite (vty, matched[0]);
847 XFREE (MTYPE_TMP, matched[0]);
848 vector_only_index_free (matched);
851 case CMD_COMPLETE_LIST_MATCH:
852 for (i = 0; matched[i] != NULL; i++)
854 if (i != 0 && ((i % 6) == 0))
855 vty_out (vty, "%s", VTY_NEWLINE);
856 vty_out (vty, "%-10s ", matched[i]);
857 XFREE (MTYPE_TMP, matched[i]);
859 vty_out (vty, "%s", VTY_NEWLINE);
862 vty_redraw_line (vty);
864 case CMD_ERR_NOTHING_TODO:
866 vty_redraw_line (vty);
872 vector_only_index_free (matched);
876 vty_describe_fold (struct vty *vty, int cmd_width,
877 int desc_width, struct desc *desc)
882 cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd;
886 vty_out (vty, " %-*s %s%s", cmd_width, cmd, desc->str, VTY_NEWLINE);
890 buf = XCALLOC (MTYPE_TMP, strlen (desc->str) + 1);
892 for (p = desc->str; strlen (p) > desc_width; p += pos + 1)
894 for (pos = desc_width; pos > 0; pos--)
895 if (*(p + pos) == ' ')
901 strncpy (buf, p, pos);
903 vty_out (vty, " %-*s %s%s", cmd_width, cmd, buf, VTY_NEWLINE);
908 vty_out (vty, " %-*s %s%s", cmd_width, cmd, p, VTY_NEWLINE);
910 XFREE (MTYPE_TMP, buf);
913 /* Describe matched command function. */
915 vty_describe_command (struct vty *vty)
920 int i, width, desc_width;
921 struct desc *desc, *desc_cr = NULL;
923 vline = cmd_make_strvec (vty->buf);
925 /* In case of '> ?'. */
928 vline = vector_init (1);
929 vector_set (vline, '\0');
932 if (isspace ((int) vty->buf[vty->length - 1]))
933 vector_set (vline, '\0');
935 describe = cmd_describe_command (vline, vty, &ret);
937 vty_out (vty, "%s", VTY_NEWLINE);
939 /* Ambiguous error. */
942 case CMD_ERR_AMBIGUOUS:
943 cmd_free_strvec (vline);
944 vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
946 vty_redraw_line (vty);
949 case CMD_ERR_NO_MATCH:
950 cmd_free_strvec (vline);
951 vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE);
953 vty_redraw_line (vty);
958 /* Get width of command string. */
960 for (i = 0; i < vector_max (describe); i++)
961 if ((desc = vector_slot (describe, i)) != NULL)
965 if (desc->cmd[0] == '\0')
968 len = strlen (desc->cmd);
969 if (desc->cmd[0] == '.')
976 /* Get width of description string. */
977 desc_width = vty->width - (width + 6);
979 /* Print out description. */
980 for (i = 0; i < vector_max (describe); i++)
981 if ((desc = vector_slot (describe, i)) != NULL)
983 if (desc->cmd[0] == '\0')
986 if (strcmp (desc->cmd, "<cr>") == 0)
993 vty_out (vty, " %-s%s",
994 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
996 else if (desc_width >= strlen (desc->str))
997 vty_out (vty, " %-*s %s%s", width,
998 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
999 desc->str, VTY_NEWLINE);
1001 vty_describe_fold (vty, width, desc_width, desc);
1004 vty_out (vty, " %-*s %s%s", width
1005 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
1006 desc->str ? desc->str : "", VTY_NEWLINE);
1010 if ((desc = desc_cr))
1013 vty_out (vty, " %-s%s",
1014 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
1016 else if (desc_width >= strlen (desc->str))
1017 vty_out (vty, " %-*s %s%s", width,
1018 desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
1019 desc->str, VTY_NEWLINE);
1021 vty_describe_fold (vty, width, desc_width, desc);
1024 cmd_free_strvec (vline);
1025 vector_free (describe);
1028 vty_redraw_line (vty);
1032 vty_clear_buf (struct vty *vty)
1034 memset (vty->buf, 0, vty->max);
1037 /* ^C stop current input and do not add command line to the history. */
1039 vty_stop_input (struct vty *vty)
1041 vty->cp = vty->length = 0;
1042 vty_clear_buf (vty);
1043 vty_out (vty, "%s", VTY_NEWLINE);
1049 /* Nothing to do. */
1052 case INTERFACE_NODE:
1061 case KEYCHAIN_KEY_NODE:
1064 vty_config_unlock (vty);
1065 vty->node = ENABLE_NODE;
1068 /* Unknown node, we have to ignore it. */
1073 /* Set history pointer to the latest one. */
1074 vty->hp = vty->hindex;
1077 /* Add current command line to the history buffer. */
1079 vty_hist_add (struct vty *vty)
1083 if (vty->length == 0)
1086 index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1;
1088 /* Ignore the same string as previous one. */
1089 if (vty->hist[index])
1090 if (strcmp (vty->buf, vty->hist[index]) == 0)
1092 vty->hp = vty->hindex;
1096 /* Insert history entry. */
1097 if (vty->hist[vty->hindex])
1098 XFREE (MTYPE_VTY_HIST, vty->hist[vty->hindex]);
1099 vty->hist[vty->hindex] = XSTRDUP (MTYPE_VTY_HIST, vty->buf);
1101 /* History index rotation. */
1103 if (vty->hindex == VTY_MAXHIST)
1106 vty->hp = vty->hindex;
1109 /* #define TELNET_OPTION_DEBUG */
1111 /* Get telnet window size. */
1113 vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes)
1115 #ifdef TELNET_OPTION_DEBUG
1118 for (i = 0; i < nbytes; i++)
1123 vty_out (vty, "IAC ");
1126 vty_out (vty, "WILL ");
1129 vty_out (vty, "WONT ");
1132 vty_out (vty, "DO ");
1135 vty_out (vty, "DONT ");
1138 vty_out (vty, "SB ");
1141 vty_out (vty, "SE ");
1144 vty_out (vty, "TELOPT_ECHO %s", VTY_NEWLINE);
1147 vty_out (vty, "TELOPT_SGA %s", VTY_NEWLINE);
1150 vty_out (vty, "TELOPT_NAWS %s", VTY_NEWLINE);
1153 vty_out (vty, "%x ", buf[i]);
1157 vty_out (vty, "%s", VTY_NEWLINE);
1159 #endif /* TELNET_OPTION_DEBUG */
1164 buffer_reset(vty->sb_buffer);
1165 vty->iac_sb_in_progress = 1;
1170 char *buffer = (char *)vty->sb_buffer->head->data;
1171 int length = vty->sb_buffer->length;
1176 if (!vty->iac_sb_in_progress)
1179 if (buffer[0] == '\0')
1181 vty->iac_sb_in_progress = 0;
1189 vty->width = buffer[2];
1190 vty->height = vty->lines >= 0 ? vty->lines : buffer[4];
1193 vty->iac_sb_in_progress = 0;
1203 /* Execute current command line. */
1205 vty_execute (struct vty *vty)
1214 case AUTH_ENABLE_NODE:
1215 vty_auth (vty, vty->buf);
1218 ret = vty_command (vty, vty->buf);
1219 if (vty->type == VTY_TERM)
1224 /* Clear command line buffer. */
1225 vty->cp = vty->length = 0;
1226 vty_clear_buf (vty);
1228 if (vty->status != VTY_CLOSE
1229 && vty->status != VTY_START
1230 && vty->status != VTY_CONTINUE)
1236 #define CONTROL(X) ((X) - '@')
1237 #define VTY_NORMAL 0
1238 #define VTY_PRE_ESCAPE 1
1239 #define VTY_ESCAPE 2
1241 /* Escape character command map. */
1243 vty_escape_map (unsigned char c, struct vty *vty)
1248 vty_previous_line (vty);
1251 vty_next_line (vty);
1254 vty_forward_char (vty);
1257 vty_backward_char (vty);
1263 /* Go back to normal mode. */
1264 vty->escape = VTY_NORMAL;
1267 /* Quit print out to the buffer. */
1269 vty_buffer_reset (struct vty *vty)
1271 buffer_reset (vty->obuf);
1273 vty_redraw_line (vty);
1276 /* Read data via vty socket. */
1278 vty_read (struct thread *thread)
1283 unsigned char buf[VTY_READ_BUFSIZ];
1285 int vty_sock = THREAD_FD (thread);
1286 struct vty *vty = THREAD_ARG (thread);
1289 /* Read raw data from socket */
1290 nbytes = read (vty->fd, buf, VTY_READ_BUFSIZ);
1292 vty->status = VTY_CLOSE;
1294 for (i = 0; i < nbytes; i++)
1309 if (vty->iac_sb_in_progress && !vty->iac)
1311 buffer_putc(vty->sb_buffer, buf[i]);
1317 /* In case of telnet command */
1318 ret = vty_telnet_option (vty, buf + i, nbytes - i);
1324 if (vty->status == VTY_MORE)
1331 if (vty->output_func)
1332 (*vty->output_func) (vty, 1);
1333 vty_buffer_reset (vty);
1336 if (vty->output_func)
1337 (*vty->output_func) (vty, 0);
1343 /* Escape character. */
1344 if (vty->escape == VTY_ESCAPE)
1346 vty_escape_map (buf[i], vty);
1350 /* Pre-escape status. */
1351 if (vty->escape == VTY_PRE_ESCAPE)
1356 vty->escape = VTY_ESCAPE;
1359 vty_backward_word (vty);
1360 vty->escape = VTY_NORMAL;
1363 vty_forward_word (vty);
1364 vty->escape = VTY_NORMAL;
1367 vty_forward_kill_word (vty);
1368 vty->escape = VTY_NORMAL;
1372 vty_backward_kill_word (vty);
1373 vty->escape = VTY_NORMAL;
1376 vty->escape = VTY_NORMAL;
1385 vty_beginning_of_line (vty);
1388 vty_backward_char (vty);
1391 vty_stop_input (vty);
1394 vty_delete_char (vty);
1397 vty_end_of_line (vty);
1400 vty_forward_char (vty);
1404 vty_delete_backward_char (vty);
1407 vty_kill_line (vty);
1410 vty_next_line (vty);
1413 vty_previous_line (vty);
1416 vty_transpose_chars (vty);
1419 vty_kill_line_from_beginning (vty);
1422 vty_backward_kill_word (vty);
1425 vty_end_config (vty);
1429 vty_out (vty, "%s", VTY_NEWLINE);
1433 vty_complete_command (vty);
1436 if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
1437 vty_self_insert (vty, buf[i]);
1439 vty_describe_command (vty);
1442 if (i + 1 < nbytes && buf[i + 1] == '[')
1444 vty->escape = VTY_ESCAPE;
1448 vty->escape = VTY_PRE_ESCAPE;
1451 if (buf[i] > 31 && buf[i] < 127)
1452 vty_self_insert (vty, buf[i]);
1458 if (vty->status == VTY_CLOSE)
1462 vty_event (VTY_WRITE, vty_sock, vty);
1463 vty_event (VTY_READ, vty_sock, vty);
1468 /* Flush buffer to the vty. */
1470 vty_flush (struct thread *thread)
1474 int vty_sock = THREAD_FD (thread);
1475 struct vty *vty = THREAD_ARG (thread);
1476 vty->t_write = NULL;
1478 /* Tempolary disable read thread. */
1479 if (vty->lines == 0)
1482 thread_cancel (vty->t_read);
1486 /* Function execution continue. */
1487 if (vty->status == VTY_START || vty->status == VTY_CONTINUE)
1489 if (vty->status == VTY_CONTINUE)
1494 if (vty->output_func == NULL)
1499 if (vty->lines == 0)
1505 buffer_flush_vty_all (vty->obuf, vty->fd, erase, dont_more);
1507 if (vty->status == VTY_CLOSE)
1513 if (vty->output_func == NULL)
1515 vty->status = VTY_NORMAL;
1517 vty_event (VTY_WRITE, vty_sock, vty);
1520 vty->status = VTY_MORE;
1522 if (vty->lines == 0)
1524 if (vty->output_func == NULL)
1525 vty_event (VTY_READ, vty_sock, vty);
1528 if (vty->output_func)
1529 (*vty->output_func) (vty, 0);
1530 vty_event (VTY_WRITE, vty_sock, vty);
1536 if (vty->status == VTY_MORE)
1541 if (vty->lines == 0)
1542 buffer_flush_window (vty->obuf, vty->fd, vty->width, 25, 0, 1);
1544 buffer_flush_window (vty->obuf, vty->fd, vty->width,
1545 vty->lines >= 0 ? vty->lines : vty->height,
1548 if (buffer_empty (vty->obuf))
1550 if (vty->status == VTY_CLOSE)
1554 vty->status = VTY_NORMAL;
1556 if (vty->lines == 0)
1557 vty_event (VTY_READ, vty_sock, vty);
1562 vty->status = VTY_MORE;
1564 if (vty->lines == 0)
1565 vty_event (VTY_WRITE, vty_sock, vty);
1572 /* Create new vty structure. */
1574 vty_create (int vty_sock, union sockunion *su)
1578 /* Allocate new vty structure and set up default values. */
1581 vty->type = VTY_TERM;
1582 vty->address = sockunion_su2str (su);
1583 if (no_password_check)
1586 vty->node = ENABLE_NODE;
1588 vty->node = VIEW_NODE;
1591 vty->node = AUTH_NODE;
1594 vty_clear_buf (vty);
1596 memset (vty->hist, 0, sizeof (vty->hist));
1599 vector_set_index (vtyvec, vty_sock, vty);
1600 vty->status = VTY_NORMAL;
1601 vty->v_timeout = vty_timeout_val;
1602 if (host.lines >= 0)
1603 vty->lines = host.lines;
1607 vty->iac_sb_in_progress = 0;
1608 vty->sb_buffer = buffer_new (1024);
1610 if (! no_password_check)
1612 /* Vty is not available if password isn't set. */
1613 if (host.password == NULL && host.password_encrypt == NULL)
1615 vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE);
1616 vty->status = VTY_CLOSE;
1622 /* Say hello to the world. */
1624 if (! no_password_check)
1625 vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
1627 /* Setting up terminal. */
1628 vty_will_echo (vty);
1629 vty_will_suppress_go_ahead (vty);
1631 vty_dont_linemode (vty);
1632 vty_do_window_size (vty);
1633 /* vty_dont_lflow_ahead (vty); */
1637 /* Add read/write thread. */
1638 vty_event (VTY_WRITE, vty_sock, vty);
1639 vty_event (VTY_READ, vty_sock, vty);
1644 /* Accept connection from the network. */
1646 vty_accept (struct thread *thread)
1654 struct prefix *p = NULL;
1655 struct access_list *acl = NULL;
1657 accept_sock = THREAD_FD (thread);
1659 /* We continue hearing vty socket. */
1660 vty_event (VTY_SERV, accept_sock, NULL);
1662 memset (&su, 0, sizeof (union sockunion));
1664 /* We can handle IPv4 or IPv6 socket. */
1665 vty_sock = sockunion_accept (accept_sock, &su);
1668 #ifdef BRCM_RIP_DEBUG
1669 zlog_warn ("can't accept vty socket : %s", strerror (errno));
1674 #ifdef BRCM_LIST_SUPPORT
1675 p = sockunion2hostprefix (&su);
1677 /* VTY's accesslist apply. */
1678 if (p->family == AF_INET && vty_accesslist_name)
1680 if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) &&
1681 (access_list_apply (acl, p) == FILTER_DENY))
1684 #ifdef BRCM_RIP_DEBUG
1685 zlog (NULL, LOG_INFO, "Vty connection refused from %s",
1686 (buf = sockunion_su2str (&su)));
1691 /* continue accepting connections */
1692 vty_event (VTY_SERV, accept_sock, NULL);
1699 #endif /* BRCM_LIST_SUPPORT */
1702 /* VTY's ipv6 accesslist apply. */
1703 if (p->family == AF_INET6 && vty_ipv6_accesslist_name)
1705 if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) &&
1706 (access_list_apply (acl, p) == FILTER_DENY))
1709 #ifdef BRCM_RIP_DEBUG
1710 zlog (NULL, LOG_INFO, "Vty connection refused from %s",
1711 (buf = sockunion_su2str (&su)));
1716 /* continue accepting connections */
1717 vty_event (VTY_SERV, accept_sock, NULL);
1724 #endif /* HAVE_IPV6 */
1729 ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY,
1730 (char *) &on, sizeof (on));
1732 #ifdef BRCM_RIP_DEBUG
1733 zlog (NULL, LOG_INFO, "can't set sockopt to vty_sock : %s",
1736 vty = vty_create (vty_sock, &su);
1741 #if defined(HAVE_IPV6) && !defined(NRL)
1743 vty_serv_sock_addrinfo (const char *hostname, unsigned short port)
1746 struct addrinfo req;
1747 struct addrinfo *ainfo;
1748 struct addrinfo *ainfo_save;
1750 char port_str[BUFSIZ];
1752 memset (&req, 0, sizeof (struct addrinfo));
1753 req.ai_flags = AI_PASSIVE;
1754 req.ai_family = AF_UNSPEC;
1755 req.ai_socktype = SOCK_STREAM;
1756 sprintf (port_str, "%d", port);
1757 port_str[sizeof (port_str) - 1] = '\0';
1759 ret = getaddrinfo (hostname, port_str, &req, &ainfo);
1763 fprintf (stderr, "getaddrinfo failed: %s\n", gai_strerror (ret));
1771 if (ainfo->ai_family != AF_INET
1773 && ainfo->ai_family != AF_INET6
1774 #endif /* HAVE_IPV6 */
1778 sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
1782 sockopt_reuseaddr (sock);
1783 sockopt_reuseport (sock);
1785 ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
1788 close (sock); /* Avoid sd leak. */
1792 ret = listen (sock, 3);
1795 close (sock); /* Avoid sd leak. */
1799 vty_event (VTY_SERV, sock, NULL);
1801 while ((ainfo = ainfo->ai_next) != NULL);
1803 freeaddrinfo (ainfo_save);
1805 #endif /* HAVE_IPV6 && ! NRL */
1807 /* Make vty server socket. */
1809 vty_serv_sock_family (unsigned short port, int family)
1815 memset (&su, 0, sizeof (union sockunion));
1816 su.sa.sa_family = family;
1818 /* Make new socket. */
1819 accept_sock = sockunion_stream_socket (&su);
1820 if (accept_sock < 0)
1823 /* This is server, so reuse address. */
1824 sockopt_reuseaddr (accept_sock);
1825 sockopt_reuseport (accept_sock);
1827 /* Bind socket to universal address and given port. */
1828 ret = sockunion_bind (accept_sock, &su, port, NULL);
1831 close (accept_sock); /* Avoid sd leak. */
1835 /* Listen socket under queue 3. */
1836 ret = listen (accept_sock, 3);
1839 #ifdef BRCM_RIP_DEBUG
1840 zlog (NULL, LOG_WARNING, "can't listen socket");
1842 close (accept_sock); /* Avoid sd leak. */
1846 /* Add vty server event. */
1847 vty_event (VTY_SERV, accept_sock, NULL);
1851 /* For sockaddr_un. */
1854 /* VTY shell UNIX domain socket. */
1856 vty_serv_un (char *path)
1860 struct sockaddr_un serv;
1863 /* First of all, unlink existing socket */
1867 old_mask = umask (0077);
1869 /* Make UNIX domain socket. */
1870 sock = socket (AF_UNIX, SOCK_STREAM, 0);
1877 /* Make server socket. */
1878 memset (&serv, 0, sizeof (struct sockaddr_un));
1879 serv.sun_family = AF_UNIX;
1880 strncpy (serv.sun_path, path, strlen (path));
1882 len = serv.sun_len = SUN_LEN(&serv);
1884 len = sizeof (serv.sun_family) + strlen (serv.sun_path);
1885 #endif /* HAVE_SUN_LEN */
1887 ret = bind (sock, (struct sockaddr *) &serv, len);
1891 close (sock); /* Avoid sd leak. */
1895 ret = listen (sock, 5);
1899 close (sock); /* Avoid sd leak. */
1905 vty_event (VTYSH_SERV, sock, NULL);
1908 /* #define VTYSH_DEBUG 1 */
1911 vtysh_accept (struct thread *thread)
1916 struct sockaddr_un client;
1919 accept_sock = THREAD_FD (thread);
1921 vty_event (VTYSH_SERV, accept_sock, NULL);
1923 memset (&client, 0, sizeof (struct sockaddr_un));
1924 client_len = sizeof (struct sockaddr_un);
1926 sock = accept (accept_sock, (struct sockaddr *) &client, &client_len);
1930 #ifdef BRCM_RIP_DEBUG
1931 zlog_warn ("can't accept vty socket : %s", strerror (errno));
1937 printf ("VTY shell accept\n");
1938 #endif /* VTYSH_DEBUG */
1942 vty->type = VTY_SHELL_SERV;
1943 vty->node = VIEW_NODE;
1945 vty_event (VTYSH_READ, sock, vty);
1951 vtysh_read (struct thread *thread)
1957 unsigned char buf[VTY_READ_BUFSIZ];
1958 u_char header[4] = {0, 0, 0, 0};
1960 sock = THREAD_FD (thread);
1961 vty = THREAD_ARG (thread);
1964 nbytes = read (sock, buf, VTY_READ_BUFSIZ);
1969 printf ("close vtysh\n");
1970 #endif /* VTYSH_DEBUG */
1975 printf ("line: %s\n", buf);
1976 #endif /* VTYSH_DEBUG */
1978 vty_ensure (vty, nbytes);
1979 memcpy (vty->buf, buf, nbytes);
1981 /* Pass this line to parser. */
1982 ret = vty_execute (vty);
1984 vty_clear_buf (vty);
1986 /* Return result. */
1988 printf ("result: %d\n", ret);
1989 printf ("vtysh node: %d\n", vty->node);
1990 #endif /* VTYSH_DEBUG */
1993 write (vty->fd, header, 4);
1995 vty_event (VTYSH_READ, sock, vty);
2001 /* Determine address family to bind. */
2003 vty_serv_sock (const char *hostname, unsigned short port, char *path)
2005 /* If port is set to 0, do not listen on TCP/IP at all! */
2011 vty_serv_sock_family (port, AF_INET);
2012 vty_serv_sock_family (port, AF_INET6);
2014 vty_serv_sock_addrinfo (hostname, port);
2016 #else /* ! HAVE_IPV6 */
2017 vty_serv_sock_family (port, AF_INET);
2018 #endif /* HAVE_IPV6 */
2025 #endif /* BRCM_CMD_SUPPORT */
2027 /* Close vty interface. */
2029 vty_close (struct vty *vty)
2033 #if defined(BRCM_CMD_SUPPORT)
2034 /* Cancel threads.*/
2036 thread_cancel (vty->t_read);
2038 thread_cancel (vty->t_write);
2040 thread_cancel (vty->t_timeout);
2042 thread_cancel (vty->t_output);
2045 if (! buffer_empty (vty->obuf))
2046 buffer_flush_all (vty->obuf, vty->fd);
2048 /* Free input buffer. */
2049 buffer_free (vty->obuf);
2051 /* Free SB buffer. */
2053 buffer_free (vty->sb_buffer);
2054 #endif /* BRCM_CMD_SUPPORT */
2056 /* Free command history. */
2057 for (i = 0; i < VTY_MAXHIST; i++)
2059 XFREE (MTYPE_VTY_HIST, vty->hist[i]);
2062 vector_unset (vtyvec, vty->fd);
2069 XFREE (0, vty->address);
2071 XFREE (MTYPE_VTY, vty->buf);
2073 /* Check configure. */
2074 vty_config_unlock (vty);
2077 XFREE (MTYPE_VTY, vty);
2080 #if defined(BRCM_CMD_SUPPORT)
2081 /* When time out occur output message then close connection. */
2083 vty_timeout (struct thread *thread)
2087 vty = THREAD_ARG (thread);
2088 vty->t_timeout = NULL;
2092 buffer_reset (vty->obuf);
2093 vty_out (vty, "%sVty connection is timed out.%s", VTY_NEWLINE, VTY_NEWLINE);
2095 /* Close connection. */
2096 vty->status = VTY_CLOSE;
2101 #endif /* BRCM_CMD_SUPPORT */
2104 /* Read up configuration file from file_name. */
2106 vty_read_file (FILE *confp)
2112 vty->fd = 0; /* stdout */
2113 vty->type = VTY_TERM;
2114 vty->node = CONFIG_NODE;
2116 /* Execute configuration file */
2117 ret = config_from_file (vty, confp);
2119 if (ret != CMD_SUCCESS)
2123 case CMD_ERR_AMBIGUOUS:
2124 fprintf (stderr, "Ambiguous command.\n");
2126 case CMD_ERR_NO_MATCH:
2127 fprintf (stderr, "There is no such command.\n");
2130 fprintf (stderr, "Error occured during reading below line.\n%s\n",
2139 #if defined(BRCM_CMD_SUPPORT)
2141 vty_use_backup_config (char *fullpath)
2143 char *fullpath_sav, *fullpath_tmp;
2150 fullpath_sav = malloc (strlen (fullpath) + strlen (CONF_BACKUP_EXT) + 1);
2151 strcpy (fullpath_sav, fullpath);
2152 strcat (fullpath_sav, CONF_BACKUP_EXT);
2153 if (stat (fullpath_sav, &buf) == -1)
2155 free (fullpath_sav);
2159 fullpath_tmp = malloc (strlen (fullpath) + 8);
2160 sprintf (fullpath_tmp, "%s.XXXXXX", fullpath);
2162 /* Open file to configuration write. */
2163 tmp = mkstemp (fullpath_tmp);
2166 free (fullpath_sav);
2167 free (fullpath_tmp);
2171 sav = open (fullpath_sav, O_RDONLY);
2174 free (fullpath_sav);
2175 free (fullpath_tmp);
2176 unlink (fullpath_tmp);
2180 while((c = read (sav, buffer, 512)) > 0)
2181 write (tmp, buffer, c);
2186 if (link (fullpath_tmp, fullpath) == 0)
2187 ret = fopen (fullpath, "r");
2189 unlink (fullpath_tmp);
2191 free (fullpath_sav);
2192 free (fullpath_tmp);
2193 return fopen (fullpath, "r");
2195 #endif /* BRCM_CMD_SUPPORT */
2197 /* Read up configuration file from file_name. */
2199 vty_read_config (char *config_file,
2200 char *config_current_dir,
2201 char *config_default_dir)
2207 /* If -f flag specified. */
2208 if (config_file != NULL)
2210 if (! IS_DIRECTORY_SEP (config_file[0]))
2212 cwd = getcwd (NULL, MAXPATHLEN);
2213 fullpath = XMALLOC (MTYPE_TMP,
2214 strlen (cwd) + strlen (config_file) + 2);
2215 sprintf (fullpath, "%s/%s", cwd, config_file);
2218 fullpath = config_file;
2220 confp = fopen (fullpath, "r");
2224 #if defined(BRCM_CMD_SUPPORT)
2225 confp = vty_use_backup_config (fullpath);
2227 fprintf (stderr, "WARNING: using backup configuration file!\n");
2230 fprintf (stderr, "can't open configuration file [%s]\n",
2232 #endif /* BRCM_CMD_SUPPORT */
2234 #if defined(BRCM_CMD_SUPPORT)
2241 /* Relative path configuration file open. */
2242 if (config_current_dir)
2244 confp = fopen (config_current_dir, "r");
2245 #if defined(BRCM_CMD_SUPPORT)
2248 confp = vty_use_backup_config (config_current_dir);
2250 fprintf (stderr, "WARNING: using backup configuration file!\n");
2252 #endif /* BRCM_CMD_SUPPORT */
2255 /* If there is no relative path exists, open system default file. */
2260 struct stat conf_stat;
2262 /* !!!!PLEASE LEAVE!!!!
2263 This is NEEDED for use with vtysh -b, or else you can get
2264 a real configuration food fight with a lot garbage in the
2265 merged configuration file it creates coming from the per
2266 daemon configuration files. This also allows the daemons
2267 to start if there default configuration file is not
2268 present or ignore them, as needed when using vtysh -b to
2269 configure the daemons at boot - MAG */
2271 /* Stat for vtysh Zebra.conf, if found startup and wait for
2272 boot configuration */
2274 if ( strstr(config_default_dir, "vtysh") == NULL)
2276 ret = stat (integrate_default, &conf_stat);
2284 #if defined(BRCM_CMD_SUPPORT)
2285 confp = fopen (config_default_dir, "r");
2288 confp = vty_use_backup_config (config_default_dir);
2291 fprintf (stderr, "WARNING: using backup configuration file!\n");
2292 fullpath = config_default_dir;
2296 fprintf (stderr, "can't open configuration file [%s]\n",
2297 config_default_dir);
2302 fullpath = config_default_dir;
2303 #endif /* BRCM_CMD_SUPPORT */
2307 /* Rleative path configuration file. */
2308 cwd = getcwd (NULL, MAXPATHLEN);
2309 fullpath = XMALLOC (MTYPE_TMP,
2310 strlen (cwd) + strlen (config_current_dir) + 2);
2311 sprintf (fullpath, "%s/%s", cwd, config_current_dir);
2314 vty_read_file (confp);
2318 host_config_set (fullpath);
2321 #if defined(BRCM_CMD_SUPPORT) || defined(BRCM_RIP_DEBUG)
2322 /* Small utility function which output loggin to the VTY. */
2324 vty_log (const char *proto_str, const char *format, va_list va)
2329 for (i = 0; i < vector_max (vtyvec); i++)
2330 if ((vty = vector_slot (vtyvec, i)) != NULL)
2333 vty_time_print (vty, 0);
2334 vty_out (vty, "%s: ", proto_str);
2335 vvty_out (vty, format, va);
2336 vty_out (vty, "\r\n");
2339 #endif /* BRCM_CMD_SUPPORT */
2342 vty_config_lock (struct vty *vty)
2344 if (vty_config == 0)
2353 vty_config_unlock (struct vty *vty)
2355 if (vty_config == 1 && vty->config == 1)
2363 /* Master of the threads. */
2364 extern struct thread_master *master;
2365 /* struct thread_master *master; */
2367 #if defined(BRCM_CMD_SUPPORT)
2369 vty_event (enum event event, int sock, struct vty *vty)
2371 struct thread *vty_serv_thread;
2376 vty_serv_thread = thread_add_read (master, vty_accept, vty, sock);
2377 vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
2381 thread_add_read (master, vtysh_accept, vty, sock);
2384 thread_add_read (master, vtysh_read, vty, sock);
2388 vty->t_read = thread_add_read (master, vty_read, vty, sock);
2390 /* Time out treatment. */
2394 thread_cancel (vty->t_timeout);
2396 thread_add_timer (master, vty_timeout, vty, vty->v_timeout);
2401 vty->t_write = thread_add_write (master, vty_flush, vty, sock);
2403 case VTY_TIMEOUT_RESET:
2406 thread_cancel (vty->t_timeout);
2407 vty->t_timeout = NULL;
2412 thread_add_timer (master, vty_timeout, vty, vty->v_timeout);
2421 "Display who is on vty\n")
2426 for (i = 0; i < vector_max (vtyvec); i++)
2427 if ((v = vector_slot (vtyvec, i)) != NULL)
2428 vty_out (vty, "%svty[%d] connected from %s.%s",
2429 v->config ? "*" : " ",
2430 i, v->address, VTY_NEWLINE);
2434 /* Move to vty configuration mode. */
2438 "Configure a terminal line\n"
2439 "Virtual terminal\n")
2441 vty->node = VTY_NODE;
2445 /* Set time out value. */
2447 exec_timeout (struct vty *vty, char *min_str, char *sec_str)
2449 unsigned long timeout = 0;
2451 /* min_str and sec_str are already checked by parser. So it must be
2452 all digit string. */
2455 timeout = strtol (min_str, NULL, 10);
2459 timeout += strtol (sec_str, NULL, 10);
2461 vty_timeout_val = timeout;
2462 vty->v_timeout = timeout;
2463 vty_event (VTY_TIMEOUT_RESET, 0, vty);
2469 DEFUN (exec_timeout_min,
2470 exec_timeout_min_cmd,
2471 "exec-timeout <0-35791>",
2472 "Set timeout value\n"
2473 "Timeout value in minutes\n")
2475 return exec_timeout (vty, argv[0], NULL);
2478 DEFUN (exec_timeout_sec,
2479 exec_timeout_sec_cmd,
2480 "exec-timeout <0-35791> <0-2147483>",
2481 "Set the EXEC timeout\n"
2482 "Timeout in minutes\n"
2483 "Timeout in seconds\n")
2485 return exec_timeout (vty, argv[0], argv[1]);
2488 DEFUN (no_exec_timeout,
2489 no_exec_timeout_cmd,
2492 "Set the EXEC timeout\n")
2494 return exec_timeout (vty, NULL, NULL);
2497 /* Set vty access class. */
2498 DEFUN (vty_access_class,
2499 vty_access_class_cmd,
2500 "access-class WORD",
2501 "Filter connections based on an IP access list\n"
2504 if (vty_accesslist_name)
2505 XFREE(MTYPE_VTY, vty_accesslist_name);
2507 vty_accesslist_name = XSTRDUP(MTYPE_VTY, argv[0]);
2512 /* Clear vty access class. */
2513 DEFUN (no_vty_access_class,
2514 no_vty_access_class_cmd,
2515 "no access-class [WORD]",
2517 "Filter connections based on an IP access list\n"
2520 if (! vty_accesslist_name || (argc && strcmp(vty_accesslist_name, argv[0])))
2522 vty_out (vty, "Access-class is not currently applied to vty%s",
2527 XFREE(MTYPE_VTY, vty_accesslist_name);
2529 vty_accesslist_name = NULL;
2535 /* Set vty access class. */
2536 DEFUN (vty_ipv6_access_class,
2537 vty_ipv6_access_class_cmd,
2538 "ipv6 access-class WORD",
2540 "Filter connections based on an IP access list\n"
2541 "IPv6 access list\n")
2543 if (vty_ipv6_accesslist_name)
2544 XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
2546 vty_ipv6_accesslist_name = XSTRDUP(MTYPE_VTY, argv[0]);
2551 /* Clear vty access class. */
2552 DEFUN (no_vty_ipv6_access_class,
2553 no_vty_ipv6_access_class_cmd,
2554 "no ipv6 access-class [WORD]",
2557 "Filter connections based on an IP access list\n"
2558 "IPv6 access list\n")
2560 if (! vty_ipv6_accesslist_name ||
2561 (argc && strcmp(vty_ipv6_accesslist_name, argv[0])))
2563 vty_out (vty, "IPv6 access-class is not currently applied to vty%s",
2568 XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
2570 vty_ipv6_accesslist_name = NULL;
2574 #endif /* HAVE_IPV6 */
2580 "Enable password checking\n")
2582 no_password_check = 0;
2586 DEFUN (no_vty_login,
2590 "Enable password checking\n")
2592 no_password_check = 1;
2596 DEFUN (service_advanced_vty,
2597 service_advanced_vty_cmd,
2598 "service advanced-vty",
2599 "Set up miscellaneous service\n"
2600 "Enable advanced mode vty interface\n")
2606 DEFUN (no_service_advanced_vty,
2607 no_service_advanced_vty_cmd,
2608 "no service advanced-vty",
2610 "Set up miscellaneous service\n"
2611 "Enable advanced mode vty interface\n")
2617 DEFUN (terminal_monitor,
2618 terminal_monitor_cmd,
2620 "Set terminal line parameters\n"
2621 "Copy debug output to the current terminal line\n")
2627 DEFUN (terminal_no_monitor,
2628 terminal_no_monitor_cmd,
2629 "terminal no monitor",
2630 "Set terminal line parameters\n"
2632 "Copy debug output to the current terminal line\n")
2638 DEFUN (show_history,
2642 "Display the session command history\n")
2646 for (index = vty->hindex + 1; index != vty->hindex;)
2648 if (index == VTY_MAXHIST)
2654 if (vty->hist[index] != NULL)
2655 vty_out (vty, " %s%s", vty->hist[index], VTY_NEWLINE);
2663 /* Display current configuration. */
2665 vty_config_write (struct vty *vty)
2667 vty_out (vty, "line vty%s", VTY_NEWLINE);
2669 if (vty_accesslist_name)
2670 vty_out (vty, " access-class %s%s",
2671 vty_accesslist_name, VTY_NEWLINE);
2674 if (vty_ipv6_accesslist_name)
2675 vty_out (vty, " ipv6 access-class %s%s",
2676 vty_ipv6_accesslist_name, VTY_NEWLINE);
2680 if (vty_timeout_val != VTY_TIMEOUT_DEFAULT)
2681 vty_out (vty, " exec-timeout %ld %ld%s",
2682 vty_timeout_val / 60,
2683 vty_timeout_val % 60, VTY_NEWLINE);
2686 if (no_password_check)
2687 vty_out (vty, " no login%s", VTY_NEWLINE);
2689 vty_out (vty, "!%s", VTY_NEWLINE);
2694 struct cmd_node vty_node =
2697 "%s(config-line)# ",
2700 /* Reset all VTY status. */
2706 struct thread *vty_serv_thread;
2708 for (i = 0; i < vector_max (vtyvec); i++)
2709 if ((vty = vector_slot (vtyvec, i)) != NULL)
2711 buffer_reset (vty->obuf);
2712 vty->status = VTY_CLOSE;
2716 for (i = 0; i < vector_max (Vvty_serv_thread); i++)
2717 if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL)
2719 thread_cancel (vty_serv_thread);
2720 vector_slot (Vvty_serv_thread, i) = NULL;
2724 vty_timeout_val = VTY_TIMEOUT_DEFAULT;
2726 if (vty_accesslist_name)
2728 XFREE(MTYPE_VTY, vty_accesslist_name);
2729 vty_accesslist_name = NULL;
2732 #ifdef BRCM_LIST_SUPPORT
2733 if (vty_ipv6_accesslist_name)
2735 XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
2736 vty_ipv6_accesslist_name = NULL;
2741 /* for ospf6d easy temprary reload function */
2742 /* vty_reset + close accept socket */
2748 struct thread *vty_serv_thread;
2750 for (i = 0; i < vector_max (vtyvec); i++)
2751 if ((vty = vector_slot (vtyvec, i)) != NULL)
2753 buffer_reset (vty->obuf);
2754 vty->status = VTY_CLOSE;
2758 for (i = 0; i < vector_max (Vvty_serv_thread); i++)
2759 if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL)
2761 thread_cancel (vty_serv_thread);
2762 vector_slot (Vvty_serv_thread, i) = NULL;
2766 vty_timeout_val = VTY_TIMEOUT_DEFAULT;
2768 #ifdef BRCM_LIST_SUPPORT
2769 if (vty_accesslist_name)
2771 XFREE(MTYPE_VTY, vty_accesslist_name);
2772 vty_accesslist_name = NULL;
2775 if (vty_ipv6_accesslist_name)
2777 XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
2778 vty_ipv6_accesslist_name = NULL;
2788 cwd = getcwd (NULL, MAXPATHLEN);
2790 vty_cwd = XMALLOC (MTYPE_TMP, strlen (cwd) + 1);
2791 strcpy (vty_cwd, cwd);
2801 vty_shell (struct vty *vty)
2803 return vty->type == VTY_SHELL ? 1 : 0;
2807 vty_shell_serv (struct vty *vty)
2809 return vty->type == VTY_SHELL_SERV ? 1 : 0;
2815 vtyvec = vector_init (VECTOR_MIN_SIZE);
2817 #endif /* BRCM_CMD_SUPPORT */
2819 /* Install vty's own commands like `who' command. */
2823 /* For further configuration read, preserve current directory. */
2824 #if defined(BRCM_CMD_SUPPORT)
2828 vtyvec = vector_init (VECTOR_MIN_SIZE);
2830 /* Initilize server thread vector. */
2831 Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE);
2833 #if defined(BRCM_CMD_SUPPORT)
2834 /* Install bgp top node. */
2835 install_node (&vty_node, vty_config_write);
2837 install_element (VIEW_NODE, &config_who_cmd);
2838 install_element (VIEW_NODE, &show_history_cmd);
2839 install_element (ENABLE_NODE, &config_who_cmd);
2840 install_element (CONFIG_NODE, &line_vty_cmd);
2841 install_element (CONFIG_NODE, &service_advanced_vty_cmd);
2842 install_element (CONFIG_NODE, &no_service_advanced_vty_cmd);
2843 install_element (CONFIG_NODE, &show_history_cmd);
2844 install_element (ENABLE_NODE, &terminal_monitor_cmd);
2845 install_element (ENABLE_NODE, &terminal_no_monitor_cmd);
2846 install_element (ENABLE_NODE, &show_history_cmd);
2848 install_default (VTY_NODE);
2849 install_element (VTY_NODE, &exec_timeout_min_cmd);
2850 install_element (VTY_NODE, &exec_timeout_sec_cmd);
2851 install_element (VTY_NODE, &no_exec_timeout_cmd);
2852 install_element (VTY_NODE, &vty_access_class_cmd);
2853 install_element (VTY_NODE, &no_vty_access_class_cmd);
2854 install_element (VTY_NODE, &vty_login_cmd);
2855 install_element (VTY_NODE, &no_vty_login_cmd);
2857 install_element (VTY_NODE, &vty_ipv6_access_class_cmd);
2858 install_element (VTY_NODE, &no_vty_ipv6_access_class_cmd);
2859 #endif /* HAVE_IPV6 */
2860 #endif /* BRCM_CMD_SUPPORT */