TUN/TAP虚拟网络设备为用户空间程序提供了网络数据包的发送和接收能力。他既可以当做点对点设备(TUN),也可以当做以太网设备(TAP)。实际上,不仅Linux支持TUN/TAP虚拟网络设备,其他UNIX也是支持的,他们之间只有少许差别。
- #include <linux/if_tun.h>
- 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;
- }
- IFF_TUN: 创建一个点对点设备
- IFF_TAP: 创建一个以太网设备
- IFF_NO_PI: 不包含包信息,默认的每个数据包当传到用户空间时,都将包含一个附加的包头来保存包信息
- IFF_ONE_QUEUE: 采用单一队列模式,即当数据包队列满的时候,由虚拟网络设备自已丢弃以后的数据包直到数据包队列再有空闲。
struct tun_pi { unsigned short flags; unsigned short proto; };
目前,flags只在收取数据包的时候有效,当它的TUN_PKT_STRIP标志被置时,表示当前的用户空间缓冲区太小,以致数据包被截断。proto成员表示发送/接收的数据包的协议。 上面代码中的文件描述符fd除了支持TUN_SETIFF和其他的常规ioctl命令外,还支持以下命令:- TUNSETNOCSUM: 不做校验和校验。参数为int型的bool值。
- TUNSETPERSIST: 把对应网络设备设置成持续模式,默认的虚拟网络设备,当其相关的文件符被关闭时,也将会伴随着与之相关的路由等信息同时消失。如果设置成持续模式,那么它将会被保留供以后使用。参数为int型的bool值。
- TUNSETOWNER: 设置网络设备的属主。参数类型为uid_t。
- TUNSETLINK: 设置网络设备的链路类型,此命令只有在虚拟网络设备关闭的情况下有效。参数为int型。
- int main(int argc, char *argv[])
- {
- int tun, ret;
- char tun_name[IFNAMSIZ];
- unsigned char buf[4096];
- tun_name[0] = '\0';
- tun = tun_create(tun_name, IFF_TUN | IFF_NO_PI);
- 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;
- }
以上代码简答地处理了ICMP的ECHO包,并回应以ECHO REPLY。 首先运行这个程序: root@gentux test # ./a.out TUN name is tun0 接着在另外一个终端运行如下命令: root@gentux linux-2.6.15-gentoo # ifconfig tun0 0.0.0.0 up root@gentux linux-2.6.15-gentoo # route add 10.10.10.1 dev tun0 root@gentux linux-2.6.15-gentoo # ping 10.10.10.1 PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data. 64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=1.09 ms 64 bytes from 10.10.10.1: icmp_seq=2 ttl=64 time=5.18 ms 64 bytes from 10.10.10.1: icmp_seq=3 ttl=64 time=3.37 ms --- 10.10.10.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2011ms rtt min/avg/max/mdev = 1.097/3.218/5.181/1.671 ms 可见,我们顺利地接受到了回应包,这时,切回到前一个终端下: read 84 bytes write 84 bytes read 84 bytes write 84 bytes read 84 bytes write 84 bytes 一切正如我们所预想的那样。 TUN/TAP能做什么? hoho,问这个问题似乎有些傻,你说一个网卡能做什么?我可以告诉你两个基于此的开源项目:和,至于其他的应用,请自由发挥你的想像力吧!
原文链接: