131123c03SMartin KaFai Lau // SPDX-License-Identifier: GPL-2.0
231123c03SMartin KaFai Lau /* Copyright (c) Meta Platforms, Inc. and affiliates. */
331123c03SMartin KaFai Lau
431123c03SMartin KaFai Lau #define _GNU_SOURCE
531123c03SMartin KaFai Lau #include <sched.h>
631123c03SMartin KaFai Lau #include <linux/socket.h>
7*d1246f93SKui-Feng Lee #include <linux/tls.h>
831123c03SMartin KaFai Lau #include <net/if.h>
931123c03SMartin KaFai Lau
1031123c03SMartin KaFai Lau #include "test_progs.h"
1131123c03SMartin KaFai Lau #include "cgroup_helpers.h"
1231123c03SMartin KaFai Lau #include "network_helpers.h"
1331123c03SMartin KaFai Lau
1431123c03SMartin KaFai Lau #include "setget_sockopt.skel.h"
1531123c03SMartin KaFai Lau
1631123c03SMartin KaFai Lau #define CG_NAME "/setget-sockopt-test"
1731123c03SMartin KaFai Lau
1831123c03SMartin KaFai Lau static const char addr4_str[] = "127.0.0.1";
1931123c03SMartin KaFai Lau static const char addr6_str[] = "::1";
2031123c03SMartin KaFai Lau static struct setget_sockopt *skel;
2131123c03SMartin KaFai Lau static int cg_fd;
2231123c03SMartin KaFai Lau
create_netns(void)2331123c03SMartin KaFai Lau static int create_netns(void)
2431123c03SMartin KaFai Lau {
2531123c03SMartin KaFai Lau if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
2631123c03SMartin KaFai Lau return -1;
2731123c03SMartin KaFai Lau
2831123c03SMartin KaFai Lau if (!ASSERT_OK(system("ip link set dev lo up"), "set lo up"))
2931123c03SMartin KaFai Lau return -1;
3031123c03SMartin KaFai Lau
3131123c03SMartin KaFai Lau if (!ASSERT_OK(system("ip link add dev binddevtest1 type veth peer name binddevtest2"),
3231123c03SMartin KaFai Lau "add veth"))
3331123c03SMartin KaFai Lau return -1;
3431123c03SMartin KaFai Lau
3531123c03SMartin KaFai Lau if (!ASSERT_OK(system("ip link set dev binddevtest1 up"),
3631123c03SMartin KaFai Lau "bring veth up"))
3731123c03SMartin KaFai Lau return -1;
3831123c03SMartin KaFai Lau
3931123c03SMartin KaFai Lau return 0;
4031123c03SMartin KaFai Lau }
4131123c03SMartin KaFai Lau
test_tcp(int family)4231123c03SMartin KaFai Lau static void test_tcp(int family)
4331123c03SMartin KaFai Lau {
4431123c03SMartin KaFai Lau struct setget_sockopt__bss *bss = skel->bss;
4531123c03SMartin KaFai Lau int sfd, cfd;
4631123c03SMartin KaFai Lau
4731123c03SMartin KaFai Lau memset(bss, 0, sizeof(*bss));
4831123c03SMartin KaFai Lau
4931123c03SMartin KaFai Lau sfd = start_server(family, SOCK_STREAM,
5031123c03SMartin KaFai Lau family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
5131123c03SMartin KaFai Lau if (!ASSERT_GE(sfd, 0, "start_server"))
5231123c03SMartin KaFai Lau return;
5331123c03SMartin KaFai Lau
5431123c03SMartin KaFai Lau cfd = connect_to_fd(sfd, 0);
5531123c03SMartin KaFai Lau if (!ASSERT_GE(cfd, 0, "connect_to_fd_server")) {
5631123c03SMartin KaFai Lau close(sfd);
5731123c03SMartin KaFai Lau return;
5831123c03SMartin KaFai Lau }
5931123c03SMartin KaFai Lau close(sfd);
6031123c03SMartin KaFai Lau close(cfd);
6131123c03SMartin KaFai Lau
6231123c03SMartin KaFai Lau ASSERT_EQ(bss->nr_listen, 1, "nr_listen");
6331123c03SMartin KaFai Lau ASSERT_EQ(bss->nr_connect, 1, "nr_connect");
6431123c03SMartin KaFai Lau ASSERT_EQ(bss->nr_active, 1, "nr_active");
6531123c03SMartin KaFai Lau ASSERT_EQ(bss->nr_passive, 1, "nr_passive");
6631123c03SMartin KaFai Lau ASSERT_EQ(bss->nr_socket_post_create, 2, "nr_socket_post_create");
6731123c03SMartin KaFai Lau ASSERT_EQ(bss->nr_binddev, 2, "nr_bind");
6831123c03SMartin KaFai Lau }
6931123c03SMartin KaFai Lau
test_udp(int family)7031123c03SMartin KaFai Lau static void test_udp(int family)
7131123c03SMartin KaFai Lau {
7231123c03SMartin KaFai Lau struct setget_sockopt__bss *bss = skel->bss;
7331123c03SMartin KaFai Lau int sfd;
7431123c03SMartin KaFai Lau
7531123c03SMartin KaFai Lau memset(bss, 0, sizeof(*bss));
7631123c03SMartin KaFai Lau
7731123c03SMartin KaFai Lau sfd = start_server(family, SOCK_DGRAM,
7831123c03SMartin KaFai Lau family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
7931123c03SMartin KaFai Lau if (!ASSERT_GE(sfd, 0, "start_server"))
8031123c03SMartin KaFai Lau return;
8131123c03SMartin KaFai Lau close(sfd);
8231123c03SMartin KaFai Lau
8331123c03SMartin KaFai Lau ASSERT_GE(bss->nr_socket_post_create, 1, "nr_socket_post_create");
8431123c03SMartin KaFai Lau ASSERT_EQ(bss->nr_binddev, 1, "nr_bind");
8531123c03SMartin KaFai Lau }
8631123c03SMartin KaFai Lau
test_ktls(int family)87*d1246f93SKui-Feng Lee static void test_ktls(int family)
88*d1246f93SKui-Feng Lee {
89*d1246f93SKui-Feng Lee struct tls12_crypto_info_aes_gcm_128 aes128;
90*d1246f93SKui-Feng Lee struct setget_sockopt__bss *bss = skel->bss;
91*d1246f93SKui-Feng Lee int cfd = -1, sfd = -1, fd = -1, ret;
92*d1246f93SKui-Feng Lee char buf;
93*d1246f93SKui-Feng Lee
94*d1246f93SKui-Feng Lee memset(bss, 0, sizeof(*bss));
95*d1246f93SKui-Feng Lee
96*d1246f93SKui-Feng Lee sfd = start_server(family, SOCK_STREAM,
97*d1246f93SKui-Feng Lee family == AF_INET6 ? addr6_str : addr4_str, 0, 0);
98*d1246f93SKui-Feng Lee if (!ASSERT_GE(sfd, 0, "start_server"))
99*d1246f93SKui-Feng Lee return;
100*d1246f93SKui-Feng Lee fd = connect_to_fd(sfd, 0);
101*d1246f93SKui-Feng Lee if (!ASSERT_GE(fd, 0, "connect_to_fd"))
102*d1246f93SKui-Feng Lee goto err_out;
103*d1246f93SKui-Feng Lee
104*d1246f93SKui-Feng Lee cfd = accept(sfd, NULL, 0);
105*d1246f93SKui-Feng Lee if (!ASSERT_GE(cfd, 0, "accept"))
106*d1246f93SKui-Feng Lee goto err_out;
107*d1246f93SKui-Feng Lee
108*d1246f93SKui-Feng Lee close(sfd);
109*d1246f93SKui-Feng Lee sfd = -1;
110*d1246f93SKui-Feng Lee
111*d1246f93SKui-Feng Lee /* Setup KTLS */
112*d1246f93SKui-Feng Lee ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
113*d1246f93SKui-Feng Lee if (!ASSERT_OK(ret, "setsockopt"))
114*d1246f93SKui-Feng Lee goto err_out;
115*d1246f93SKui-Feng Lee ret = setsockopt(cfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));
116*d1246f93SKui-Feng Lee if (!ASSERT_OK(ret, "setsockopt"))
117*d1246f93SKui-Feng Lee goto err_out;
118*d1246f93SKui-Feng Lee
119*d1246f93SKui-Feng Lee memset(&aes128, 0, sizeof(aes128));
120*d1246f93SKui-Feng Lee aes128.info.version = TLS_1_2_VERSION;
121*d1246f93SKui-Feng Lee aes128.info.cipher_type = TLS_CIPHER_AES_GCM_128;
122*d1246f93SKui-Feng Lee
123*d1246f93SKui-Feng Lee ret = setsockopt(fd, SOL_TLS, TLS_TX, &aes128, sizeof(aes128));
124*d1246f93SKui-Feng Lee if (!ASSERT_OK(ret, "setsockopt"))
125*d1246f93SKui-Feng Lee goto err_out;
126*d1246f93SKui-Feng Lee
127*d1246f93SKui-Feng Lee ret = setsockopt(cfd, SOL_TLS, TLS_RX, &aes128, sizeof(aes128));
128*d1246f93SKui-Feng Lee if (!ASSERT_OK(ret, "setsockopt"))
129*d1246f93SKui-Feng Lee goto err_out;
130*d1246f93SKui-Feng Lee
131*d1246f93SKui-Feng Lee /* KTLS is enabled */
132*d1246f93SKui-Feng Lee
133*d1246f93SKui-Feng Lee close(fd);
134*d1246f93SKui-Feng Lee /* At this point, the cfd socket is at the CLOSE_WAIT state
135*d1246f93SKui-Feng Lee * and still run TLS protocol. The test for
136*d1246f93SKui-Feng Lee * BPF_TCP_CLOSE_WAIT should be run at this point.
137*d1246f93SKui-Feng Lee */
138*d1246f93SKui-Feng Lee ret = read(cfd, &buf, sizeof(buf));
139*d1246f93SKui-Feng Lee ASSERT_EQ(ret, 0, "read");
140*d1246f93SKui-Feng Lee close(cfd);
141*d1246f93SKui-Feng Lee
142*d1246f93SKui-Feng Lee ASSERT_EQ(bss->nr_listen, 1, "nr_listen");
143*d1246f93SKui-Feng Lee ASSERT_EQ(bss->nr_connect, 1, "nr_connect");
144*d1246f93SKui-Feng Lee ASSERT_EQ(bss->nr_active, 1, "nr_active");
145*d1246f93SKui-Feng Lee ASSERT_EQ(bss->nr_passive, 1, "nr_passive");
146*d1246f93SKui-Feng Lee ASSERT_EQ(bss->nr_socket_post_create, 2, "nr_socket_post_create");
147*d1246f93SKui-Feng Lee ASSERT_EQ(bss->nr_binddev, 2, "nr_bind");
148*d1246f93SKui-Feng Lee ASSERT_EQ(bss->nr_fin_wait1, 1, "nr_fin_wait1");
149*d1246f93SKui-Feng Lee return;
150*d1246f93SKui-Feng Lee
151*d1246f93SKui-Feng Lee err_out:
152*d1246f93SKui-Feng Lee close(fd);
153*d1246f93SKui-Feng Lee close(cfd);
154*d1246f93SKui-Feng Lee close(sfd);
155*d1246f93SKui-Feng Lee }
156*d1246f93SKui-Feng Lee
test_setget_sockopt(void)15731123c03SMartin KaFai Lau void test_setget_sockopt(void)
15831123c03SMartin KaFai Lau {
15931123c03SMartin KaFai Lau cg_fd = test__join_cgroup(CG_NAME);
16031123c03SMartin KaFai Lau if (cg_fd < 0)
16131123c03SMartin KaFai Lau return;
16231123c03SMartin KaFai Lau
16331123c03SMartin KaFai Lau if (create_netns())
16431123c03SMartin KaFai Lau goto done;
16531123c03SMartin KaFai Lau
16631123c03SMartin KaFai Lau skel = setget_sockopt__open();
16731123c03SMartin KaFai Lau if (!ASSERT_OK_PTR(skel, "open skel"))
16831123c03SMartin KaFai Lau goto done;
16931123c03SMartin KaFai Lau
17031123c03SMartin KaFai Lau strcpy(skel->rodata->veth, "binddevtest1");
17131123c03SMartin KaFai Lau skel->rodata->veth_ifindex = if_nametoindex("binddevtest1");
17231123c03SMartin KaFai Lau if (!ASSERT_GT(skel->rodata->veth_ifindex, 0, "if_nametoindex"))
17331123c03SMartin KaFai Lau goto done;
17431123c03SMartin KaFai Lau
17531123c03SMartin KaFai Lau if (!ASSERT_OK(setget_sockopt__load(skel), "load skel"))
17631123c03SMartin KaFai Lau goto done;
17731123c03SMartin KaFai Lau
17831123c03SMartin KaFai Lau skel->links.skops_sockopt =
17931123c03SMartin KaFai Lau bpf_program__attach_cgroup(skel->progs.skops_sockopt, cg_fd);
18031123c03SMartin KaFai Lau if (!ASSERT_OK_PTR(skel->links.skops_sockopt, "attach cgroup"))
18131123c03SMartin KaFai Lau goto done;
18231123c03SMartin KaFai Lau
18331123c03SMartin KaFai Lau skel->links.socket_post_create =
18431123c03SMartin KaFai Lau bpf_program__attach_cgroup(skel->progs.socket_post_create, cg_fd);
18531123c03SMartin KaFai Lau if (!ASSERT_OK_PTR(skel->links.socket_post_create, "attach_cgroup"))
18631123c03SMartin KaFai Lau goto done;
18731123c03SMartin KaFai Lau
18831123c03SMartin KaFai Lau test_tcp(AF_INET6);
18931123c03SMartin KaFai Lau test_tcp(AF_INET);
19031123c03SMartin KaFai Lau test_udp(AF_INET6);
19131123c03SMartin KaFai Lau test_udp(AF_INET);
192*d1246f93SKui-Feng Lee test_ktls(AF_INET6);
193*d1246f93SKui-Feng Lee test_ktls(AF_INET);
19431123c03SMartin KaFai Lau
19531123c03SMartin KaFai Lau done:
19631123c03SMartin KaFai Lau setget_sockopt__destroy(skel);
19731123c03SMartin KaFai Lau close(cg_fd);
19831123c03SMartin KaFai Lau }
199