My program needs to connect to two TAP interfaces that each live in their own network namespace. Because setns() works at the pthread level I plan to have a dedicated pthread for each interface. (My program itself runs in the "root" namespace.)
However, the setns() function requires me to pass a file descriptor to the network namespace I want to enter. Obtaining this descriptor requires the pid of a process that already exists in that namespace. Once I have that PID I can do a call to open() to get the file descriptor to the network namespace:
int fd = open("/proc/<pid>/ns/net");
But how do I obtain that PID?
One way would be to create a "dummy" process in the desired namespace:
ip netns exec tap101-ns sleep 100 &
[1] 30645
And then use that PID in my program: int fd = open("/proc/30645/ns/net")
However, this way of working seems a bit silly...
Is there a cleaner way to enter a network namespace when all I have is the name of the namespace I want to enter?
I stumbled upon a solution shortly after posting my question.
The path /var/run/netns/ can also be used to obtain a file descriptor. According to the ip-netns documentation:
The file descriptor resulting from opening /var/run/netns/NAME refers to the specified network namespace. Holding that file descriptor open keeps the network namespace alive. The file descriptor can be used with the setns(2) system call to change the network namespace associated with a task.
So I can use this code to switch to a namespace inside my pthread:
int namespace_fd = open("/var/run/netns/tap101-ns");
setns(namespace_fd, CLONE_NEWNET);