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

📄 net_io.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * Network Input/Output Abstraction Layer. *//* 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 <stdarg.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include <fcntl.h>#include <ctype.h>#include <time.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/un.h>#include <sys/wait.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <pthread.h>#ifdef __linux__#include <net/if.h>#include <linux/if_tun.h>#endif#include "registry.h"#include "net.h"#include "net_io.h"#include "net_io_filter.h"/* Free a NetIO descriptor */static int netio_free(void *data,void *arg);/* NIO RX listener */static pthread_mutex_t netio_rxl_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t netio_rxq_mutex = PTHREAD_MUTEX_INITIALIZER;static struct netio_rx_listener *netio_rxl_list = NULL;static struct netio_rx_listener *netio_rxl_add_list = NULL;static netio_desc_t *netio_rxl_remove_list = NULL;static pthread_t netio_rxl_thread;static pthread_cond_t netio_rxl_cond;#define NETIO_RXL_LOCK()   pthread_mutex_lock(&netio_rxl_mutex);#define NETIO_RXL_UNLOCK() pthread_mutex_unlock(&netio_rxl_mutex);#define NETIO_RXQ_LOCK()   pthread_mutex_lock(&netio_rxq_mutex);#define NETIO_RXQ_UNLOCK() pthread_mutex_unlock(&netio_rxq_mutex);/* NetIO type */typedef struct {   char *name;   char *desc;}netio_type_t;/* NETIO types (must follow the enum definition) */static netio_type_t netio_types[NETIO_TYPE_MAX] = {   { "unix"      , "UNIX local sockets" },   { "vde"       , "Virtual Distributed Ethernet / UML switch" },   { "tap"       , "Linux/FreeBSD TAP device" },   { "udp"       , "UDP sockets" },   { "tcp_cli"   , "TCP client" },   { "tcp_ser"   , "TCP server" },#ifdef LINUX_ETH   { "linux_eth" , "Linux Ethernet device" },#endif#ifdef GEN_ETH   { "gen_eth"   , "Generic Ethernet device (PCAP)" },#endif   { "fifo"      , "FIFO (intra-hypervisor)" },   { "null"      , "Null device" },};/* Get NETIO type given a description */int netio_get_type(char *type){   int i;   for(i=0;i<NETIO_TYPE_MAX;i++)      if (!strcmp(type,netio_types[i].name))         return(i);   return(-1);}/* Show the NETIO types */void netio_show_types(void){   int i;   printf("Available NETIO types:\n");   for(i=0;i<NETIO_TYPE_MAX;i++)      printf("  * %-10s : %s\n",netio_types[i].name,netio_types[i].desc);   printf("\n");}/* * ========================================================================= * Generic functions (abstraction layer) * ========================================================================= *//* Acquire a reference to NIO from registry (increment reference count) */netio_desc_t *netio_acquire(char *name){   return(registry_find(name,OBJ_TYPE_NIO));}/* Release an NIO (decrement reference count) */int netio_release(char *name){   return(registry_unref(name,OBJ_TYPE_NIO));}/* Record an NIO in registry */static int netio_record(netio_desc_t *nio){   return(registry_add(nio->name,OBJ_TYPE_NIO,nio));}/* Create a new NetIO descriptor */static netio_desc_t *netio_create(char *name){   netio_desc_t *nio;   if (!(nio = malloc(sizeof(*nio))))      return NULL;   /* setup as a NULL descriptor */   memset(nio,0,sizeof(*nio));   nio->type = NETIO_TYPE_NULL;   /* save name for registry */   if (!(nio->name = strdup(name))) {      free(nio);      return NULL;   }   return nio;}/* Delete a NetIO descriptor */int netio_delete(char *name){   return(registry_delete_if_unused(name,OBJ_TYPE_NIO,netio_free,NULL));}/* Delete all NetIO descriptors */int netio_delete_all(void){   return(registry_delete_type(OBJ_TYPE_NIO,netio_free,NULL));}/* Save the configuration of a NetIO descriptor */void netio_save_config(netio_desc_t *nio,FILE *fd){   if (nio->save_cfg)      nio->save_cfg(nio,fd);}/* Save configurations of all NetIO descriptors */static void netio_reg_save_config(registry_entry_t *entry,void *opt,int *err){   netio_save_config((netio_desc_t *)entry->data,(FILE *)opt);}void netio_save_config_all(FILE *fd){   registry_foreach_type(OBJ_TYPE_NIO,netio_reg_save_config,fd,NULL);   fprintf(fd,"\n");}/* Send a packet through a NetIO descriptor */ssize_t netio_send(netio_desc_t *nio,void *pkt,size_t len){   int res;   if (!nio)      return(-1);   if (nio->debug) {      printf("NIO %s: sending a packet of %lu bytes:\n",nio->name,(u_long)len);      mem_dump(stdout,pkt,len);   }   /* Apply the TX filter */   if (nio->tx_filter != NULL) {      res = nio->tx_filter->pkt_handler(nio,pkt,len,nio->tx_filter_data);      if (res <= 0)         return(-1);   }   return(nio->send(nio->dptr,pkt,len));}/* Receive a packet through a NetIO descriptor */ssize_t netio_recv(netio_desc_t *nio,void *pkt,size_t max_len){   ssize_t len;   int res;   if (!nio)      return(-1);   /* Receive the packet */   if ((len = nio->recv(nio->dptr,pkt,max_len)) <= 0)      return(-1);   if (nio->debug) {      printf("NIO %s: receiving a packet of %ld bytes:\n",nio->name,(long)len);      mem_dump(stdout,pkt,len);   }   /* Apply the RX filter */   if (nio->rx_filter != NULL) {      res = nio->rx_filter->pkt_handler(nio,pkt,len,nio->rx_filter_data);      if (res == NETIO_FILTER_ACTION_DROP)         return(-1);   }   return(len);}/* Get a NetIO FD */int netio_get_fd(netio_desc_t *nio){   int fd = -1;   switch(nio->type) {      case NETIO_TYPE_UNIX:         fd = nio->u.nud.fd;         break;      case NETIO_TYPE_VDE:         fd = nio->u.nvd.data_fd;         break;      case NETIO_TYPE_TAP:         fd = nio->u.ntd.fd;         break;      case NETIO_TYPE_TCP_CLI:      case NETIO_TYPE_TCP_SER:      case NETIO_TYPE_UDP:         fd = nio->u.nid.fd;         break;#ifdef LINUX_ETH      case NETIO_TYPE_LINUX_ETH:         fd = nio->u.nled.fd;         break;#endif   }      return(fd);}/* * ========================================================================= * UNIX sockets * ========================================================================= *//* Create an UNIX socket */static int netio_unix_create_socket(netio_unix_desc_t *nud){   struct sockaddr_un local_sock;   if ((nud->fd = socket(AF_UNIX,SOCK_DGRAM,0)) == -1) {      perror("netio_unix: socket");      return(-1);   }   memset(&local_sock,0,sizeof(local_sock));   local_sock.sun_family = AF_UNIX;   strcpy(local_sock.sun_path,nud->local_filename);   if (bind(nud->fd,(struct sockaddr *)&local_sock,sizeof(local_sock)) == -1) {      perror("netio_unix: bind");      return(-1);   }   return(nud->fd);}/* Free a NetIO unix descriptor */static void netio_unix_free(netio_unix_desc_t *nud){   if (nud->fd != -1)      close(nud->fd);   if (nud->local_filename) {      unlink(nud->local_filename);      free(nud->local_filename);   }}/* Allocate a new NetIO UNIX descriptor */static int netio_unix_create(netio_unix_desc_t *nud,char *local,char *remote){   memset(nud,0,sizeof(*nud));   nud->fd = -1;   /* check lengths */   if ((strlen(local) >= sizeof(nud->remote_sock.sun_path)) ||       (strlen(remote) >= sizeof(nud->remote_sock.sun_path)))      goto nomem_error;   if (!(nud->local_filename = strdup(local)))      goto nomem_error;   if (netio_unix_create_socket(nud) == -1)      return(-1);         /* prepare the remote info */   nud->remote_sock.sun_family = AF_UNIX;   strcpy(nud->remote_sock.sun_path,remote);   return(0); nomem_error:   fprintf(stderr,"netio_unix_create: "           "invalid file size or insufficient memory\n");   return(-1);}/* Write a packet to an UNIX socket */static ssize_t netio_unix_send(netio_unix_desc_t *nud,void *pkt,size_t pkt_len){   return(sendto(nud->fd,pkt,pkt_len,0,                 (struct sockaddr *)&nud->remote_sock,                 sizeof(&nud->remote_sock)));}/* Receive a packet from an UNIX socket */static ssize_t netio_unix_recv(netio_unix_desc_t *nud,void *pkt,size_t max_len){   return(recvfrom(nud->fd,pkt,max_len,0,NULL,NULL));}/* Save the NIO configuration */static void netio_unix_save_cfg(netio_desc_t *nio,FILE *fd){   netio_unix_desc_t *nud = nio->dptr;   fprintf(fd,"nio create_unix %s %s %s\n",           nio->name,nud->local_filename,nud->remote_sock.sun_path);}/* Create a new NetIO descriptor with UNIX method */netio_desc_t *netio_desc_create_unix(char *nio_name,char *local,char *remote){   netio_desc_t *nio;      if (!(nio = netio_create(nio_name)))      return NULL;   if (netio_unix_create(&nio->u.nud,local,remote) == -1) {      netio_free(nio,NULL);      return NULL;   }   nio->type     = NETIO_TYPE_UNIX;   nio->send     = (void *)netio_unix_send;   nio->recv     = (void *)netio_unix_recv;   nio->save_cfg = netio_unix_save_cfg;   nio->dptr     = &nio->u.nud;   if (netio_record(nio) == -1) {      netio_free(nio,NULL);      return NULL;   }   return nio;}/* * ========================================================================= * VDE (Virtual Distributed Ethernet) interface * ========================================================================= *//* Free a NetIO VDE descriptor */static void netio_vde_free(netio_vde_desc_t *nvd){   if (nvd->data_fd != -1)       close(nvd->data_fd);   if (nvd->ctrl_fd != -1)       close(nvd->ctrl_fd);   if (nvd->local_filename) {      unlink(nvd->local_filename);      free(nvd->local_filename);   }}/* Create a new NetIO VDE descriptor */static int netio_vde_create(netio_vde_desc_t *nvd,char *control,char *local){   struct sockaddr_un ctrl_sock,tst;   struct vde_request_v3 req;   ssize_t len;   int res;   memset(nvd,0,sizeof(*nvd));   nvd->ctrl_fd = nvd->data_fd = -1;   if ((strlen(control) >= sizeof(ctrl_sock.sun_path)) ||       (strlen(local) >= sizeof(nvd->remote_sock.sun_path))) {      fprintf(stderr,"netio_vde_create: bad filenames specified\n");      return(-1);   }   /* Copy the local filename */   if (!(nvd->local_filename = strdup(local))) {      fprintf(stderr,"netio_vde_create: insufficient memory\n");      return(-1);   }   /* Connect to the VDE switch controller */   nvd->ctrl_fd = socket(AF_UNIX,SOCK_STREAM,0);   if (nvd->ctrl_fd < 0) {      perror("netio_vde_create: socket(control)");      return(-1);   }         memset(&ctrl_sock,0,sizeof(ctrl_sock));   ctrl_sock.sun_family = AF_UNIX;   strcpy(ctrl_sock.sun_path,control);   res = connect(nvd->ctrl_fd,(struct sockaddr *)&ctrl_sock,                 sizeof(ctrl_sock));   if (res < 0) {      perror("netio_vde_create: connect(control)");      return(-1);   }   tst.sun_family = AF_UNIX;   strcpy(tst.sun_path,local);   /* Create the data connection */   nvd->data_fd = socket(AF_UNIX,SOCK_DGRAM,0);   if (nvd->data_fd < 0) {      perror("netio_vde_create: socket(data)");      return(-1);   }   if (bind(nvd->data_fd,(struct sockaddr *)&tst,sizeof(tst))<0) {      perror("netio_vde_create: bind(data)");      return(-1);   }   /* Now, process to registration */   memset(&req,0,sizeof(req));   req.sock.sun_family = AF_UNIX;   strcpy(req.sock.sun_path,local);   req.magic   = VDE_SWITCH_MAGIC;   req.version = VDE_SWITCH_VERSION;   req.type    = VDE_REQ_NEW_CONTROL;      len = write(nvd->ctrl_fd,&req,sizeof(req));   if (len != sizeof(req)) {      perror("netio_vde_create: write(req)");      return(-1);   }   /* Read the remote socket descriptor */   len = read(nvd->ctrl_fd,&nvd->remote_sock,sizeof(nvd->remote_sock));   if (len != sizeof(nvd->remote_sock)) {      perror("netio_vde_create: read(req)");      return(-1);   }   return(0);}/* Write a packet to a VDE data socket */static ssize_t netio_vde_send(netio_vde_desc_t *nvd,void *pkt,size_t pkt_len){   return(sendto(nvd->data_fd,pkt,pkt_len,0,                 (struct sockaddr *)&nvd->remote_sock,                 sizeof(nvd->remote_sock)));}/* Receive a packet from a VDE socket */static ssize_t netio_vde_recv(netio_vde_desc_t *nvd,void *pkt,size_t max_len){   return(recvfrom(nvd->data_fd,pkt,max_len,0,NULL,NULL));}/* Save the NIO configuration */static void netio_vde_save_cfg(netio_desc_t *nio,FILE *fd){   netio_vde_desc_t *nvd = nio->dptr;   fprintf(fd,"nio create_vde %s %s %s\n",           nio->name,nvd->remote_sock.sun_path,nvd->local_filename);}/* Create a new NetIO descriptor with VDE method */netio_desc_t *netio_desc_create_vde(char *nio_name,char *control,char *local){   netio_vde_desc_t *nvd;   netio_desc_t *nio;      if (!(nio = netio_create(nio_name)))      return NULL;   nvd = &nio->u.nvd;   if (netio_vde_create(nvd,control,local) == -1) {      netio_free(nio,NULL);      return NULL;   }   nio->type     = NETIO_TYPE_VDE;   nio->send     = (void *)netio_vde_send;   nio->recv     = (void *)netio_vde_recv;   nio->save_cfg = netio_vde_save_cfg;   nio->dptr     = &nio->u.nvd;

⌨️ 快捷键说明

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