xref: /linux/tools/testing/selftests/namespaces/siocgskns_test.c (revision a1e49d8d18ba0fc53f1a2d5453af32b6339b67cf)
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <limits.h>
6 #include <sched.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/ioctl.h>
11 #include <sys/socket.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <unistd.h>
16 #include <linux/if.h>
17 #include <linux/sockios.h>
18 #include <linux/nsfs.h>
19 #include <arpa/inet.h>
20 #include "../kselftest_harness.h"
21 #include "../filesystems/utils.h"
22 #include "wrappers.h"
23 
24 #ifndef SIOCGSKNS
25 #define SIOCGSKNS 0x894C
26 #endif
27 
28 #ifndef FD_NSFS_ROOT
29 #define FD_NSFS_ROOT -10003
30 #endif
31 
32 #ifndef FILEID_NSFS
33 #define FILEID_NSFS 0xf1
34 #endif
35 
36 /*
37  * Test basic SIOCGSKNS functionality.
38  * Create a socket and verify SIOCGSKNS returns the correct network namespace.
39  */
40 TEST(siocgskns_basic)
41 {
42 	int sock_fd, netns_fd, current_netns_fd;
43 	struct stat st1, st2;
44 
45 	/* Create a TCP socket */
46 	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
47 	ASSERT_GE(sock_fd, 0);
48 
49 	/* Use SIOCGSKNS to get network namespace */
50 	netns_fd = ioctl(sock_fd, SIOCGSKNS);
51 	if (netns_fd < 0) {
52 		close(sock_fd);
53 		if (errno == ENOTTY || errno == EINVAL)
54 			SKIP(return, "SIOCGSKNS not supported");
55 		ASSERT_GE(netns_fd, 0);
56 	}
57 
58 	/* Get current network namespace */
59 	current_netns_fd = open("/proc/self/ns/net", O_RDONLY);
60 	ASSERT_GE(current_netns_fd, 0);
61 
62 	/* Verify they match */
63 	ASSERT_EQ(fstat(netns_fd, &st1), 0);
64 	ASSERT_EQ(fstat(current_netns_fd, &st2), 0);
65 	ASSERT_EQ(st1.st_ino, st2.st_ino);
66 
67 	close(sock_fd);
68 	close(netns_fd);
69 	close(current_netns_fd);
70 }
71 
72 TEST_HARNESS_MAIN
73