红联Linux门户
Linux帮助

Linux下实现虚拟网卡

发布时间:2014-12-31 10:48:41来源:linux网站作者:linux人

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


#include <unistd.h>  
#include <stdio.h>  
#include <curses.h>  
#include <string.h>  
#include <assert.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <signal.h>  
#include <unistd.h>  
#include <linux/if_tun.h>  
#include <netinet/in.h>  
#include <sys/ioctl.h>  
#include <sys/time.h>  
#include <linux/if.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <errno.h>  
#include <fcntl.h>
int tun_creat(char *dev,int flags)  
{  
struct ifreq ifr;  
int fd,err;  
assert(dev != NULL);  
if((fd = open ("/dev/net/tun",O_RDWR))<0) //you can replace it to tap to create tap device.  
return fd;  
memset(&ifr,0,sizeof (ifr));  
ifr.ifr_flags|=flags;  
if(*dev != '\0')  
strncpy(ifr.ifr_name,dev,IFNAMSIZ);  
if((err = ioctl(fd,TUNSETIFF,(void *)&ifr))<0)  
{  
close (fd);  
return err;  
}  
strcpy(dev,ifr.ifr_name);  
return fd;  
}  
 
int main()  
{  
int tun,ret;  
char tun_name[IFNAMSIZ];  
unsigned char buf[4096];  
tun_name[0]='\0';  
tun = tun_creat(tun_name,IFF_TAP|IFF_NO_PI);//如果需要配置tun设备,则把"IFF_TAP"改成“IFF_TUN”  
if(tun<0)  
{  
perror("tun_create");  
return 1;  
}  
printf("TUN name is %s\n",tun_name);  
while (1) {  
unsigned char ip[4];  
 
ret = read(tun, buf, sizeof(buf));  
if (ret < 0)  
break;  
memcpy(ip, &buf[12], 4);  
memcpy(&buf[12], &buf[16], 4);  
memcpy(&buf[16], ip, 4);  
buf[20] = 0;  
*((unsigned short*)&buf[22]) += 8;  
printf("read %d bytes\n", ret);  
ret = write(tun, buf, ret);  
printf("write %d bytes\n", ret);  
}  
return 0;  
}


另开启一个终端

路由配置:

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

开始测试