创建tun/tap设备时如何指定命名空间?

创建tun/tap设备时如何指定命名空间?

在 Linux 上,我可以使用 C 语言创建一个新的 tun/tap 设备,例如:

int fd = open("/dev/net/tun", O_RDWR);
ioctl(fd, TUNSETIFF, (void *)&ifr);

这将在当前网络命名空间中创建一个新的网络接口。之后我可以使用类似的方法ip link set tap0 netns foo将其从 shell 移动到另一个命名空间。

首先在正确的命名空间中创建它的正确方法是什么,或者至少将其从我的 C 代码移动到该命名空间?

答案1

如果您正在尝试创建一个tun现存的命名空间,您应该能够setns()在创建 tun 设备之前使用系统调用来设置进程的网络命名空间。例如,假设存在一个名为“blue”的命名空间:

# ip netns
blue

以下代码将在该命名空间中打开一个 tun 设备:

#define _GNU_SOURCE

#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <linux/if.h>
#include <linux/if_tun.h>

int main() {
    int nsfd;
    int tunfd;
    struct ifreq ifr;

    nsfd = open("/run/netns/blue", O_RDONLY);
    if (setns(nsfd, CLONE_NEWNET) == -1) {
        perror("setns");
        exit(1);
    }

    memset(&ifr, 0, sizeof(ifr));
    ifr.ifr_flags = IFF_TUN;
    tunfd = open("/dev/net/tun", O_RDWR);
    if (ioctl(tunfd, TUNSETIFF, (void *)&ifr) < 0) {
        perror("ioctl");
        exit(1);
    }

    // this is just here to prevent the code from exiting, which
    sleep(300);
}

当上面的代码运行时,我们可以验证设备是否tun已在适当的命名空间中创建:

# ip netns exec blue ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 500
    link/none 

相关内容