目标:在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
#include
#include
#include
#include
#include
#include
#include
#include
#include //memset
#include //ntohs
int 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
3.搭建网络
我们搭建的网络为虚拟网桥br0,连接eth0和tap100。在shell中输入以下代码建立br0和eth0:
brctl addbr br0
brctl addif br0 eth0
ifconfig br0 192.168.0.10 netmask 255.255.255.0 up
然后在另一个shell终端执行我们写的tap.c文件,代码如下:
gcc tap.c -o tao
sudo ./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;
}