1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <test_progs.h> 4 #include "cgroup_helpers.h" 5 #include "network_helpers.h" 6 7 static int verify_ports(int family, int fd, 8 __u16 expected_local, __u16 expected_peer) 9 { 10 struct sockaddr_storage addr; 11 socklen_t len = sizeof(addr); 12 __u16 port; 13 14 if (getsockname(fd, (struct sockaddr *)&addr, &len)) { 15 log_err("Failed to get server addr"); 16 return -1; 17 } 18 19 if (family == AF_INET) 20 port = ((struct sockaddr_in *)&addr)->sin_port; 21 else 22 port = ((struct sockaddr_in6 *)&addr)->sin6_port; 23 24 if (ntohs(port) != expected_local) { 25 log_err("Unexpected local port %d, expected %d", ntohs(port), 26 expected_local); 27 return -1; 28 } 29 30 if (getpeername(fd, (struct sockaddr *)&addr, &len)) { 31 log_err("Failed to get peer addr"); 32 return -1; 33 } 34 35 if (family == AF_INET) 36 port = ((struct sockaddr_in *)&addr)->sin_port; 37 else 38 port = ((struct sockaddr_in6 *)&addr)->sin6_port; 39 40 if (ntohs(port) != expected_peer) { 41 log_err("Unexpected peer port %d, expected %d", ntohs(port), 42 expected_peer); 43 return -1; 44 } 45 46 return 0; 47 } 48 49 static int run_test(int cgroup_fd, int server_fd, int family, int type) 50 { 51 bool v4 = family == AF_INET; 52 __u16 expected_local_port = v4 ? 22222 : 22223; 53 __u16 expected_peer_port = 60000; 54 struct bpf_prog_load_attr attr = { 55 .file = v4 ? "./connect_force_port4.o" : 56 "./connect_force_port6.o", 57 }; 58 struct bpf_program *prog; 59 struct bpf_object *obj; 60 int xlate_fd, fd, err; 61 __u32 duration = 0; 62 63 err = bpf_prog_load_xattr(&attr, &obj, &xlate_fd); 64 if (err) { 65 log_err("Failed to load BPF object"); 66 return -1; 67 } 68 69 prog = bpf_object__find_program_by_title(obj, v4 ? 70 "cgroup/connect4" : 71 "cgroup/connect6"); 72 if (CHECK(!prog, "find_prog", "connect prog not found\n")) { 73 err = -EIO; 74 goto close_bpf_object; 75 } 76 77 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ? 78 BPF_CGROUP_INET4_CONNECT : 79 BPF_CGROUP_INET6_CONNECT, 0); 80 if (err) { 81 log_err("Failed to attach BPF program"); 82 goto close_bpf_object; 83 } 84 85 prog = bpf_object__find_program_by_title(obj, v4 ? 86 "cgroup/getpeername4" : 87 "cgroup/getpeername6"); 88 if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) { 89 err = -EIO; 90 goto close_bpf_object; 91 } 92 93 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ? 94 BPF_CGROUP_INET4_GETPEERNAME : 95 BPF_CGROUP_INET6_GETPEERNAME, 0); 96 if (err) { 97 log_err("Failed to attach BPF program"); 98 goto close_bpf_object; 99 } 100 101 prog = bpf_object__find_program_by_title(obj, v4 ? 102 "cgroup/getsockname4" : 103 "cgroup/getsockname6"); 104 if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) { 105 err = -EIO; 106 goto close_bpf_object; 107 } 108 109 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ? 110 BPF_CGROUP_INET4_GETSOCKNAME : 111 BPF_CGROUP_INET6_GETSOCKNAME, 0); 112 if (err) { 113 log_err("Failed to attach BPF program"); 114 goto close_bpf_object; 115 } 116 117 fd = connect_to_fd(server_fd, 0); 118 if (fd < 0) { 119 err = -1; 120 goto close_bpf_object; 121 } 122 123 err = verify_ports(family, fd, expected_local_port, 124 expected_peer_port); 125 close(fd); 126 127 close_bpf_object: 128 bpf_object__close(obj); 129 return err; 130 } 131 132 void test_connect_force_port(void) 133 { 134 int server_fd, cgroup_fd; 135 136 cgroup_fd = test__join_cgroup("/connect_force_port"); 137 if (CHECK_FAIL(cgroup_fd < 0)) 138 return; 139 140 server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 60123, 0); 141 if (CHECK_FAIL(server_fd < 0)) 142 goto close_cgroup_fd; 143 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET, SOCK_STREAM)); 144 close(server_fd); 145 146 server_fd = start_server(AF_INET6, SOCK_STREAM, NULL, 60124, 0); 147 if (CHECK_FAIL(server_fd < 0)) 148 goto close_cgroup_fd; 149 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET6, SOCK_STREAM)); 150 close(server_fd); 151 152 server_fd = start_server(AF_INET, SOCK_DGRAM, NULL, 60123, 0); 153 if (CHECK_FAIL(server_fd < 0)) 154 goto close_cgroup_fd; 155 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET, SOCK_DGRAM)); 156 close(server_fd); 157 158 server_fd = start_server(AF_INET6, SOCK_DGRAM, NULL, 60124, 0); 159 if (CHECK_FAIL(server_fd < 0)) 160 goto close_cgroup_fd; 161 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET6, SOCK_DGRAM)); 162 close(server_fd); 163 164 close_cgroup_fd: 165 close(cgroup_fd); 166 } 167