Networking
如何從點擊界面讀取數據?
我遇到了網橋和 tun/tap 設備的問題。
實際上,主要問題是我試圖在編譯之前創建一個網橋和一個 Tap 介面。在編譯時我的程式碼需要使用介面。在我的項目程式碼中,
the Contiki
( https://github.com/contiki-os/contiki ) 程式碼被編譯並用於創建點擊介面和通信。如果我用命令執行我的原始碼
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; }
-ESUDO
說真的,你應該設置點擊界面的所有者。嘗試以下:
ip tuntap add tap0 mode tap user USER
USER
將讀取和寫入通過打開的句柄的使用者在哪裡/dev/net/tun
。我懷疑不僅 read 失敗了,而且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; }