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

📄 dev_vtty.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * Virtual console TTY. * * "Interactive" part idea by Mtve. * TCP console added by Mtve. * Serial console by Peter Ross (suxen_drol@hotmail.com) *//* By default, Cygwin supports only 64 FDs with select()! */#ifdef __CYGWIN__#define FD_SETSIZE 1024#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <termios.h>#include <fcntl.h>#include <errno.h>#include <assert.h>#include <arpa/telnet.h>#include "mips64.h"#include "cp0.h"#include "cpu.h"#include "dynamips.h"#include "mips64_exec.h"#include "device.h"#include "memory.h"#include "dev_c7200.h"#include "dev_c3600.h"#include "dev_vtty.h"#include "vm.h"#include "utils.h"/* VTTY list */static pthread_mutex_t vtty_list_mutex = PTHREAD_MUTEX_INITIALIZER;static vtty_t *vtty_list = NULL;static pthread_t vtty_thread;#define VTTY_LIST_LOCK()   pthread_mutex_lock(&vtty_list_mutex);#define VTTY_LIST_UNLOCK() pthread_mutex_unlock(&vtty_list_mutex);static struct termios tios,tios_orig;/* Send Telnet command: WILL TELOPT_ECHO */static void vtty_telnet_will_echo(vtty_t *vtty){   u_char cmd[] = { IAC, WILL, TELOPT_ECHO };   write(vtty->fd,cmd,sizeof(cmd));}/* Send Telnet command: Suppress Go-Ahead */static void vtty_telnet_will_suppress_go_ahead(vtty_t *vtty){   u_char cmd[] = { IAC, WILL, TELOPT_SGA };   write(vtty->fd,cmd,sizeof(cmd));}/* Send Telnet command: Don't use linemode */static void vtty_telnet_dont_linemode(vtty_t *vtty){   u_char cmd[] = { IAC, DONT, TELOPT_LINEMODE };   write(vtty->fd,cmd,sizeof(cmd));}/* Send Telnet command: does the client support terminal type message? */static void vtty_telnet_do_ttype(vtty_t *vtty){   u_char cmd[] = { IAC, DO, TELOPT_TTYPE };   write(vtty->fd,cmd,sizeof(cmd));}/* Restore TTY original settings */static void vtty_term_reset(void){   tcsetattr(STDIN_FILENO,TCSANOW,&tios_orig);}/* Initialize real TTY */static void vtty_term_init(void){   tcgetattr(STDIN_FILENO,&tios);   memcpy(&tios_orig,&tios,sizeof(struct termios));   atexit(vtty_term_reset);   tios.c_cc[VTIME] = 0;   tios.c_cc[VMIN] = 1;   /* Disable Ctrl-C, Ctrl-S, Ctrl-Q and Ctrl-Z */   tios.c_cc[VINTR] = 0;   tios.c_cc[VSTART] = 0;   tios.c_cc[VSTOP] = 0;   tios.c_cc[VSUSP] = 0;   tios.c_lflag &= ~(ICANON|ECHO);   tios.c_iflag &= ~ICRNL;   tcsetattr(STDIN_FILENO, TCSANOW, &tios);   tcflush(STDIN_FILENO,TCIFLUSH);}/* Wait for a TCP connection */static int vtty_tcp_conn_wait(vtty_t *vtty){   struct sockaddr_in serv;   int one = 1;   vtty->state = VTTY_STATE_TCP_INVALID;   if ((vtty->accept_fd = socket(PF_INET,SOCK_STREAM,0)) < 0) {      perror("vtty_tcp_waitcon: socket");      return(-1);   }   if (setsockopt(vtty->accept_fd,SOL_SOCKET,SO_REUSEADDR,                  &one,sizeof(one)) < 0)    {      perror("vtty_tcp_waitcon: setsockopt(SO_REUSEADDR)");      goto error;   }   memset(&serv,0,sizeof(serv));   serv.sin_family = AF_INET;   serv.sin_addr.s_addr = htonl(INADDR_ANY);   serv.sin_port = htons(vtty->tcp_port);   if (bind(vtty->accept_fd,(struct sockaddr *)&serv,sizeof(serv)) < 0) {      perror("vtty_tcp_waitcon: bind");      goto error;   }   if (listen(vtty->accept_fd,1) < 0) {      perror("vtty_tcp_waitcon: listen");      goto error;   }   vm_log(vtty->vm,"VTTY","%s: waiting connection on tcp port %d (FD %d)\n",          vtty->name,vtty->tcp_port,vtty->accept_fd);      vtty->select_fd = &vtty->accept_fd;   vtty->state = VTTY_STATE_TCP_WAITING;   return(0); error:   close(vtty->accept_fd);   vtty->accept_fd = -1;   vtty->select_fd = NULL;   return(-1);}/* Accept a TCP connection */static int vtty_tcp_conn_accept(vtty_t *vtty){   if ((vtty->fd = accept(vtty->accept_fd,NULL,NULL)) < 0) {      fprintf(stderr,"vtty_tcp_conn_accept: accept on port %d failed %s\n",              vtty->tcp_port,strerror(errno));      return(-1);   }   vm_log(vtty->vm,"VTTY","%s is now connected (accept_fd=%d,conn_fd=%d)\n",          vtty->name,vtty->accept_fd,vtty->fd);   /* Adapt Telnet settings */   if (vtty->terminal_support) {      vtty_telnet_do_ttype(vtty);      vtty_telnet_will_echo(vtty);      vtty_telnet_will_suppress_go_ahead(vtty);      vtty_telnet_dont_linemode(vtty);      vtty->input_state = VTTY_INPUT_TELNET;   }   if (!(vtty->fstream = fdopen(vtty->fd, "wb"))) {      close(vtty->fd);      vtty->fd = -1;      return(-1);   }   fprintf(vtty->fstream,           "Connected to Dynamips VM \"%s\" (ID %u, type %s) - %s\r\n\r\n",            vtty->vm->name, vtty->vm->instance_id, vm_get_type(vtty->vm),           vtty->name);   vtty->select_fd = &vtty->fd;   vtty->state = VTTY_STATE_TCP_RUNNING;   return(0);}/*  * Parse serial interface descriptor string, return 0 if success * string takes the form "device:baudrate:databits:parity:stopbits:hwflow" * device is mandatory, other options are optional (default=9600,8,N,1,0). */int vtty_parse_serial_option(vtty_serial_option_t *option, char *optarg){   char *array[6];   int count;   if ((count = m_strtok(optarg, ':', array, 6)) < 1) {      fprintf(stderr,"vtty_parse_serial_option: invalid string\n");      return(-1);   }   if (!(option->device = strdup(array[0]))) {      fprintf(stderr,"vtty_parse_serial_option: unable to copy string\n");      return(-1);   }      option->baudrate = (count>1) ? atoi(array[1]) : 9600;   option->databits = (count>2) ? atoi(array[2]) : 8;   if (count > 3) {      switch(*array[3]) {         case 'o':         case 'O':             option->parity = 1;  /* odd */         case 'e':         case 'E':             option->parity = 2;  /* even */         default:            option->parity = 0;  /* none */      }   } else {      option->parity = 0;   }   option->stopbits = (count>4) ? atoi(array[4]) : 1;   option->hwflow   = (count>5) ? atoi(array[5]) : 0;   return(0);}#if defined(__CYGWIN__) || defined(SUNOS)void cfmakeraw(struct termios *termios_p) {    termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|                            INLCR|IGNCR|ICRNL|IXON);    termios_p->c_oflag &= ~OPOST;    termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);    termios_p->c_cflag &= ~(CSIZE|PARENB);    termios_p->c_cflag |= CS8;}#endif/*  * Setup serial port, return 0 if success. */static int vtty_serial_setup(vtty_t *vtty, const vtty_serial_option_t *option){   struct termios tio;   int tio_baudrate;   if (tcgetattr(vtty->fd, &tio) != 0) {       fprintf(stderr, "error: tcgetattr failed\n");      return(-1);   }   cfmakeraw(&tio);   tio.c_cflag = 0      |CLOCAL     // ignore modem control lines      ;   tio.c_cflag &= ~CREAD;   tio.c_cflag |= CREAD;   switch(option->baudrate) {      case 50     : tio_baudrate = B50; break;      case 75     : tio_baudrate = B75; break;      case 110    : tio_baudrate = B110; break;      case 134    : tio_baudrate = B134; break;      case 150    : tio_baudrate = B150; break;      case 200    : tio_baudrate = B200; break;      case 300    : tio_baudrate = B300; break;      case 600    : tio_baudrate = B600; break;      case 1200   : tio_baudrate = B1200; break;      case 1800   : tio_baudrate = B1800; break;      case 2400   : tio_baudrate = B2400; break;      case 4800   : tio_baudrate = B4800; break;      case 9600   : tio_baudrate = B9600; break;      case 19200  : tio_baudrate = B19200; break;      case 38400  : tio_baudrate = B38400; break;      case 57600  : tio_baudrate = B57600; break;#if defined(B76800)      case 76800  : tio_baudrate = B76800; break;#endif      case 115200 : tio_baudrate = B115200; break;#if defined(B230400)      case 230400 : tio_baudrate = B230400; break;#endif      default:         fprintf(stderr, "error: unsupported baudrate\n");         return(-1);   }   cfsetospeed(&tio, tio_baudrate);   cfsetispeed(&tio, tio_baudrate);   tio.c_cflag &= ~CSIZE; /* clear size flag */   switch(option->databits) {      case 5 : tio.c_cflag |= CS5; break;      case 6 : tio.c_cflag |= CS6; break;      case 7 : tio.c_cflag |= CS7; break;      case 8 : tio.c_cflag |= CS8; break;      default :         fprintf(stderr, "error: unsupported databits\n");         return(-1);   }   tio.c_iflag &= ~INPCK;  /* clear parity flag */   tio.c_cflag &= ~(PARENB|PARODD);   switch(option->parity) {      case 0 : break;      case 2 : tio.c_iflag|=INPCK; tio.c_cflag|=PARENB; break;  /* even */      case 1 : tio.c_iflag|=INPCK; tio.c_cflag|=PARENB|PARODD; break; /* odd */      default:         fprintf(stderr, "error: unsupported parity\n");         return(-1);   }   tio.c_cflag &= ~CSTOPB; /* clear stop flag */   switch(option->stopbits) {      case 1 : break;      case 2 : tio.c_cflag |= CSTOPB; break;      default :         fprintf(stderr, "error: unsupported stopbits\n");         return(-1);   }#if defined(CRTSCTS)   tio.c_cflag &= ~CRTSCTS;#endif#if defined(CNEW_RTSCTS)   tio.c_cflag &= ~CNEW_RTSCTS;#endif   if (option->hwflow) {#if defined(CRTSCTS)      tio.c_cflag |= CRTSCTS;#else      tio.c_cflag |= CNEW_RTSCTS;#endif   }   tio.c_cc[VTIME] = 0;   tio.c_cc[VMIN] = 1; /* block read() until one character is available */#if 0   /* not neccessary unless O_NONBLOCK used */   if (fcntl(vtty->fd, F_SETFL, 0) != 0) {  /* enable blocking mode */      fprintf(stderr, "error: fnctl F_SETFL failed\n");      return(-1);   }#endif     if (tcflush(vtty->fd, TCIOFLUSH) != 0) {      fprintf(stderr, "error: tcflush failed\n");      return(-1);   }     if (tcsetattr(vtty->fd, TCSANOW, &tio) != 0 ) {      fprintf(stderr, "error: tcsetattr failed\n");      return(-1);   }   return(0);}/* Create a virtual tty */vtty_t *vtty_create(vm_instance_t *vm,char *name,int type,int tcp_port,                    const vtty_serial_option_t *option){   vtty_t *vtty;   if (!(vtty = malloc(sizeof(*vtty)))) {      fprintf(stderr,"VTTY: unable to create new virtual tty.\n");      return NULL;   }   memset(vtty,0,sizeof(*vtty));   vtty->name = name;   vtty->type = type;   vtty->vm   = vm;   vtty->fd   = -1;   vtty->fstream = NULL;   vtty->accept_fd = -1;   pthread_mutex_init(&vtty->lock,NULL);   vtty->terminal_support = 1;   vtty->input_state = VTTY_INPUT_TEXT;      switch (vtty->type) {      case VTTY_TYPE_NONE:         vtty->select_fd = NULL;         break;      case VTTY_TYPE_TERM:         vtty_term_init();         vtty->fd = STDIN_FILENO;         vtty->select_fd = &vtty->fd;         vtty->fstream = stdout;         break;      case VTTY_TYPE_TCP:         vtty->tcp_port = tcp_port;         vtty_tcp_conn_wait(vtty);         break;      case VTTY_TYPE_SERIAL:         vtty->fd = open(option->device, O_RDWR);         if (vtty->fd < 0) {            fprintf(stderr,"VTTY: open failed\n");            free(vtty);            return NULL;         }         if (vtty_serial_setup(vtty,option)) {            fprintf(stderr,"VTTY: setup failed\n");            close(vtty->fd);            free(vtty);            return NULL;         }         vtty->select_fd = &vtty->fd;         vtty->terminal_support = 0;         break;      default:         fprintf(stderr,"tty_create: bad vtty type %d\n",vtty->type);         return NULL;   }   /* Add this new VTTY to the list */   VTTY_LIST_LOCK();   vtty->next = vtty_list;   vtty->pprev = &vtty_list;   if (vtty_list != NULL)      vtty_list->pprev = &vtty->next;   vtty_list = vtty;   VTTY_LIST_UNLOCK();   return vtty;}/* Delete a virtual tty */void vtty_delete(vtty_t *vtty){   if (vtty != NULL) {      if (vtty->pprev != NULL) {         VTTY_LIST_LOCK();         if (vtty->next)            vtty->next->pprev = vtty->pprev;         *(vtty->pprev) = vtty->next;         VTTY_LIST_UNLOCK();      }      if ((vtty->fstream) && (vtty->fstream != stdout))         fclose(vtty->fstream);      /* We don't close FD 0 since it is stdin */      if (vtty->fd > 0) {         vm_log(vtty->vm,"VTTY","%s: closing FD %d\n",vtty->name,vtty->fd);         close(vtty->fd);      }      if (vtty->accept_fd != -1) {         vm_log(vtty->vm,"VTTY","%s: closing accept FD %d\n",                vtty->name,vtty->accept_fd);         close(vtty->accept_fd);      }      free(vtty);   }}/* Store a character in the FIFO buffer */static int vtty_store(vtty_t *vtty,u_char c){   u_int nwptr;   VTTY_LOCK(vtty);   nwptr = vtty->write_ptr + 1;   if (nwptr == VTTY_BUFFER_SIZE)      nwptr = 0;   if (nwptr == vtty->read_ptr) {      VTTY_UNLOCK(vtty);      return(-1);   }   vtty->buffer[vtty->write_ptr] = c;   vtty->write_ptr = nwptr;   VTTY_UNLOCK(vtty);   return(0);}/* Store a string in the FIFO buffer */int vtty_store_str(vtty_t *vtty,char *str){   if (!vtty)      return(0);   while(*str != 0) {      if (vtty_store(vtty,*str) == -1)         return(-1);            str++;   }   vtty->input_pending = TRUE;   return(0);}/* Store CTRL+C in buffer */int vtty_store_ctrlc(vtty_t *vtty){   if (vtty)      vtty_store(vtty,0x03);   return(0);}/*  * Read a character from the terminal. */static int vtty_term_read(vtty_t *vtty){

⌨️ 快捷键说明

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