TAP/TUN(二)
tap.c代码
#include<assert.h>
#include<fcntl.h>
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<linux/if.h>
#include<linux/if_tun.h>
#include<sys/types.h>
#include<errno.h>
#include<net/route.h>
intTap=0;
intTap1=0;
int interface_up(char*interface_name)
{
int s;
if((s = socket(PF_INET,SOCK_STREAM,0))<0)
{
printf("Error create socket :%m/n", errno);
return-1;
}
struct ifreq ifr;
strcpy(ifr.ifr_name,interface_name);
short flag;
flag = IFF_UP;
if(ioctl(s, SIOCGIFFLAGS,&ifr)<0)
{
printf("Error up %s :%m/n",interface_name, errno);
return-1;
}
ifr.ifr_ifru.ifru_flags |= flag;
if(ioctl(s, SIOCSIFFLAGS,&ifr)<0)
{
printf("Error up %s :%m/n",interface_name, errno);
return-1;
}
return0;
}
int tun_create(char*dev,int flags)
{
struct ifreq ifr;
int fd, err;
assert(dev != NULL);
if((fd = open("/dev/net/tun", O_RDWR))<0){
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 argc,char*argv[])
{
char tun_name[IFNAMSIZ]="tap0";
char tun_name1[IFNAMSIZ]="tap1";
Tap=tun_create(tun_name, IFF_TAP | IFF_NO_PI);
if(Tap<0){
perror("tun_create");
return1;
}
printf("TAP name is %s\n", tun_name);
printf("Tap=%d\n",Tap);
//interface_up(tun_name);
system("ifconfig tap0 10.66.31.185 netmask 255.255.0.0 up");
while(1);
}
程序要一直运行,否则程序退出后创建的TAP设备会被释放
在前面讲到了TAP口的基本原理。
那么我们直接用TAP口转发报文和TAP口绑定的虚拟网卡上用socket上发报文有什么区别呢?
我上图,我们可以看到, Virtual NIC 就是我们的虚拟网卡,那么如果从TAP口进行报文发送的时候,
我们说了,TAP的使用者就相当于远程机器的网卡,也就是说报文会从虚拟网卡进入到协议栈,然后走内核
的转发流程进行转发(如果是本机就再去LocalIn点),否则就通过forward 到postRoute节点再次进入到TAP口,被
TAP接收后到应用层进行再次转发出去。
但是如果是通过Virtual NIC的socket发送消息就不同了,会先进入到内核,然后进入到转发面(LocalOut->forward),如果是本机发给本机的,报文就会进入到LocalIn节点,再被socket接收。
如果是非本机的,就会通过postRoute发出去,再进入到TAP口被应用层转发面走转发流程。
附件列表