Contributors: 7
	  
        
          | Author | 
          Tokens | 
          Token Proportion | 
          Commits | 
          Commit Proportion | 
        
	  
	  
        
        
          | Stanislav Fomichev | 
          541 | 
          65.34% | 
          1 | 
          14.29% | 
        
        
          | Daniel Borkmann | 
          213 | 
          25.72% | 
          1 | 
          14.29% | 
        
        
          | Andrii Nakryiko | 
          34 | 
          4.11% | 
          1 | 
          14.29% | 
        
        
          | Martin KaFai Lau | 
          22 | 
          2.66% | 
          1 | 
          14.29% | 
        
        
          | Kui-Feng Lee | 
          9 | 
          1.09% | 
          1 | 
          14.29% | 
        
        
          | David Ahern | 
          7 | 
          0.85% | 
          1 | 
          14.29% | 
        
        
          | Daniel Müller | 
          2 | 
          0.24% | 
          1 | 
          14.29% | 
        
	  
	  
        
          | Total | 
          828 | 
           | 
          7 | 
           | 
	    
	  
    
 
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
#include "cgroup_helpers.h"
#include "network_helpers.h"
static int verify_ports(int family, int fd,
			__u16 expected_local, __u16 expected_peer)
{
	struct sockaddr_storage addr;
	socklen_t len = sizeof(addr);
	__u16 port;
	if (getsockname(fd, (struct sockaddr *)&addr, &len)) {
		log_err("Failed to get server addr");
		return -1;
	}
	if (family == AF_INET)
		port = ((struct sockaddr_in *)&addr)->sin_port;
	else
		port = ((struct sockaddr_in6 *)&addr)->sin6_port;
	if (ntohs(port) != expected_local) {
		log_err("Unexpected local port %d, expected %d", ntohs(port),
			expected_local);
		return -1;
	}
	if (getpeername(fd, (struct sockaddr *)&addr, &len)) {
		log_err("Failed to get peer addr");
		return -1;
	}
	if (family == AF_INET)
		port = ((struct sockaddr_in *)&addr)->sin_port;
	else
		port = ((struct sockaddr_in6 *)&addr)->sin6_port;
	if (ntohs(port) != expected_peer) {
		log_err("Unexpected peer port %d, expected %d", ntohs(port),
			expected_peer);
		return -1;
	}
	return 0;
}
static int run_test(int cgroup_fd, int server_fd, int family, int type)
{
	bool v4 = family == AF_INET;
	__u16 expected_local_port = v4 ? 22222 : 22223;
	__u16 expected_peer_port = 60000;
	struct bpf_program *prog;
	struct bpf_object *obj;
	const char *obj_file = v4 ? "connect_force_port4.bpf.o" : "connect_force_port6.bpf.o";
	int fd, err;
	__u32 duration = 0;
	obj = bpf_object__open_file(obj_file, NULL);
	if (!ASSERT_OK_PTR(obj, "bpf_obj_open"))
		return -1;
	err = bpf_object__load(obj);
	if (!ASSERT_OK(err, "bpf_obj_load")) {
		err = -EIO;
		goto close_bpf_object;
	}
	prog = bpf_object__find_program_by_name(obj, v4 ?
						"connect4" :
						"connect6");
	if (CHECK(!prog, "find_prog", "connect prog not found\n")) {
		err = -EIO;
		goto close_bpf_object;
	}
	err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ?
			      BPF_CGROUP_INET4_CONNECT :
			      BPF_CGROUP_INET6_CONNECT, 0);
	if (err) {
		log_err("Failed to attach BPF program");
		goto close_bpf_object;
	}
	prog = bpf_object__find_program_by_name(obj, v4 ?
						"getpeername4" :
						"getpeername6");
	if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) {
		err = -EIO;
		goto close_bpf_object;
	}
	err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ?
			      BPF_CGROUP_INET4_GETPEERNAME :
			      BPF_CGROUP_INET6_GETPEERNAME, 0);
	if (err) {
		log_err("Failed to attach BPF program");
		goto close_bpf_object;
	}
	prog = bpf_object__find_program_by_name(obj, v4 ?
						"getsockname4" :
						"getsockname6");
	if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) {
		err = -EIO;
		goto close_bpf_object;
	}
	err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ?
			      BPF_CGROUP_INET4_GETSOCKNAME :
			      BPF_CGROUP_INET6_GETSOCKNAME, 0);
	if (err) {
		log_err("Failed to attach BPF program");
		goto close_bpf_object;
	}
	fd = connect_to_fd(server_fd, 0);
	if (fd < 0) {
		err = -1;
		goto close_bpf_object;
	}
	err = verify_ports(family, fd, expected_local_port,
			   expected_peer_port);
	close(fd);
close_bpf_object:
	bpf_object__close(obj);
	return err;
}
void test_connect_force_port(void)
{
	int server_fd, cgroup_fd;
	cgroup_fd = test__join_cgroup("/connect_force_port");
	if (CHECK_FAIL(cgroup_fd < 0))
		return;
	server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 60123, 0);
	if (CHECK_FAIL(server_fd < 0))
		goto close_cgroup_fd;
	CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET, SOCK_STREAM));
	close(server_fd);
	server_fd = start_server(AF_INET6, SOCK_STREAM, NULL, 60124, 0);
	if (CHECK_FAIL(server_fd < 0))
		goto close_cgroup_fd;
	CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET6, SOCK_STREAM));
	close(server_fd);
	server_fd = start_server(AF_INET, SOCK_DGRAM, NULL, 60123, 0);
	if (CHECK_FAIL(server_fd < 0))
		goto close_cgroup_fd;
	CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET, SOCK_DGRAM));
	close(server_fd);
	server_fd = start_server(AF_INET6, SOCK_DGRAM, NULL, 60124, 0);
	if (CHECK_FAIL(server_fd < 0))
		goto close_cgroup_fd;
	CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET6, SOCK_DGRAM));
	close(server_fd);
close_cgroup_fd:
	close(cgroup_fd);
}