linux下创建tuntap网络设备

来源:互联网 发布:php input获取数据 编辑:程序博客网 时间:2024/05/23 23:48

目标:在linux下建立bridge虚拟网桥、eth虚拟网卡、tuntap接口设备。通过ping来传递报文,通过tuntap使用户应用程序来收发报文。

环境:测试环境为VMware、Ubuntu14。

1.准备工作。

安装brctl、tunctl:

输入brctl和tunctl指令会出现相应指示,输入相应命令即可。我由于Ubuntu版本较低,在apt-get update时报错,出现同样错误可参考下面链接解决。

http://webres.wang/404-not-found-error-apt-get-update-ubuntu/?utm_source=tuicool&utm_medium=referral

设置IP:

我采用的方法是由主机来ping通VMware的虚拟网卡,需要设置相应的模式。在VMware中设置为HOST-ONLY模式,并在主机中设置vmnet1的IP为192.168.0.2,子网掩码为255.255.255.0。之后我们会在linux中设置bridge的IP为192.168.0.10作为虚拟机的IP地址。


2.编写tuntap代码。

此处创建tap设备,而不是tun设备。通过read和write读写tap,并将得到的报文打印出来。

#include <linux/if_tun.h>#include <stdio.h>#include <unistd.h>#include <sys/socket.h>#include <sys/types.h>#include <fcntl.h>#include <sys/ioctl.h>#include <linux/if.h>#include <error.h>#include <string.h>   //memset#include <arpa/inet.h> //ntohsint tap_create(char *dev, int flags);int main(int argc, char *argv[]){        int tap,ret,i,ret_all=0,time=0,pkts=0;        char *tap_name = NULL;        unsigned char buf[1024];if (argc < 2){printf("Please input tap's name\n");return -1; }if (argc == 2){tap_name = argv[1];}        tap = tap_create(tap_name, IFF_TAP | IFF_NO_PI);        if (tap < 0) {                perror("tap_create");                return 1;        }        printf("TAP name is %s\n", tap_name);        while (1) { ret = read(tap, buf, sizeof(buf));                if (ret < 0)                {printf("delay 10 secs\n");sleep(10);continue;}pkts++;ret_all+=ret;printf("read all %d bytes %d pkts\n", ret_all, pkts);for(i=0;i<ret;i++){if(i%16==0 && i!=0)printf("\n");printf("%02x ",buf[i]);}printf("\n");                                ret = write(tap, buf, ret);                printf("write %d bytes\n", ret);for(i=0;i<ret;i++){if(i%16==0 && i!=0)printf("\n");printf("%02x ",buf[i]);}printf("\n");        }        return 0;}  int tap_create(char *dev, int flags) {     struct ifreq ifr;     int fd, err;     if ((fd = open("/dev/net/tun", O_RDWR|O_NONBLOCK)) < 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; }


3.搭建网络

我们搭建的网络为虚拟网桥br0,连接eth0和tap100。在shell中输入以下代码建立br0和eth0:

brctl addbr br0brctl addif br0 eth0ifconfig br0 192.168.0.10 netmask 255.255.255.0 up

然后在另一个shell终端执行我们写的tap.c文件,代码如下:

gcc tap.c -o taosudo ./tap tap100

程序执行,在第一个shell中再写入代码:

sudo ip link set dev tap100 up  //该代码使tap设备UP,我在测试中发现如果不加tap设备会收不到数据sudo brctl addif br0 tap100

然后在主机中启动cmd,通过代码:

ping 192.168.0.11 -t


4.测试结果



5.另

在后来测试中需要设定tap设备的MAC地址,后来采用了如下代码:

//用例:tap_setMAC("tap100","08:00:11:22:33:44")signed char tap_setMAC(const unsigned char *interface_name, const unsigned char *str_macaddr)    {      int             ret;        int             sock_fd;        struct ifreq    ifr;            unsigned int    mac2bit[6];            if(interface_name == NULL || str_macaddr == NULL)      {          return -1;      }      //提取mac格式       sscanf((char *)str_macaddr, "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned int *)&mac2bit[0], (unsigned int *)&mac2bit[1], (unsigned int *)&mac2bit[2], (unsigned int *)&mac2bit[3], (unsigned int *)&mac2bit[4], (unsigned int *)&mac2bit[5]);            sock_fd = socket(PF_INET, SOCK_DGRAM, 0);        if (sock_fd < 0)        {                    return -2;        }              sprintf(ifr.ifr_ifrn.ifrn_name, "%s", interface_name);        ifr.ifr_ifru.ifru_hwaddr.sa_family = 1;        ifr.ifr_ifru.ifru_hwaddr.sa_data[0] = mac2bit[0];      ifr.ifr_ifru.ifru_hwaddr.sa_data[1] = mac2bit[1];      ifr.ifr_ifru.ifru_hwaddr.sa_data[2] = mac2bit[2];      ifr.ifr_ifru.ifru_hwaddr.sa_data[3] = mac2bit[3];      ifr.ifr_ifru.ifru_hwaddr.sa_data[4] = mac2bit[4];      ifr.ifr_ifru.ifru_hwaddr.sa_data[5] = mac2bit[5];            ret = ioctl(sock_fd, SIOCSIFHWADDR, &ifr);        if (ret != 0)        {            return -4;        }              close( sock_fd );             return 0;    }  


0 0
原创粉丝点击