【问题标题】:Setting an IP address to a TUN in C在 C 中将 IP 地址设置为 TUN
【发布时间】:2023-01-28 02:21:25
【问题描述】:

我试图在 C 中创建一个隧道,但我正在努力设置它的 IP 地址。我在带有 SIOCSIFADDR 参数的 ioctl 中出现“无效参数”错误。如果此功能不适用于 tun,有人可以向我解释如何设置 IP 地址吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if_tun.h>
#include <linux/if.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>


#define IP_DEST "127.0.0.1"
#define IP_SOURCE "127.0.0.1"



int tun_alloc(char* dev) {
    //dev will store the name of the tun created

    struct ifreq ifr;
    int fd, err;
    char *clonedev = "/dev/net/tun";

    //open the clone device 
    if( (fd = open(clonedev, O_RDWR)) < 0 ) {
        printf("Error opening directory");
        return fd;
    }

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN;  
    if (*dev) {
     strncpy(ifr.ifr_name, dev, IFNAMSIZ);
   }

    //Create the TUN
    if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
        close(fd);
        printf("Error creating the tun");
        return err;
    }
    strcpy(dev, ifr.ifr_name);

    return fd;
}

int main(int argc, char* argv[]) {

    //Creating the TUN interface
    char tun_name[IFNAMSIZ];
    strncpy(tun_name, "tun3", IFNAMSIZ);

    int tunfd = tun_alloc(tun_name);
    if (tunfd < 0) {
        perror("tun_create");
        return 1;
    }
    printf("TUN interface %s created\n", tun_name);

    //Setting its IP Adress
    struct ifreq ifr;
    struct sockaddr_in addr;

    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, tun_name, IFNAMSIZ);

    addr.sin_family = AF_INET;
    if(inet_pton(AF_INET,IP_DEST,&(addr.sin_addr))<0){
        fprintf(stderr,"ERROR with the IP address");
        return 1;
    };

    memcpy(&(ifr.ifr_addr), &addr, sizeof (struct sockaddr));
    if (ioctl(tunfd, SIOCSIFADDR, &ifr) < 0) {
        perror("ioctl");
        exit(1);
    }
    printf("TUN interface %s set IP address to %s\n", tun_name, IP_DEST);

    ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
    if(ioctl(tunfd, SIOCSIFFLAGS, &ifr)<0){
        perror("ioctl");
        exit(1);
    };
    printf("TUN running");
    return 0;
}

我真的不明白 iotcl 是如何工作的,而且文档对 tun 接口没有帮助。

【问题讨论】:

  • 我相信这些 SIO ioctl 应该在任何插座,不在 tun 文件上。这就是为什么接口名称是请求的一部分,这就是为什么它们也适用于例如以太网端口。

标签: c network-programming ioctl tun


【解决方案1】:

SIOCSIFADDRSIOCSIFFLAGS(以及其他SIOwhateverioctl 调用应该针对任何AF_INET 套接字,而不是针对tun 接口本身。设计是为了让您可以使用它们来配置任何界面,而不仅仅是您创建的界面。您必须创建一个 AF_INET 套接字,然后在该套接字上调用 ioctl

如果您认为必须制作套接字有点奇怪,那您是对的。 ioctl 用于对文件提出“特殊请求”,而不是readwrite。根据文件类型解释请求。使用套接字确保它被 IP 网络系统解释为与 IP 套接字相关的请求。它从逻辑上讲,您也可以在 tun 接口上提出与 IP 相关的特殊请求,但显然内核开发人员没有想到这一点,并且不需要它们工作,因为您只需创建一个套接字即可。

还有另一种使用称为“rtnetlink”的系统设置 IP 地址的方法,但对于像这样的简单场景来说它更复杂且不必要。

【讨论】:

    猜你喜欢
    • 2013-07-04
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 2017-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多