mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	selftests/bpf: Move open_netns() and close_netns() into network_helpers.c
These will also be used by the xdp_do_redirect test being added in the next commit. Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Martin KaFai Lau <kafai@fb.com> Link: https://lore.kernel.org/bpf/20220309105346.100053-5-toke@redhat.com
This commit is contained in:
		
							parent
							
								
									24592ad1ab
								
							
						
					
					
						commit
						a30338840f
					
				
					 3 changed files with 95 additions and 89 deletions
				
			
		| 
						 | 
				
			
			@ -1,18 +1,25 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0-only
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sched.h>
 | 
			
		||||
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/err.h>
 | 
			
		||||
#include <linux/in.h>
 | 
			
		||||
#include <linux/in6.h>
 | 
			
		||||
#include <linux/limits.h>
 | 
			
		||||
 | 
			
		||||
#include "bpf_util.h"
 | 
			
		||||
#include "network_helpers.h"
 | 
			
		||||
#include "test_progs.h"
 | 
			
		||||
 | 
			
		||||
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
 | 
			
		||||
#define log_err(MSG, ...) ({						\
 | 
			
		||||
| 
						 | 
				
			
			@ -356,3 +363,82 @@ char *ping_command(int family)
 | 
			
		|||
	}
 | 
			
		||||
	return "ping";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct nstoken {
 | 
			
		||||
	int orig_netns_fd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int setns_by_fd(int nsfd)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = setns(nsfd, CLONE_NEWNET);
 | 
			
		||||
	close(nsfd);
 | 
			
		||||
 | 
			
		||||
	if (!ASSERT_OK(err, "setns"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	/* Switch /sys to the new namespace so that e.g. /sys/class/net
 | 
			
		||||
	 * reflects the devices in the new namespace.
 | 
			
		||||
	 */
 | 
			
		||||
	err = unshare(CLONE_NEWNS);
 | 
			
		||||
	if (!ASSERT_OK(err, "unshare"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	/* Make our /sys mount private, so the following umount won't
 | 
			
		||||
	 * trigger the global umount in case it's shared.
 | 
			
		||||
	 */
 | 
			
		||||
	err = mount("none", "/sys", NULL, MS_PRIVATE, NULL);
 | 
			
		||||
	if (!ASSERT_OK(err, "remount private /sys"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = umount2("/sys", MNT_DETACH);
 | 
			
		||||
	if (!ASSERT_OK(err, "umount2 /sys"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = mount("sysfs", "/sys", "sysfs", 0, NULL);
 | 
			
		||||
	if (!ASSERT_OK(err, "mount /sys"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = mount("bpffs", "/sys/fs/bpf", "bpf", 0, NULL);
 | 
			
		||||
	if (!ASSERT_OK(err, "mount /sys/fs/bpf"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct nstoken *open_netns(const char *name)
 | 
			
		||||
{
 | 
			
		||||
	int nsfd;
 | 
			
		||||
	char nspath[PATH_MAX];
 | 
			
		||||
	int err;
 | 
			
		||||
	struct nstoken *token;
 | 
			
		||||
 | 
			
		||||
	token = malloc(sizeof(struct nstoken));
 | 
			
		||||
	if (!ASSERT_OK_PTR(token, "malloc token"))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY);
 | 
			
		||||
	if (!ASSERT_GE(token->orig_netns_fd, 0, "open /proc/self/ns/net"))
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name);
 | 
			
		||||
	nsfd = open(nspath, O_RDONLY | O_CLOEXEC);
 | 
			
		||||
	if (!ASSERT_GE(nsfd, 0, "open netns fd"))
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	err = setns_by_fd(nsfd);
 | 
			
		||||
	if (!ASSERT_OK(err, "setns_by_fd"))
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	return token;
 | 
			
		||||
fail:
 | 
			
		||||
	free(token);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void close_netns(struct nstoken *token)
 | 
			
		||||
{
 | 
			
		||||
	ASSERT_OK(setns_by_fd(token->orig_netns_fd), "setns_by_fd");
 | 
			
		||||
	free(token);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,4 +55,13 @@ int make_sockaddr(int family, const char *addr_str, __u16 port,
 | 
			
		|||
		  struct sockaddr_storage *addr, socklen_t *len);
 | 
			
		||||
char *ping_command(int family);
 | 
			
		||||
 | 
			
		||||
struct nstoken;
 | 
			
		||||
/**
 | 
			
		||||
 * open_netns() - Switch to specified network namespace by name.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns token with which to restore the original namespace
 | 
			
		||||
 * using close_netns().
 | 
			
		||||
 */
 | 
			
		||||
struct nstoken *open_netns(const char *name);
 | 
			
		||||
void close_netns(struct nstoken *token);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,8 +10,6 @@
 | 
			
		|||
 * to drop unexpected traffic.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <linux/if.h>
 | 
			
		||||
#include <linux/if_tun.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -19,10 +17,8 @@
 | 
			
		|||
#include <linux/sysctl.h>
 | 
			
		||||
#include <linux/time_types.h>
 | 
			
		||||
#include <linux/net_tstamp.h>
 | 
			
		||||
#include <sched.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -92,91 +88,6 @@ static int write_file(const char *path, const char *newval)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct nstoken {
 | 
			
		||||
	int orig_netns_fd;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int setns_by_fd(int nsfd)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = setns(nsfd, CLONE_NEWNET);
 | 
			
		||||
	close(nsfd);
 | 
			
		||||
 | 
			
		||||
	if (!ASSERT_OK(err, "setns"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	/* Switch /sys to the new namespace so that e.g. /sys/class/net
 | 
			
		||||
	 * reflects the devices in the new namespace.
 | 
			
		||||
	 */
 | 
			
		||||
	err = unshare(CLONE_NEWNS);
 | 
			
		||||
	if (!ASSERT_OK(err, "unshare"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	/* Make our /sys mount private, so the following umount won't
 | 
			
		||||
	 * trigger the global umount in case it's shared.
 | 
			
		||||
	 */
 | 
			
		||||
	err = mount("none", "/sys", NULL, MS_PRIVATE, NULL);
 | 
			
		||||
	if (!ASSERT_OK(err, "remount private /sys"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = umount2("/sys", MNT_DETACH);
 | 
			
		||||
	if (!ASSERT_OK(err, "umount2 /sys"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = mount("sysfs", "/sys", "sysfs", 0, NULL);
 | 
			
		||||
	if (!ASSERT_OK(err, "mount /sys"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = mount("bpffs", "/sys/fs/bpf", "bpf", 0, NULL);
 | 
			
		||||
	if (!ASSERT_OK(err, "mount /sys/fs/bpf"))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * open_netns() - Switch to specified network namespace by name.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns token with which to restore the original namespace
 | 
			
		||||
 * using close_netns().
 | 
			
		||||
 */
 | 
			
		||||
static struct nstoken *open_netns(const char *name)
 | 
			
		||||
{
 | 
			
		||||
	int nsfd;
 | 
			
		||||
	char nspath[PATH_MAX];
 | 
			
		||||
	int err;
 | 
			
		||||
	struct nstoken *token;
 | 
			
		||||
 | 
			
		||||
	token = calloc(1, sizeof(struct nstoken));
 | 
			
		||||
	if (!ASSERT_OK_PTR(token, "malloc token"))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY);
 | 
			
		||||
	if (!ASSERT_GE(token->orig_netns_fd, 0, "open /proc/self/ns/net"))
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name);
 | 
			
		||||
	nsfd = open(nspath, O_RDONLY | O_CLOEXEC);
 | 
			
		||||
	if (!ASSERT_GE(nsfd, 0, "open netns fd"))
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	err = setns_by_fd(nsfd);
 | 
			
		||||
	if (!ASSERT_OK(err, "setns_by_fd"))
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	return token;
 | 
			
		||||
fail:
 | 
			
		||||
	free(token);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void close_netns(struct nstoken *token)
 | 
			
		||||
{
 | 
			
		||||
	ASSERT_OK(setns_by_fd(token->orig_netns_fd), "setns_by_fd");
 | 
			
		||||
	free(token);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int netns_setup_namespaces(const char *verb)
 | 
			
		||||
{
 | 
			
		||||
	const char * const *ns = namespaces;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue