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

📄 vty.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 4 页
字号:
	  break;	case CONTROL('K'):	  vty_kill_line (vty);	  break;	case CONTROL('N'):	  vty_next_line (vty);	  break;	case CONTROL('P'):	  vty_previous_line (vty);	  break;	case CONTROL('T'):	  vty_transpose_chars (vty);	  break;	case CONTROL('U'):	  vty_kill_line_from_beginning (vty);	  break;	case CONTROL('W'):	  vty_backward_kill_word (vty);	  break;	case CONTROL('Z'):	  vty_end_config (vty);	  break;	case '\n':	case '\r':	  vty_out (vty, "%s", VTY_NEWLINE);	  vty_execute (vty);	  break;	case '\t':	  vty_complete_command (vty);	  break;	case '?':	  if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)	    vty_self_insert (vty, buf[i]);	  else	    vty_describe_command (vty);	  break;	case '\033':	  if (i + 1 < nbytes && buf[i + 1] == '[')	    {	      vty->escape = VTY_ESCAPE;	      i++;	    }	  else	    vty->escape = VTY_PRE_ESCAPE;	  break;	default:	  if (buf[i] > 31 && buf[i] < 127)	    vty_self_insert (vty, buf[i]);	  break;	}    }  /* Check status. */  if (vty->status == VTY_CLOSE)    vty_close (vty);  else    {      vty_event (VTY_WRITE, vty_sock, vty);      vty_event (VTY_READ, vty_sock, vty);    }  return 0;}/* Flush buffer to the vty. */static intvty_flush (struct thread *thread){  int erase;  int dont_more;  int vty_sock = THREAD_FD (thread);  struct vty *vty = THREAD_ARG (thread);  vty->t_write = NULL;  /* Tempolary disable read thread. */  if (vty->lines == 0)    if (vty->t_read)      {	thread_cancel (vty->t_read);	vty->t_read = NULL;      }  /* Function execution continue. */  if (vty->status == VTY_START || vty->status == VTY_CONTINUE)    {      if (vty->status == VTY_CONTINUE)	erase = 1;      else	erase = 0;      if (vty->output_func == NULL)	dont_more = 1;      else	dont_more = 0;      if (vty->lines == 0)	{	  erase = 0;	  dont_more = 1;	}      buffer_flush_vty_all (vty->obuf, vty->fd, erase, dont_more);      if (vty->status == VTY_CLOSE)	{	  vty_close (vty);	  return 0;	}      if (vty->output_func == NULL)	{	  vty->status = VTY_NORMAL;	  vty_prompt (vty);	  vty_event (VTY_WRITE, vty_sock, vty);	}      else	vty->status = VTY_MORE;      if (vty->lines == 0)	{	  if (vty->output_func == NULL)	    vty_event (VTY_READ, vty_sock, vty);	  else	    {	      if (vty->output_func)		(*vty->output_func) (vty, 0);	      vty_event (VTY_WRITE, vty_sock, vty);	    }	}    }  else    {      if (vty->status == VTY_MORE || vty->status == VTY_MORELINE)	erase = 1;      else	erase = 0;      if (vty->lines == 0)	buffer_flush_window (vty->obuf, vty->fd, vty->width, 25, 0, 1);      else if (vty->status == VTY_MORELINE)	buffer_flush_window (vty->obuf, vty->fd, vty->width, 1, erase, 0);      else	buffer_flush_window (vty->obuf, vty->fd, vty->width,			     vty->lines >= 0 ? vty->lines : vty->height,			     erase, 0);        if (buffer_empty (vty->obuf))	{	  if (vty->status == VTY_CLOSE)	    vty_close (vty);	  else	    {	      vty->status = VTY_NORMAL;	  	      if (vty->lines == 0)		vty_event (VTY_READ, vty_sock, vty);	    }	}      else	{	  vty->status = VTY_MORE;	  if (vty->lines == 0)	    vty_event (VTY_WRITE, vty_sock, vty);	}    }  return 0;}/* Create new vty structure. */struct vty *vty_create (int vty_sock, union sockunion *su){  struct vty *vty;  /* Allocate new vty structure and set up default values. */  vty = vty_new ();  vty->fd = vty_sock;  vty->type = VTY_TERM;  vty->address = sockunion_su2str (su);  if (no_password_check)    {      if (host.advanced)	vty->node = ENABLE_NODE;      else	vty->node = VIEW_NODE;    }  else    vty->node = AUTH_NODE;  vty->fail = 0;  vty->cp = 0;  vty_clear_buf (vty);  vty->length = 0;  memset (vty->hist, 0, sizeof (vty->hist));  vty->hp = 0;  vty->hindex = 0;  vector_set_index (vtyvec, vty_sock, vty);  vty->status = VTY_NORMAL;  vty->v_timeout = vty_timeout_val;  if (host.lines >= 0)    vty->lines = host.lines;  else    vty->lines = -1;  vty->iac = 0;  vty->iac_sb_in_progress = 0;  vty->sb_buffer = buffer_new (1024);  if (! no_password_check)    {      /* Vty is not available if password isn't set. */      if (host.password == NULL && host.password_encrypt == NULL)	{	  vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE);	  vty->status = VTY_CLOSE;	  vty_close (vty);	  return NULL;	}    }  /* Say hello to the world. */  vty_hello (vty);  if (! no_password_check)    vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);  /* Setting up terminal. */  vty_will_echo (vty);  vty_will_suppress_go_ahead (vty);  vty_dont_linemode (vty);  vty_do_window_size (vty);  /* vty_dont_lflow_ahead (vty); */  vty_prompt (vty);  /* Add read/write thread. */  vty_event (VTY_WRITE, vty_sock, vty);  vty_event (VTY_READ, vty_sock, vty);  return vty;}/* Accept connection from the network. */static intvty_accept (struct thread *thread){  int vty_sock;  struct vty *vty;  union sockunion su;  int ret;  unsigned int on;  int accept_sock;  struct prefix *p = NULL;  struct access_list *acl = NULL;  accept_sock = THREAD_FD (thread);  /* We continue hearing vty socket. */  vty_event (VTY_SERV, accept_sock, NULL);  memset (&su, 0, sizeof (union sockunion));  /* We can handle IPv4 or IPv6 socket. */  vty_sock = sockunion_accept (accept_sock, &su);  if (vty_sock < 0)    {      zlog_warn ("can't accept vty socket : %s", strerror (errno));      return -1;    }  p = sockunion2hostprefix (&su);  /* VTY's accesslist apply. */  if (p->family == AF_INET && vty_accesslist_name)    {      if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) &&	  (access_list_apply (acl, p) == FILTER_DENY))	{	  char *buf;	  zlog (NULL, LOG_INFO, "Vty connection refused from %s",		(buf = sockunion_su2str (&su)));	  free (buf);	  close (vty_sock);	  	  /* continue accepting connections */	  vty_event (VTY_SERV, accept_sock, NULL);	  	  prefix_free (p);	  return 0;	}    }#ifdef HAVE_IPV6  /* VTY's ipv6 accesslist apply. */  if (p->family == AF_INET6 && vty_ipv6_accesslist_name)    {      if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) &&	  (access_list_apply (acl, p) == FILTER_DENY))	{	  char *buf;	  zlog (NULL, LOG_INFO, "Vty connection refused from %s",		(buf = sockunion_su2str (&su)));	  free (buf);	  close (vty_sock);	  	  /* continue accepting connections */	  vty_event (VTY_SERV, accept_sock, NULL);	  	  prefix_free (p);	  return 0;	}    }#endif /* HAVE_IPV6 */    prefix_free (p);  on = 1;  ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY, 		    (char *) &on, sizeof (on));  if (ret < 0)    zlog (NULL, LOG_INFO, "can't set sockopt to vty_sock : %s", 	  strerror (errno));  vty = vty_create (vty_sock, &su);  return 0;}#if defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO)voidvty_serv_sock_addrinfo (const char *hostname, unsigned short port){  int ret;  struct addrinfo req;  struct addrinfo *ainfo;  struct addrinfo *ainfo_save;  int sock;  char port_str[BUFSIZ];  memset (&req, 0, sizeof (struct addrinfo));  req.ai_flags = AI_PASSIVE;  req.ai_family = AF_UNSPEC;  req.ai_socktype = SOCK_STREAM;  sprintf (port_str, "%d", port);  port_str[sizeof (port_str) - 1] = '\0';  ret = getaddrinfo (hostname, port_str, &req, &ainfo);  if (ret != 0)    {      fprintf (stderr, "getaddrinfo failed: %s\n", gai_strerror (ret));      exit (1);    }  ainfo_save = ainfo;  do    {      if (ainfo->ai_family != AF_INET#ifdef HAVE_IPV6	  && ainfo->ai_family != AF_INET6#endif /* HAVE_IPV6 */	  )	continue;      sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);      if (sock < 0)	continue;      sockopt_reuseaddr (sock);      sockopt_reuseport (sock);      ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);      if (ret < 0)	{	  close (sock);	/* Avoid sd leak. */	  continue;	}      ret = listen (sock, 3);      if (ret < 0) 	{	  close (sock);	/* Avoid sd leak. */	  continue;	}      vty_event (VTY_SERV, sock, NULL);    }  while ((ainfo = ainfo->ai_next) != NULL);  freeaddrinfo (ainfo_save);}#endif /* ! (defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO)) *//* Make vty server socket. */voidvty_serv_sock_family (unsigned short port, int family){  int ret;  union sockunion su;  int accept_sock;  memset (&su, 0, sizeof (union sockunion));  su.sa.sa_family = family;  /* Make new socket. */  accept_sock = sockunion_stream_socket (&su);  if (accept_sock < 0)    return;  /* This is server, so reuse address. */  sockopt_reuseaddr (accept_sock);  sockopt_reuseport (accept_sock);  /* Bind socket to universal address and given port. */  ret = sockunion_bind (accept_sock, &su, port, NULL);  if (ret < 0)    {      close (accept_sock);	/* Avoid sd leak. */      return;    }  /* Listen socket under queue 3. */  ret = listen (accept_sock, 3);  if (ret < 0)     {      zlog (NULL, LOG_WARNING, "can't listen socket");      close (accept_sock);	/* Avoid sd leak. */      return;    }  /* Add vty server event. */  vty_event (VTY_SERV, accept_sock, NULL);}#ifdef VTYSH/* For sockaddr_un. */#include <sys/un.h>/* VTY shell UNIX domain socket. */voidvty_serv_un (char *path){  int ret;  int sock, len;  struct sockaddr_un serv;  mode_t old_mask;  /* First of all, unlink existing socket */  unlink (path);  /* Set umask */  old_mask = umask (0077);  /* Make UNIX domain socket. */  sock = socket (AF_UNIX, SOCK_STREAM, 0);  if (sock < 0)    {      perror ("sock");      return;    }  /* Make server socket. */  memset (&serv, 0, sizeof (struct sockaddr_un));  serv.sun_family = AF_UNIX;  strncpy (serv.sun_path, path, strlen (path));#ifdef HAVE_SUN_LEN  len = serv.sun_len = SUN_LEN(&serv);#else  len = sizeof (serv.sun_family) + strlen (serv.sun_path);#endif /* HAVE_SUN_LEN */  ret = bind (sock, (struct sockaddr *) &serv, len);  if (ret < 0)    {      perror ("bind");      close (sock);	/* Avoid sd leak. */      return;    }  ret = listen (sock, 5);  if (ret < 0)    {      perror ("listen");      close (sock);	/* Avoid sd leak. */      return;    }  umask (old_mask);  vty_event (VTYSH_SERV, sock, NULL);}/* #define VTYSH_DEBUG 1 */static intvtysh_accept (struct thread *thread){  int accept_sock;  int sock;  int client_len;  struct sockaddr_un client;  struct vty *vty;    accept_sock = THREAD_FD (thread);  vty_event (VTYSH_SERV, accept_sock, NULL);  memset (&client, 0, sizeof (struct sockaddr_un));  client_len = sizeof (struct sockaddr_un);  sock = accept (accept_sock, (struct sockaddr *) &client, &client_len);  if (sock < 0)    {      zlog_warn ("can't accept vty socket : %s", strerror (errno));      return -1;    }#ifdef VTYSH_DEBUG  printf ("VTY shell accept\n");#endif /* VTYSH_DEBUG */  vty = vty_new ();  vty->fd = sock;  vty->type = VTY_SHELL_SERV;  vty->node = VIEW_NODE;  vty_event (VTYSH_READ, sock, vty);  return 0;}static intvtysh_read (struct thread *thread){  int ret;  int sock;  int nbytes;  struct vty *vty;  unsigned char buf[VTY_READ_BUFSIZ];  u_char header[4] = {0, 0, 0, 0};  sock = THREAD_FD (thread);  vty = THREAD_ARG (thread);  vty->t_read = NULL;  nbytes = read (sock, buf, VTY_READ_BUFSIZ);  if (nbytes <= 0)    {      vty_close (vty);#ifdef VTYSH_DEBUG      printf ("close vtysh\n");#endif /* VTYSH_DEBUG */      return 0;    }#ifdef VTYSH_DEBUG  printf ("line: %s\n", buf);#endif /* VTYSH_DEBUG */  vty_ensure (vty, nbytes);  memcpy (vty->buf, buf, nbytes);    /* Pass this line to parser. */  ret = vty_execute (vty);  vty_clear_buf (vty);  /* Return result. */#ifdef VTYSH_DEBUG  printf ("result: %d\n", ret);  printf ("vtysh node: %d\n", vty->node);#endif /* VTYSH_DEBUG */  header[3] = ret;  write (vty->fd, header, 4);  vty_event (VTYSH_READ, sock, vty);  return 0;}#endif /* VTYSH *//* Determine address family to bind. */voidvty_serv_sock (const char *hostname, unsigned short port, char *path){  /* If port is set to 0, do not listen on TCP/IP at all! */  if (port)    {#if defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO)      vty_serv_sock_addrinfo (hostname, port);#else /* ! (defined(HAVE_IPV6) || defined(HAVE_GETADDRINFO)) */      vty_serv_sock_family (port, AF_INET);#endif /* HAVE_IPV6 */    }#ifdef VTYSH  vty_serv_un (path);#endif /* VTYSH */}/* Close vty interface. */voidvty_close (struct vty *vty){  int i;  /* Cancel threads.*/  if (vty->t_read)    thread_cancel (vty->t_read);  if (vty->t_write)    thread_cancel (vty->t_write);  if (vty->t_timeout)    thread_cancel (vty->t_timeout);  if (vty->t_output)    thread_cancel (vty->t_output);  /* Flush buffer. */  if (! buffer_empty (vty->obuf))    buffer_flush_all (vty->obuf, vty->fd);  /* Free input buffer. */  buffer_free (vty->obuf);  /* Free SB buffer. */  if (vty->sb_buffer)    buffer_free (vty->sb_buffer);  /* Free command history. */  for (i = 0; i < VTY_MAXHIST; i++)    if (vty->hist[i])      XFREE (MTYPE_VTY_HIST, vty->hist[i]);  /* Unset vector. */  vector_unset (vtyvec, vty->fd);  /* Close socket. */  if (vty->fd > 0)    close (vty->fd);  if (vty->address)    XFREE (0, vty->address);  if (vty->buf)    XFREE (MTYPE_VTY, vty->buf);  /* Check configure. */  vty_config_unlock (vty);  /* OK free vty. */  XFREE (MTYPE_VTY, vty);}/* When time out occur output message then close connection. */static intvty_timeout (struct thread *thread){  struct vty *vty;  vty = THREAD_ARG (thread);  vty->t_timeout = NULL;  vty->v_timeout = 0;  /* Clear buffer*/  buffer_reset (vty->obuf);  vty_out (vty, "%sVty connection is timed out.%s", VTY_NEWLINE, VTY_NEWLINE);  /* Close connection. */  vty->status = VTY_CLOSE;  vty_close (vty);  return 0;}/* Read up configuration file from file_name. */static voidvty_read_file (FILE *confp){  int ret;  struct vty *vty;  vty = vty_new ();  vty->fd = 0;			/* stdout */  vty->type = VTY_TERM;  vty->node = CONFIG_NODE;    /* Execute configuration file */  ret = config_from_file (vty, confp);  if (ret != CMD_SUCCESS)     {      switch (ret)	{	case CMD_ERR_AMBIGUOUS:	  fprintf (stderr, "Ambiguous command.\n");	  break;	case CMD_ERR_NO_MATCH:	  fprintf (stderr, "There is no such command.\n");	  break;	}      fprintf (stderr, "Error occured during reading below line.\n%s\n", 

⌨️ 快捷键说明

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