tap虚拟网卡的实现

Linux支持基于TAP/TUN的虚拟网卡实现(TAP实现2层协议,TUN实现3层协议),根据这个特点我们可以实现针对某种物理层的特定网卡,如串口。

下面是大概的设计思路:

1、打开内核的TAP/TUN支持。

位于:Device Drivers->Network Device Support->Universe TAP/TUN device driver support。

2、根据不同的内核版本,TAP驱动可能位于/dev/tun或者/dev/net/tun下,打开设备:

fd = open("/dev/tun", O_RDWR);

3、设置驱动属性及设备名:

struct ifreq ifr;

memset(&ifr, 0, sizeof(ifr));

ifr.ifr_flags = IFF_TAP | IFF_NO_PI;

strncpy(ifr.ifr_name, "tap", IFNAMSIZ);

ioctl(fd, TUNSETIFF, (void *)&ifr);

成功则表示虚拟网卡已经建立完毕,可以通过ifconfig tap up启用网卡并设置相关属性。

但这时虚拟网卡还不能做任何有意义的工作,因为没有对接任何物理设备,接下来我们分别对接串口和eth0。

1、串口

struct termios   Opt;

if_fd   =   open("/dev/ttyAMA0", O_RDWR | O_NOCTTY);

cfmakeraw(&Opt);

cfsetispeed(&Opt, B115200);

cfsetospeed(&Opt, B115200);

tcsetattr(if_fd, TCSANOW, &Opt);

串口属性设置完毕。

2、eth0

创建一个raw socket并设置eth0为混杂模式,上传所有数据到tap虚拟网卡。

struct sockaddr_ll sll;

if_fd   =   socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

memset(&ifr, 0, sizeof(ifr));

strcpy(ifr.ifr_name, "eth0");

ioctl(if_fd, SIOCGIFFLAGS, &ifr);

ifr.ifr_flags   |=  IFF_PROMISC;

ioctl(if_fd, SIOCSIFFLAGS, &ifr);


ioctl(if_fd, SIOCGIFINDEX, &ifr);

sll.sll_family  =   AF_PACKET;

sll.sll_ifindex =   ifr.ifr_ifindex;

sll.sll_protocol    =   htons(ETH_P_ALL);

bind(if_fd, (struct sockaddr *)&sll, sizeof(sll));

eth0设置完毕。

3、服务线程

创建2个线程,分别处理上行和下行数据:

len = read(if_fd, _buf, 2000);

if(len > 0) write(fd, _buf, len);

和:

len = read(fd, _buf, 2000);

if(len > 0) write(if_fd, _buf, len);

至此,这个虚拟网卡已经可以通过串口或者eth0与外界通信了。

你可能感兴趣的:(Linux)