173 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <test_progs.h>3#include "cgroup_helpers.h"4#include "network_helpers.h"5 6#include "sockopt_inherit.skel.h"7 8#define SOL_CUSTOM 0xdeadbeef9#define CUSTOM_INHERIT1 010#define CUSTOM_INHERIT2 111#define CUSTOM_LISTENER 212 13static int verify_sockopt(int fd, int optname, const char *msg, char expected)14{15 socklen_t optlen = 1;16 char buf = 0;17 int err;18 19 err = getsockopt(fd, SOL_CUSTOM, optname, &buf, &optlen);20 if (err) {21 log_err("%s: failed to call getsockopt", msg);22 return 1;23 }24 25 printf("%s %d: got=0x%x ? expected=0x%x\n", msg, optname, buf, expected);26 27 if (buf != expected) {28 log_err("%s: unexpected getsockopt value %d != %d", msg,29 buf, expected);30 return 1;31 }32 33 return 0;34}35 36static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER;37static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER;38 39static void *server_thread(void *arg)40{41 struct sockaddr_storage addr;42 socklen_t len = sizeof(addr);43 int fd = *(int *)arg;44 int client_fd;45 int err = 0;46 47 err = listen(fd, 1);48 49 pthread_mutex_lock(&server_started_mtx);50 pthread_cond_signal(&server_started);51 pthread_mutex_unlock(&server_started_mtx);52 53 if (!ASSERT_GE(err, 0, "listed on socket"))54 return NULL;55 56 err += verify_sockopt(fd, CUSTOM_INHERIT1, "listen", 1);57 err += verify_sockopt(fd, CUSTOM_INHERIT2, "listen", 1);58 err += verify_sockopt(fd, CUSTOM_LISTENER, "listen", 1);59 60 client_fd = accept(fd, (struct sockaddr *)&addr, &len);61 if (!ASSERT_GE(client_fd, 0, "accept client"))62 return NULL;63 64 err += verify_sockopt(client_fd, CUSTOM_INHERIT1, "accept", 1);65 err += verify_sockopt(client_fd, CUSTOM_INHERIT2, "accept", 1);66 err += verify_sockopt(client_fd, CUSTOM_LISTENER, "accept", 0);67 68 close(client_fd);69 70 return (void *)(long)err;71}72 73static int custom_cb(int fd, void *opts)74{75 char buf;76 int err;77 int i;78 79 for (i = CUSTOM_INHERIT1; i <= CUSTOM_LISTENER; i++) {80 buf = 0x01;81 err = setsockopt(fd, SOL_CUSTOM, i, &buf, 1);82 if (err) {83 log_err("Failed to call setsockopt(%d)", i);84 return -1;85 }86 }87 88 return 0;89}90 91static void run_test(int cgroup_fd)92{93 struct bpf_link *link_getsockopt = NULL;94 struct bpf_link *link_setsockopt = NULL;95 struct network_helper_opts opts = {96 .post_socket_cb = custom_cb,97 };98 int server_fd = -1, client_fd;99 struct sockaddr_in addr = {100 .sin_family = AF_INET,101 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),102 };103 struct sockopt_inherit *obj;104 void *server_err;105 pthread_t tid;106 int err;107 108 obj = sockopt_inherit__open_and_load();109 if (!ASSERT_OK_PTR(obj, "skel-load"))110 return;111 112 obj->bss->page_size = sysconf(_SC_PAGESIZE);113 114 link_getsockopt = bpf_program__attach_cgroup(obj->progs._getsockopt,115 cgroup_fd);116 if (!ASSERT_OK_PTR(link_getsockopt, "cg-attach-getsockopt"))117 goto close_bpf_object;118 119 link_setsockopt = bpf_program__attach_cgroup(obj->progs._setsockopt,120 cgroup_fd);121 if (!ASSERT_OK_PTR(link_setsockopt, "cg-attach-setsockopt"))122 goto close_bpf_object;123 124 server_fd = start_server_addr(SOCK_STREAM, (struct sockaddr_storage *)&addr,125 sizeof(addr), &opts);126 if (!ASSERT_GE(server_fd, 0, "start_server"))127 goto close_bpf_object;128 129 pthread_mutex_lock(&server_started_mtx);130 if (!ASSERT_OK(pthread_create(&tid, NULL, server_thread,131 (void *)&server_fd), "pthread_create")) {132 pthread_mutex_unlock(&server_started_mtx);133 goto close_server_fd;134 }135 pthread_cond_wait(&server_started, &server_started_mtx);136 pthread_mutex_unlock(&server_started_mtx);137 138 client_fd = connect_to_fd(server_fd, 0);139 if (!ASSERT_GE(client_fd, 0, "connect_to_server"))140 goto close_server_fd;141 142 ASSERT_OK(verify_sockopt(client_fd, CUSTOM_INHERIT1, "connect", 0), "verify_sockopt1");143 ASSERT_OK(verify_sockopt(client_fd, CUSTOM_INHERIT2, "connect", 0), "verify_sockopt2");144 ASSERT_OK(verify_sockopt(client_fd, CUSTOM_LISTENER, "connect", 0), "verify_sockopt ener");145 146 pthread_join(tid, &server_err);147 148 err = (int)(long)server_err;149 ASSERT_OK(err, "pthread_join retval");150 151 close(client_fd);152 153close_server_fd:154 close(server_fd);155close_bpf_object:156 bpf_link__destroy(link_getsockopt);157 bpf_link__destroy(link_setsockopt);158 159 sockopt_inherit__destroy(obj);160}161 162void test_sockopt_inherit(void)163{164 int cgroup_fd;165 166 cgroup_fd = test__join_cgroup("/sockopt_inherit");167 if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup"))168 return;169 170 run_test(cgroup_fd);171 close(cgroup_fd);172}173