1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <test_progs.h>
4 #include "cgroup_helpers.h"
5 #include "network_helpers.h"
6
verify_ports(int family,int fd,__u16 expected_local,__u16 expected_peer)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
run_test(int cgroup_fd,int server_fd,int family,int type)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_program *prog;
55 struct bpf_object *obj;
56 const char *obj_file = v4 ? "connect_force_port4.bpf.o" : "connect_force_port6.bpf.o";
57 int fd, err;
58 __u32 duration = 0;
59
60 obj = bpf_object__open_file(obj_file, NULL);
61 if (!ASSERT_OK_PTR(obj, "bpf_obj_open"))
62 return -1;
63
64 err = bpf_object__load(obj);
65 if (!ASSERT_OK(err, "bpf_obj_load")) {
66 err = -EIO;
67 goto close_bpf_object;
68 }
69
70 prog = bpf_object__find_program_by_name(obj, v4 ?
71 "connect4" :
72 "connect6");
73 if (CHECK(!prog, "find_prog", "connect prog not found\n")) {
74 err = -EIO;
75 goto close_bpf_object;
76 }
77
78 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ?
79 BPF_CGROUP_INET4_CONNECT :
80 BPF_CGROUP_INET6_CONNECT, 0);
81 if (err) {
82 log_err("Failed to attach BPF program");
83 goto close_bpf_object;
84 }
85
86 prog = bpf_object__find_program_by_name(obj, v4 ?
87 "getpeername4" :
88 "getpeername6");
89 if (CHECK(!prog, "find_prog", "getpeername prog not found\n")) {
90 err = -EIO;
91 goto close_bpf_object;
92 }
93
94 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ?
95 BPF_CGROUP_INET4_GETPEERNAME :
96 BPF_CGROUP_INET6_GETPEERNAME, 0);
97 if (err) {
98 log_err("Failed to attach BPF program");
99 goto close_bpf_object;
100 }
101
102 prog = bpf_object__find_program_by_name(obj, v4 ?
103 "getsockname4" :
104 "getsockname6");
105 if (CHECK(!prog, "find_prog", "getsockname prog not found\n")) {
106 err = -EIO;
107 goto close_bpf_object;
108 }
109
110 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd, v4 ?
111 BPF_CGROUP_INET4_GETSOCKNAME :
112 BPF_CGROUP_INET6_GETSOCKNAME, 0);
113 if (err) {
114 log_err("Failed to attach BPF program");
115 goto close_bpf_object;
116 }
117
118 fd = connect_to_fd(server_fd, 0);
119 if (fd < 0) {
120 err = -1;
121 goto close_bpf_object;
122 }
123
124 err = verify_ports(family, fd, expected_local_port,
125 expected_peer_port);
126 close(fd);
127
128 close_bpf_object:
129 bpf_object__close(obj);
130 return err;
131 }
132
test_connect_force_port(void)133 void test_connect_force_port(void)
134 {
135 int server_fd, cgroup_fd;
136
137 cgroup_fd = test__join_cgroup("/connect_force_port");
138 if (CHECK_FAIL(cgroup_fd < 0))
139 return;
140
141 server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 60123, 0);
142 if (CHECK_FAIL(server_fd < 0))
143 goto close_cgroup_fd;
144 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET, SOCK_STREAM));
145 close(server_fd);
146
147 server_fd = start_server(AF_INET6, SOCK_STREAM, NULL, 60124, 0);
148 if (CHECK_FAIL(server_fd < 0))
149 goto close_cgroup_fd;
150 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET6, SOCK_STREAM));
151 close(server_fd);
152
153 server_fd = start_server(AF_INET, SOCK_DGRAM, NULL, 60123, 0);
154 if (CHECK_FAIL(server_fd < 0))
155 goto close_cgroup_fd;
156 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET, SOCK_DGRAM));
157 close(server_fd);
158
159 server_fd = start_server(AF_INET6, SOCK_DGRAM, NULL, 60124, 0);
160 if (CHECK_FAIL(server_fd < 0))
161 goto close_cgroup_fd;
162 CHECK_FAIL(run_test(cgroup_fd, server_fd, AF_INET6, SOCK_DGRAM));
163 close(server_fd);
164
165 close_cgroup_fd:
166 close(cgroup_fd);
167 }
168