⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vty.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Virtual terminal [aka TeletYpe] interface routine. * Copyright (C) 1997, 98 Kunihiro Ishiguro * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING.  If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA.   */#include <zebra.h>#include "linklist.h"#include "buffer.h"#include "version.h"#include "command.h"#include "sockunion.h"#include "thread.h"#include "memory.h"#include "str.h"#include "log.h"#include "prefix.h"#include "filter.h"/* Vty events */enum event   {    VTY_SERV,    VTY_READ,    VTY_WRITE,    VTY_TIMEOUT_RESET,#ifdef VTYSH    VTYSH_SERV,    VTYSH_READ#endif /* VTYSH */  };static void vty_event (enum event, int, struct vty *);/* Extern host structure from command.c */extern struct host host;/* Vector which store each vty structure. */static vector vtyvec;/* Vty timeout value. */static unsigned long vty_timeout_val = VTY_TIMEOUT_DEFAULT;/* Vty access-class command */static char *vty_accesslist_name = NULL;/* Vty access-calss for IPv6. */static char *vty_ipv6_accesslist_name = NULL;/* VTY server thread. */vector Vvty_serv_thread;/* Current directory. */char *vty_cwd = NULL;/* Configure lock. */static int vty_config;/* Login password check. */static int no_password_check = 0;/* Integrated configuration file path */char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;/* VTY standard output function. */intvty_out (struct vty *vty, const char *format, ...){  va_list args;  int len = 0;  int size = 1024;  char buf[1024];  char *p = NULL;    va_start (args, format);  if (vty_shell (vty))    vprintf (format, args);  else    {      /* Try to write to initial buffer.  */      len = vsnprintf (buf, sizeof buf, format, args);      /* Initial buffer is not enough.  */      if (len < 0 || len >= size)	{	  while (1)	    {	      if (len > -1)		size = len + 1;	      else		size = size * 2;	      p = XREALLOC (MTYPE_VTY_OUT_BUF, p, size);	      if (! p)		return -1;	      len = vsnprintf (p, size, format, args);	      if (len > -1 && len < size)		break;	    }	}      /* When initial buffer is enough to store all output.  */      if (! p)	p = buf;      /* Pointer p must point out buffer. */      if (vty_shell_serv (vty))	write (vty->fd, (u_char *) p, len);      else	buffer_write (vty->obuf, (u_char *) p, len);      /* If p is not different with buf, it is allocated buffer.  */      if (p != buf)	XFREE (MTYPE_VTY_OUT_BUF, p);    }  va_end (args);  return len;}#define TIME_BUF 27/* current time string. */inttime_str (char *buf){  time_t clock;  struct tm *tm;  int ret;  time (&clock);  tm = localtime (&clock);  ret = strftime (buf, TIME_BUF, "%Y/%m/%d %H:%M:%S", tm);  return ret;}intvty_log_out (struct vty *vty, const char *proto_str, const char *format,	     va_list va){  int len;  int ret;  char buf[1024];  char time_buf[TIME_BUF];  ret = time_str (time_buf);  if (ret != 0)    {      snprintf (buf, sizeof buf, "%s ", time_buf);      write (vty->fd, buf, strlen (time_buf) + 1);    }  snprintf (buf, sizeof buf, "%s: ", proto_str);  write (vty->fd, buf, strlen (proto_str) + 2);  len = vsnprintf (buf, sizeof buf, format, va);  if (len < 0)    return -1;  write (vty->fd, (u_char *)buf, len);  snprintf (buf, sizeof buf, "\r\n");  write (vty->fd, buf, 2);  return len;}/* Output current time to the vty. */voidvty_time_print (struct vty *vty, int cr){  int ret;  char buf [TIME_BUF];   ret = time_str (buf);  if (ret == 0)    {      zlog (NULL, LOG_INFO, "strftime error");      return;    }  if (cr)    vty_out (vty, "%s\n", buf);  else    vty_out (vty, "%s ", buf);  return;}/* Say hello to vty interface. */voidvty_hello (struct vty *vty){  if (host.motd)    vty_out (vty, host.motd);}/* Put out prompt and wait input from user. */static voidvty_prompt (struct vty *vty){  struct utsname names;  const char*hostname;  if (vty->type == VTY_TERM)    {      hostname = host.name;      if (!hostname)	{	  uname (&names);	  hostname = names.nodename;	}      vty_out (vty, cmd_prompt (vty->node), hostname);    }}/* Send WILL TELOPT_ECHO to remote server. */voidvty_will_echo (struct vty *vty){  char cmd[] = { IAC, WILL, TELOPT_ECHO, '\0' };  vty_out (vty, "%s", cmd);}/* Make suppress Go-Ahead telnet option. */static voidvty_will_suppress_go_ahead (struct vty *vty){  char cmd[] = { IAC, WILL, TELOPT_SGA, '\0' };  vty_out (vty, "%s", cmd);}/* Make don't use linemode over telnet. */static voidvty_dont_linemode (struct vty *vty){  char cmd[] = { IAC, DONT, TELOPT_LINEMODE, '\0' };  vty_out (vty, "%s", cmd);}/* Use window size. */static voidvty_do_window_size (struct vty *vty){  char cmd[] = { IAC, DO, TELOPT_NAWS, '\0' };  vty_out (vty, "%s", cmd);}#if 0 /* Currently not used. *//* Make don't use lflow vty interface. */static voidvty_dont_lflow_ahead (struct vty *vty){  char cmd[] = { IAC, DONT, TELOPT_LFLOW, '\0' };  vty_out (vty, "%s", cmd);}#endif /* 0 *//* Allocate new vty struct. */struct vty *vty_new (){  struct vty *new = XCALLOC (MTYPE_VTY, sizeof (struct vty));  new->obuf = (struct buffer *) buffer_new (100);  new->buf = XCALLOC (MTYPE_VTY, VTY_BUFSIZ);  new->max = VTY_BUFSIZ;  new->sb_buffer = NULL;  return new;}/* Authentication of vty */static voidvty_auth (struct vty *vty, char *buf){  char *passwd = NULL;  enum node_type next_node = 0;  int fail;  char *crypt (const char *, const char *);  switch (vty->node)    {    case AUTH_NODE:      if (host.encrypt)	passwd = host.password_encrypt;      else	passwd = host.password;      if (host.advanced)	next_node = host.enable ? VIEW_NODE : ENABLE_NODE;      else	next_node = VIEW_NODE;      break;    case AUTH_ENABLE_NODE:      if (host.encrypt)	passwd = host.enable_encrypt;      else	passwd = host.enable;      next_node = ENABLE_NODE;      break;    }  if (passwd)    {      if (host.encrypt)	fail = strcmp (crypt(buf, passwd), passwd);      else	fail = strcmp (buf, passwd);    }  else    fail = 1;  if (! fail)    {      vty->fail = 0;      vty->node = next_node;	/* Success ! */    }  else    {      vty->fail++;      if (vty->fail >= 3)	{	  if (vty->node == AUTH_NODE)	    {	      vty_out (vty, "%% Bad passwords, too many failures!%s", VTY_NEWLINE);	      vty->status = VTY_CLOSE;	    }	  else				    {	      /* AUTH_ENABLE_NODE */	      vty->fail = 0;	      vty_out (vty, "%% Bad enable passwords, too many failures!%s", VTY_NEWLINE);	      vty->node = VIEW_NODE;	    }	}    }}/* Command execution over the vty interface. */intvty_command (struct vty *vty, char *buf){  int ret;  vector vline;  /* Split readline string up into the vector */  vline = cmd_make_strvec (buf);  if (vline == NULL)    return CMD_SUCCESS;  ret = cmd_execute_command (vline, vty, NULL);  if (ret != CMD_SUCCESS)    switch (ret)      {      case CMD_WARNING:	if (vty->type == VTY_FILE)	  vty_out (vty, "Warning...%s", VTY_NEWLINE);	break;      case CMD_ERR_AMBIGUOUS:	vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);	break;      case CMD_ERR_NO_MATCH:	vty_out (vty, "%% Unknown command.%s", VTY_NEWLINE);	break;      case CMD_ERR_INCOMPLETE:	vty_out (vty, "%% Command incomplete.%s", VTY_NEWLINE);	break;      }  cmd_free_strvec (vline);  return ret;}char telnet_backward_char = 0x08;char telnet_space_char = ' ';/* Basic function to write buffer to vty. */static voidvty_write (struct vty *vty, char *buf, size_t nbytes){  if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))    return;  /* Should we do buffering here ?  And make vty_flush (vty) ? */  buffer_write (vty->obuf, (u_char *)buf, nbytes);}/* Ensure length of input buffer.  Is buffer is short, double it. */static voidvty_ensure (struct vty *vty, int length){  if (vty->max <= length)    {      vty->max *= 2;      vty->buf = XREALLOC (MTYPE_VTY, vty->buf, vty->max);    }}/* Basic function to insert character into vty. */static voidvty_self_insert (struct vty *vty, char c){  int i;  int length;  vty_ensure (vty, vty->length + 1);  length = vty->length - vty->cp;  memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);  vty->buf[vty->cp] = c;  vty_write (vty, &vty->buf[vty->cp], length + 1);  for (i = 0; i < length; i++)    vty_write (vty, &telnet_backward_char, 1);  vty->cp++;  vty->length++;}/* Self insert character 'c' in overwrite mode. */static voidvty_self_insert_overwrite (struct vty *vty, char c){  vty_ensure (vty, vty->length + 1);  vty->buf[vty->cp++] = c;  if (vty->cp > vty->length)    vty->length++;  if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))    return;  vty_write (vty, &c, 1);}/* Insert a word into vty interface with overwrite mode. */static voidvty_insert_word_overwrite (struct vty *vty, char *str){  int len = strlen (str);  vty_write (vty, str, len);  strcpy (&vty->buf[vty->cp], str);  vty->cp += len;  vty->length = vty->cp;}/* Forward character. */static voidvty_forward_char (struct vty *vty){  if (vty->cp < vty->length)    {      vty_write (vty, &vty->buf[vty->cp], 1);      vty->cp++;    }}/* Backward character. */static voidvty_backward_char (struct vty *vty){  if (vty->cp > 0)    {      vty->cp--;      vty_write (vty, &telnet_backward_char, 1);    }}/* Move to the beginning of the line. */static voidvty_beginning_of_line (struct vty *vty){  while (vty->cp)    vty_backward_char (vty);}/* Move to the end of the line. */static voidvty_end_of_line (struct vty *vty){  while (vty->cp < vty->length)    vty_forward_char (vty);}static void vty_kill_line_from_beginning (struct vty *);static void vty_redraw_line (struct vty *);/* Print command line history.  This function is called from   vty_next_line and vty_previous_line. */static voidvty_history_print (struct vty *vty){  int length;  vty_kill_line_from_beginning (vty);  /* Get previous line from history buffer */  length = strlen (vty->hist[vty->hp]);  memcpy (vty->buf, vty->hist[vty->hp], length);  vty->cp = vty->length = length;  /* Redraw current line */  vty_redraw_line (vty);}/* Show next command line history. */voidvty_next_line (struct vty *vty){  int try_index;  if (vty->hp == vty->hindex)    return;  /* Try is there history exist or not. */  try_index = vty->hp;  if (try_index == (VTY_MAXHIST - 1))    try_index = 0;  else    try_index++;  /* If there is not history return. */  if (vty->hist[try_index] == NULL)    return;  else    vty->hp = try_index;  vty_history_print (vty);}/* Show previous command line history. */voidvty_previous_line (struct vty *vty){  int try_index;  try_index = vty->hp;  if (try_index == 0)    try_index = VTY_MAXHIST - 1;  else    try_index--;  if (vty->hist[try_index] == NULL)    return;  else    vty->hp = try_index;  vty_history_print (vty);}/* This function redraw all of the command line character. */static voidvty_redraw_line (struct vty *vty){  vty_write (vty, vty->buf, vty->length);  vty->cp = vty->length;}/* Forward word. */static voidvty_forward_word (struct vty *vty){  while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')    vty_forward_char (vty);    while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')    vty_forward_char (vty);}/* Backward word without skipping training space. */static voidvty_backward_pure_word (struct vty *vty){  while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')    vty_backward_char (vty);}/* Backward word. */static voidvty_backward_word (struct vty *vty){  while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')    vty_backward_char (vty);  while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')    vty_backward_char (vty);}/* When '^D' is typed at the beginning of the line we move to the down   level. */static voidvty_down_level (struct vty *vty){  vty_out (vty, "%s", VTY_NEWLINE);  config_exit (NULL, vty, 0, NULL);  vty_prompt (vty);  vty->cp = 0;}/* When '^Z' is received from vty, move down to the enable mode. */voidvty_end_config (struct vty *vty){  vty_out (vty, "%s", VTY_NEWLINE);  switch (vty->node)    {    case VIEW_NODE:    case ENABLE_NODE:      /* Nothing to do. */      break;    case CONFIG_NODE:    case INTERFACE_NODE:    case ZEBRA_NODE:    case RIP_NODE:    case RIPNG_NODE:    case BGP_NODE:    case BGP_VPNV4_NODE:    case BGP_IPV4_NODE:    case BGP_IPV4M_NODE:    case BGP_IPV6_NODE:    case RMAP_NODE:    case OSPF_NODE:    case OSPF6_NODE:    case KEYCHAIN_NODE:    case KEYCHAIN_KEY_NODE:    case MASC_NODE:    case VTY_NODE:      vty_config_unlock (vty);      vty->node = ENABLE_NODE;      break;    default:      /* Unknown node, we have to ignore it. */      break;    }  vty_prompt (vty);  vty->cp = 0;}/* Delete a charcter at the current point. */static voidvty_delete_char (struct vty *vty){  int i;  int size;  if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)    return;  if (vty->length == 0)    {      vty_down_level (vty);      return;    }  if (vty->cp == vty->length)    return;			/* completion need here? */  size = vty->length - vty->cp;  vty->length--;  memmove (&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1);  vty->buf[vty->length] = '\0';  vty_write (vty, &vty->buf[vty->cp], size - 1);  vty_write (vty, &telnet_space_char, 1);  for (i = 0; i < size; i++)    vty_write (vty, &telnet_backward_char, 1);}/* Delete a character before the point. */static voidvty_delete_backward_char (struct vty *vty){  if (vty->cp == 0)    return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -