1

On linux I can create a new tun/tap device in C using something like:

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

This will create a new network interface in the current network namespace. I could afterwards use something like ip link set tap0 netns foo to move it to another namespace from shell.

What is the right way to create it in the correct namespace in the first place, or at least move it to that namespace from my C code?

  • I currently work around that issue by calling system("ip link ...") but that is really ugly. – michas Aug 1 '16 at 12:27
  • I think the only way to do advanced networking configuration programmatically is by using the netlink interface. Have a look at libnfnetlink or the source code of iproute2. – Andreas Wiese Aug 1 '16 at 13:39
1

If you are trying to create a tun device in an existing namespace, you should be able to use the setns() system call before creating the tun device to set the network namespace of your process. For example, assuming that there exists a namespace named "blue":

# ip netns
blue

The following code will open a tun device in that namespace:

#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);
}

While the above code is running, we can verify that the tun device has been created in the appropriate namespace:

# 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 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.