我的网桥和 tun/tap 设备有问题。
实际上,主要问题是我试图在编译之前创建一个网桥和一个tap接口。在编译时我的代码需要使用该接口。在我的项目代码中,the Contiki
(https://github.com/contiki-os/contiki)代码被编译并用于创建tap接口和通信。
如果我使用sudo
命令运行源代码,一切都很好,但正如我所说,我需要之前创建点击界面,并且我应该在没有命令的情况下运行代码sudo
。
因此,如果我的代码使用命令运行sudo
,ifconfig tap0
则响应如下所示;
tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fc00::231 prefixlen 7 scopeid 0x0<global>
inet6 fe80::cc9f:ddff:fe50:7d9a prefixlen 64 scopeid 0x20<link>
ether ce:9f:dd:50:7d:9a txqueuelen 1000 (Ethernet)
RX packets 50 bytes 12195 (12.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 52 bytes 7869 (7.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
而在这种状态下,我的项目运行得很好。
但我正在尝试使用以下命令创建点击界面;
sudo ip tuntap add mode tap tap0 user myusername
sudo ifconfig tap0 up
sudo ip link set tap0 up
sudo ip -6 address add fc00::231/7 dev tap0
sudo ip address add dev tap0 scope link fe80::cc9f:ddff:fe50:7d9a
然后是ifconfig tap0
响应;
tap0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet6 fe80::cc9f:ddff:fe50:7d9a prefixlen 128 scopeid 0x20<link>
inet6 fc00::231 prefixlen 7 scopeid 0x0<global>
ether 06:ea:8d:0e:66:74 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
因此,在我的 Contiki 代码修改之后,尝试读取 tap0 接口
ret = read(fd, uip_buf, UIP_BUFSIZE);
但 ret 值为 -1。(当它与 sudo 一起运行时,它返回一个 int 值)我想如果我能够更改 tap0 接口的状态,也许RUNNING
我可以获得 ret 值,但我不知道该怎么做。
有谁知道我该怎么办?
注意:tapdev6.c 修改
void
tapdev_init(void)
{
printf("INIT TAP DEV!!!!!!!!!!!!!!!!! \n");
net_fd = open(DEVTAP, O_RDWR);
if(net_fd == -1) {
perror("tapdev: tapdev_init: open");
return;
}
#ifdef __linux
{
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
printf("INIT0 net_fd %d \n", net_fd);
if (ioctl(/*net_fd*/4, TUNSETIFF, (void *) &ifr) < 0) {
printf("INIT FAIL \n");
perror("Unable to init tunnel interface\n");
//exit(1);
}
printf("INIT1 net_fd %d \n", net_fd);
ioctl(/*net_fd*/4, SIOCGIFHWADDR, &ifr);
printf("INIT2 net_fd %d \n", net_fd);
}
/* Linux (ubuntu) */
char buf[256];
snprintf(buf, sizeof(buf), "ip link set tap0 up");
system(buf);
PRINTF("%s\n", buf);
snprintf(buf, sizeof(buf), "ip -6 address add fc00::231/7 dev tap0");
system(buf);
PRINTF("%s\n", buf);
snprintf(buf, sizeof(buf), "ip -6 route add fc00::0/7 dev tap0");
system(buf);
PRINTF("%s\n", buf);
/* freebsd */
//try to set hw address
// 12:bc:34:76:c9:2f
ifr.ifr_hwaddr.sa_data[0] = 0x12;
ifr.ifr_hwaddr.sa_data[1] = 0xbc;
ifr.ifr_hwaddr.sa_data[2] = 0x34;
ifr.ifr_hwaddr.sa_data[3] = 0x76;
ifr.ifr_hwaddr.sa_data[4] = 0xc9;
ifr.ifr_hwaddr.sa_data[5] = 0x2f;
printf("Lan device %s\n", ifr.ifr_name);
printf("LAN HW addr %02X:%02X:%02X:%02X:%02X:%02X\n",
(unsigned char)ifr.ifr_hwaddr.sa_data[0],
(unsigned char)ifr.ifr_hwaddr.sa_data[1],
(unsigned char)ifr.ifr_hwaddr.sa_data[2],
(unsigned char)ifr.ifr_hwaddr.sa_data[3],
(unsigned char)ifr.ifr_hwaddr.sa_data[4],
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
#endif /* Linux */
lasttime = 0;
}
答案1
-ESUDO
说真的,你应该设置点击界面的所有者。尝试以下操作:
ip tuntap add tap0 mode tap user USER
USER
将读取和写入通过打开的句柄的用户在哪里/dev/net/tun
。我怀疑不仅仅是读取失败,还有ioctl(TUNSETIFF)
,但你没有费心去检查返回值。
这是一个简单的opentap(ifname)
函数,应该打开一个指向 Tap 接口的 fd 句柄,前提是运行它的用户具有正确的权限:
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int opentap(char *ifn)
{
int fd;
struct ifreq ifr = { 0 };
if (snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "%s", ifn)
>= sizeof ifr.ifr_name) {
errno = ENAMETOOLONG; return -1;
}
if ((fd = open("/dev/net/tun", O_RDWR)) == -1) return -1;
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
if (ioctl(fd, TUNSETIFF, &ifr) == -1) {
int e = errno; close(fd); errno = e; return -1;
}
return fd;
}