linux下实现虚拟网卡TAP/TUN例子

原文地址:http://blog.csdn.net/xuxinyl/article/details/6454119

 

我们在使用VMWARE的虚拟化软件时经常会发现它们能都能虚拟出一个网卡,貌似很神奇的技术,其实在Linux下很简单,有两种虚拟设 备,TUN时点对点的设备,tap表示以太网设备的,做为虚拟网卡驱动,Tun/tap驱动程序的数据接收和发送并不直接和真实网卡打交道,而是通 过用户态来转交。在linux下,要实现核心态和用户态数据的交互,有多种方式:可以通用socket创建特殊套接字,利用套接字实现数据交 互;通过proc文件系统创建文件来进行数据交互;还可以使用设备文件的方式,访问设备文件会调用设备驱动相应的例程,设备驱动本身就 是核心态和用户态的一个接口,Tun/tap驱动就是利用设备文件实现用户态和核心态的数据交互。

[cpp] view plain copy print ?
  1. #include <unistd.h>   
  2. #include <stdio.h>   
  3. #include <curses.h>   
  4. #include <string.h>   
  5. #include <assert.h>   
  6. #include <sys/types.h>   
  7. #include <sys/socket.h>   
  8. #include <netinet/in.h>   
  9. #include <signal.h>   
  10. #include <unistd.h>   
  11. #include <linux/if_tun.h>   
  12. #include <netinet/in.h>   
  13. #include <sys/ioctl.h>   
  14. #include <sys/time.h>   
  15. #include <linux/if.h>   
  16. #include <netinet/in.h>   
  17. #include <arpa/inet.h>   
  18. #include <errno.h>   
  19. #include <fcntl.h>     
  20. int tun_creat(char *dev,int flags)  
  21. {  
  22.  struct ifreq ifr;  
  23.  int fd,err;  
  24.  assert(dev != NULL);  
  25.  if((fd = open ("/dev/net/tun",O_RDWR))<0) //you can replace it to tap to create tap device.   
  26.   return fd;  
  27.  memset(&ifr,0,sizeof (ifr));  
  28.  ifr.ifr_flags|=flags;  
  29.  if(*dev != '/0')  
  30.   strncpy(ifr.ifr_name,dev,IFNAMSIZ);  
  31.  if((err = ioctl(fd,TUNSETIFF,(void *)&ifr))<0)  
  32.  {  
  33.   close (fd);  
  34.   return err;  
  35.  }  
  36.  strcpy(dev,ifr.ifr_name);  
  37.  return fd;  
  38. }  
  39.   
  40. int main()  
  41. {  
  42.  int tun,ret;  
  43.  char tun_name[IFNAMSIZ];  
  44.  unsigned char buf[4096];  
  45.  tun_name[0]='/0';  
  46.  tun = tun_creat(tun_name,IFF_TAP|IFF_NO_PI);//如果需要配置tun设备,则把"IFF_TAP"改成“IFF_TUN”   
  47.  if(tun<0)  
  48.  {  
  49.   perror("tun_create");  
  50.   return 1;  
  51.  }  
  52.  printf("TUN name is %s/n",tun_name);  
  53.         while (1) {  
  54.                 unsigned char ip[4];  
  55.   
  56.                  ret = read(tun, buf, sizeof(buf));  
  57.                 if (ret < 0)  
  58.                         break;  
  59.                 memcpy(ip, &buf[12], 4);  
  60.                 memcpy(&buf[12], &buf[16], 4);  
  61.                 memcpy(&buf[16], ip, 4);  
  62.                  buf[20] = 0;  
  63.                 *((unsigned short*)&buf[22]) += 8;  
  64.                 printf("read %d bytes/n", ret);  
  65.                  ret = write(tun, buf, ret);  
  66.                 printf("write %d bytes/n", ret);  
  67.         }  
  68.  return 0;  
  69. }  

另开启一个终端

路由配置:

ifconfig devname 10.0.0.1 up;    //10.0.0.1是本虚拟网卡的IP地址,uP是激活该网卡

route add -net 10.0.0.2 netmask 255.255.255.255 dev devname

ping 10.0.0.2

开始测试

 

你可能感兴趣的:(tap,TUN)