Linux
如何在C中設置TUN介面的IP地址和Peer IP地址
我是一名在 CMU 研究月球車的學生,需要在月球車上的兩個設備之間使用 TUN 介面通信。我可以創建一個 TUN 介面,但無法在 C 中分配其 IP 地址。
以下是製作 TUN 設備後的目前狀態:
41: tun11: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500 link/none
這是所需的狀態:
14: tun71: <POINTOPOINT,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 500 link/none inet 192.168.0.29 peer 192.168.0.23/32 scope global tun71 valid_lft forever preferred_lft forever
我嘗試為 ifreq 設置 dstaddr 無濟於事。
int fd; int dst_fd; struct ifreq ifr; struct sockaddr_in* addr; struct sockaddr_in* dst_addr; fd = socket(AF_INET, SOCK_DGRAM, 0); dst_fd = socket(AF_INET, SOCK_DGRAM, 0); ifr.ifr_addr.sa_family = AF_INET; memcpy(ifr.ifr_name, "tun11", IFNAMSIZ - 1); addr = (struct sockaddr_in*)&ifr.ifr_addr; dst_addr = (struct sockaddr_in*)&ifr.ifr_dstaddr; inet_pton(AF_INET, ip_address, &addr->sin_addr); inet_pton(AF_INET, ip_address, &dst_addr->sin_addr); int err; if ( (err = ioctl(fd, SIOCSIFADDR, &ifr)) == -1 ) { perror("ioctl SIOCSIFFLAGS");close(fd);exit(1); }
我不知道還能做什麼。我在給它一個命令後嘗試調試 IP,但我無法弄清楚。
如果您還沒有,請創建一個測試 tun:
# ip tuntap add mode tun dev tun0 # ip address show dev tun0 5: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500 link/none
這看起來與問題中的內容非常相似。現在看看我們需要什麼程式碼……
// uptun.c - set an IP address and UP a tun #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stddef.h> /* offsetof */ #include <net/if.h> #include <net/if.h> #include <linux/sockios.h> #include <netinet/in.h> #if __GLIBC__ >=2 && __GLIBC_MINOR >= 1 #include <netpacket/packet.h> #include <net/ethernet.h> #else #include <asm/types.h> #include <linux/if_ether.h> #endif // TWEAK #define IFNAME "tun0" #define HOST "192.168.0.29" #define ifreq_offsetof(x) offsetof(struct ifreq, x) int main(int argc, char **argv) { struct ifreq ifr; struct sockaddr_in sai; int sockfd; /* socket fd we use to manipulate stuff with */ int selector; unsigned char mask; char *p; /* Create a channel to the NET kernel. */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); /* get interface name */ strncpy(ifr.ifr_name, IFNAME, IFNAMSIZ); memset(&sai, 0, sizeof(struct sockaddr)); sai.sin_family = AF_INET; sai.sin_port = 0; sai.sin_addr.s_addr = inet_addr(HOST); p = (char *) &sai; memcpy((((char *) &ifr + ifreq_offsetof(ifr_addr))), p, sizeof(struct sockaddr)); ioctl(sockfd, SIOCSIFADDR, &ifr); ioctl(sockfd, SIOCGIFFLAGS, &ifr); ifr.ifr_flags |= IFF_UP | IFF_RUNNING; // ifr.ifr_flags &= ~selector; // unset something ioctl(sockfd, SIOCSIFFLAGS, &ifr); close(sockfd); return 0; }
這給了我們:
# make uptun cc uptun.c -o uptun # ./uptun # ip address show dev tun0 5: tun0: <NO-CARRIER,POINTOPOINT,MULTICAST,NOARP,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 500 link/none inet 192.168.0.29/32 scope global tun0 valid_lft forever preferred_lft forever
僅缺少對等地址。一些 altagoobingleduckgoing 顯示 tun
SIOCSIFDSTADDR
除了SIOCSIFADDR
. 讓我們把它塞進劇本之後SIOCGIFFLAGS
…// KLUGE copypasta in the destination address sai.sin_addr.s_addr = inet_addr("192.168.0.23"); p = (char *) &sai; memcpy((((char *) &ifr + ifreq_offsetof(ifr_addr))), p, sizeof(struct sockaddr)); ioctl(sockfd, SIOCSIFDSTADDR, &ifr);
在編譯並重新執行之後,
uptun
我們有:# ip address show dev tun0 5: tun0: <NO-CARRIER,POINTOPOINT,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 500 link/none inet 192.168.0.29 peer 192.168.0.23/32 scope global tun0 valid_lft forever preferred_lft forever