]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/prog_tests/setget_sockopt.c
Linux 6.14-rc3
[linux.git] / tools / testing / selftests / bpf / prog_tests / setget_sockopt.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3
4 #define _GNU_SOURCE
5 #include <sched.h>
6 #include <linux/socket.h>
7 #include <linux/tls.h>
8 #include <net/if.h>
9
10 #include "test_progs.h"
11 #include "cgroup_helpers.h"
12 #include "network_helpers.h"
13
14 #include "setget_sockopt.skel.h"
15
16 #define CG_NAME "/setget-sockopt-test"
17
18 static const char addr4_str[] = "127.0.0.1";
19 static const char addr6_str[] = "::1";
20 static struct setget_sockopt *skel;
21 static int cg_fd;
22
23 static int create_netns(void)
24 {
25         if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
26                 return -1;
27
28         if (!ASSERT_OK(system("ip link set dev lo up"), "set lo up"))
29                 return -1;
30
31         if (!ASSERT_OK(system("ip link add dev binddevtest1 type veth peer name binddevtest2"),
32                        "add veth"))
33                 return -1;
34
35         if (!ASSERT_OK(system("ip link set dev binddevtest1 up"),
36                        "bring veth up"))
37                 return -1;
38
39         return 0;
40 }
41
42 static void test_tcp(int family)
43 {
44         struct setget_sockopt__bss *bss = skel->bss;
45         int sfd, cfd;
46
47         memset(bss, 0, sizeof(*bss));
48
49         sfd = start_server(family, SOCK_STREAM,
50                            family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
51         if (!ASSERT_GE(sfd, 0, "start_server"))
52                 return;
53
54         cfd = connect_to_fd(sfd, 0);
55         if (!ASSERT_GE(cfd, 0, "connect_to_fd_server")) {
56                 close(sfd);
57                 return;
58         }
59         close(sfd);
60         close(cfd);
61
62         ASSERT_EQ(bss->nr_listen, 1, "nr_listen");
63         ASSERT_EQ(bss->nr_connect, 1, "nr_connect");
64         ASSERT_EQ(bss->nr_active, 1, "nr_active");
65         ASSERT_EQ(bss->nr_passive, 1, "nr_passive");
66         ASSERT_EQ(bss->nr_socket_post_create, 2, "nr_socket_post_create");
67         ASSERT_EQ(bss->nr_binddev, 2, "nr_bind");
68 }
69
70 static void test_udp(int family)
71 {
72         struct setget_sockopt__bss *bss = skel->bss;
73         int sfd;
74
75         memset(bss, 0, sizeof(*bss));
76
77         sfd = start_server(family, SOCK_DGRAM,
78                            family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
79         if (!ASSERT_GE(sfd, 0, "start_server"))
80                 return;
81         close(sfd);
82
83         ASSERT_GE(bss->nr_socket_post_create, 1, "nr_socket_post_create");
84         ASSERT_EQ(bss->nr_binddev, 1, "nr_bind");
85 }
86
87 static void test_ktls(int family)
88 {
89         struct tls12_crypto_info_aes_gcm_128 aes128;
90         struct setget_sockopt__bss *bss = skel->bss;
91         int cfd = -1, sfd = -1, fd = -1, ret;
92         char buf;
93
94         memset(bss, 0, sizeof(*bss));
95
96         sfd = start_server(family, SOCK_STREAM,
97                            family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
98         if (!ASSERT_GE(sfd, 0, "start_server"))
99                 return;
100         fd = connect_to_fd(sfd, 0);
101         if (!ASSERT_GE(fd, 0, "connect_to_fd"))
102                 goto err_out;
103
104         cfd = accept(sfd, NULL, 0);
105         if (!ASSERT_GE(cfd, 0, "accept"))
106                 goto err_out;
107
108         close(sfd);
109         sfd = -1;
110
111         /* Setup KTLS */
112         ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
113         if (!ASSERT_OK(ret, "setsockopt"))
114                 goto err_out;
115         ret = setsockopt(cfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
116         if (!ASSERT_OK(ret, "setsockopt"))
117                 goto err_out;
118
119         memset(&aes128, 0, sizeof(aes128));
120         aes128.info.version = TLS_1_2_VERSION;
121         aes128.info.cipher_type = TLS_CIPHER_AES_GCM_128;
122
123         ret = setsockopt(fd, SOL_TLS, TLS_TX, &aes128, sizeof(aes128));
124         if (!ASSERT_OK(ret, "setsockopt"))
125                 goto err_out;
126
127         ret = setsockopt(cfd, SOL_TLS, TLS_RX, &aes128, sizeof(aes128));
128         if (!ASSERT_OK(ret, "setsockopt"))
129                 goto err_out;
130
131         /* KTLS is enabled */
132
133         close(fd);
134         /* At this point, the cfd socket is at the CLOSE_WAIT state
135          * and still run TLS protocol.  The test for
136          * BPF_TCP_CLOSE_WAIT should be run at this point.
137          */
138         ret = read(cfd, &buf, sizeof(buf));
139         ASSERT_EQ(ret, 0, "read");
140         close(cfd);
141
142         ASSERT_EQ(bss->nr_listen, 1, "nr_listen");
143         ASSERT_EQ(bss->nr_connect, 1, "nr_connect");
144         ASSERT_EQ(bss->nr_active, 1, "nr_active");
145         ASSERT_EQ(bss->nr_passive, 1, "nr_passive");
146         ASSERT_EQ(bss->nr_socket_post_create, 2, "nr_socket_post_create");
147         ASSERT_EQ(bss->nr_binddev, 2, "nr_bind");
148         ASSERT_EQ(bss->nr_fin_wait1, 1, "nr_fin_wait1");
149         return;
150
151 err_out:
152         close(fd);
153         close(cfd);
154         close(sfd);
155 }
156
157 static void test_nonstandard_opt(int family)
158 {
159         struct setget_sockopt__bss *bss = skel->bss;
160         struct bpf_link *getsockopt_link = NULL;
161         int sfd = -1, fd = -1, cfd = -1, flags;
162         socklen_t flagslen = sizeof(flags);
163
164         memset(bss, 0, sizeof(*bss));
165
166         sfd = start_server(family, SOCK_STREAM,
167                            family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
168         if (!ASSERT_GE(sfd, 0, "start_server"))
169                 return;
170
171         fd = connect_to_fd(sfd, 0);
172         if (!ASSERT_GE(fd, 0, "connect_to_fd_server"))
173                 goto err_out;
174
175         /* cgroup/getsockopt prog will intercept getsockopt() below and
176          * retrieve the tcp socket bpf_sock_ops_cb_flags value for the
177          * accept()ed socket; this was set earlier in the passive established
178          * callback for the accept()ed socket via bpf_setsockopt().
179          */
180         getsockopt_link = bpf_program__attach_cgroup(skel->progs._getsockopt, cg_fd);
181         if (!ASSERT_OK_PTR(getsockopt_link, "getsockopt prog"))
182                 goto err_out;
183
184         cfd = accept(sfd, NULL, 0);
185         if (!ASSERT_GE(cfd, 0, "accept"))
186                 goto err_out;
187
188         if (!ASSERT_OK(getsockopt(cfd, SOL_TCP, TCP_BPF_SOCK_OPS_CB_FLAGS, &flags, &flagslen),
189                        "getsockopt_flags"))
190                 goto err_out;
191         ASSERT_EQ(flags & BPF_SOCK_OPS_STATE_CB_FLAG, BPF_SOCK_OPS_STATE_CB_FLAG,
192                   "cb_flags_set");
193 err_out:
194         close(sfd);
195         if (fd != -1)
196                 close(fd);
197         if (cfd != -1)
198                 close(cfd);
199         bpf_link__destroy(getsockopt_link);
200 }
201
202 void test_setget_sockopt(void)
203 {
204         cg_fd = test__join_cgroup(CG_NAME);
205         if (cg_fd < 0)
206                 return;
207
208         if (create_netns())
209                 goto done;
210
211         skel = setget_sockopt__open();
212         if (!ASSERT_OK_PTR(skel, "open skel"))
213                 goto done;
214
215         strcpy(skel->rodata->veth, "binddevtest1");
216         skel->rodata->veth_ifindex = if_nametoindex("binddevtest1");
217         if (!ASSERT_GT(skel->rodata->veth_ifindex, 0, "if_nametoindex"))
218                 goto done;
219
220         if (!ASSERT_OK(setget_sockopt__load(skel), "load skel"))
221                 goto done;
222
223         skel->links.skops_sockopt =
224                 bpf_program__attach_cgroup(skel->progs.skops_sockopt, cg_fd);
225         if (!ASSERT_OK_PTR(skel->links.skops_sockopt, "attach cgroup"))
226                 goto done;
227
228         skel->links.socket_post_create =
229                 bpf_program__attach_cgroup(skel->progs.socket_post_create, cg_fd);
230         if (!ASSERT_OK_PTR(skel->links.socket_post_create, "attach_cgroup"))
231                 goto done;
232
233         test_tcp(AF_INET6);
234         test_tcp(AF_INET);
235         test_udp(AF_INET6);
236         test_udp(AF_INET);
237         test_ktls(AF_INET6);
238         test_ktls(AF_INET);
239         test_nonstandard_opt(AF_INET);
240         test_nonstandard_opt(AF_INET6);
241
242 done:
243         setget_sockopt__destroy(skel);
244         close(cg_fd);
245 }
This page took 0.044656 seconds and 4 git commands to generate.