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口被應用層轉發面走轉發流程。
附件列表