0001
0002 #include <test_progs.h>
0003 #include "cgroup_helpers.h"
0004
0005 #include <linux/tcp.h>
0006 #include "sockopt_sk.skel.h"
0007
0008 #ifndef SOL_TCP
0009 #define SOL_TCP IPPROTO_TCP
0010 #endif
0011
0012 #define SOL_CUSTOM 0xdeadbeef
0013
0014 static int getsetsockopt(void)
0015 {
0016 int fd, err;
0017 union {
0018 char u8[4];
0019 __u32 u32;
0020 char cc[16];
0021 struct tcp_zerocopy_receive zc;
0022 } buf = {};
0023 socklen_t optlen;
0024 char *big_buf = NULL;
0025
0026 fd = socket(AF_INET, SOCK_STREAM, 0);
0027 if (fd < 0) {
0028 log_err("Failed to create socket");
0029 return -1;
0030 }
0031
0032
0033
0034 optlen = getpagesize() * 2;
0035 big_buf = calloc(1, optlen);
0036 if (!big_buf) {
0037 log_err("Couldn't allocate two pages");
0038 goto err;
0039 }
0040
0041 *(int *)big_buf = 0x08;
0042 err = setsockopt(fd, SOL_IP, IP_TOS, big_buf, optlen);
0043 if (err) {
0044 log_err("Failed to call setsockopt(IP_TOS)");
0045 goto err;
0046 }
0047
0048 memset(big_buf, 0, optlen);
0049 optlen = 1;
0050 err = getsockopt(fd, SOL_IP, IP_TOS, big_buf, &optlen);
0051 if (err) {
0052 log_err("Failed to call getsockopt(IP_TOS)");
0053 goto err;
0054 }
0055
0056 if (*big_buf != 0x08) {
0057 log_err("Unexpected getsockopt(IP_TOS) optval 0x%x != 0x08",
0058 (int)*big_buf);
0059 goto err;
0060 }
0061
0062
0063
0064 buf.u8[0] = 1;
0065 err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
0066 if (!err || errno != EPERM) {
0067 log_err("Unexpected success from setsockopt(IP_TTL)");
0068 goto err;
0069 }
0070
0071
0072
0073 buf.u8[0] = 0x01;
0074 err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
0075 if (err) {
0076 log_err("Failed to call setsockopt");
0077 goto err;
0078 }
0079
0080 buf.u32 = 0x00;
0081 optlen = 4;
0082 err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
0083 if (err) {
0084 log_err("Failed to call getsockopt");
0085 goto err;
0086 }
0087
0088 if (optlen != 1) {
0089 log_err("Unexpected optlen %d != 1", optlen);
0090 goto err;
0091 }
0092 if (buf.u8[0] != 0x01) {
0093 log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
0094 goto err;
0095 }
0096
0097
0098
0099 optlen = getpagesize() * 2;
0100 memset(big_buf, 0, optlen);
0101
0102 err = setsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, optlen);
0103 if (err != 0) {
0104 log_err("Failed to call setsockopt, ret=%d", err);
0105 goto err;
0106 }
0107
0108 err = getsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, &optlen);
0109 if (err != 0) {
0110 log_err("Failed to call getsockopt, ret=%d", err);
0111 goto err;
0112 }
0113
0114 if (optlen != 1 || *(__u8 *)big_buf != 0x55) {
0115 log_err("Unexpected IP_FREEBIND getsockopt, optlen=%d, optval=0x%x",
0116 optlen, *(__u8 *)big_buf);
0117 }
0118
0119
0120
0121 buf.u32 = 0x01010101;
0122 err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
0123 if (err) {
0124 log_err("Failed to call setsockopt(SO_SNDBUF)");
0125 goto err;
0126 }
0127
0128 buf.u32 = 0x00;
0129 optlen = 4;
0130 err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
0131 if (err) {
0132 log_err("Failed to call getsockopt(SO_SNDBUF)");
0133 goto err;
0134 }
0135
0136 if (buf.u32 != 0x55AA*2) {
0137 log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
0138 buf.u32);
0139 goto err;
0140 }
0141
0142
0143
0144 strcpy(buf.cc, "nv");
0145 err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
0146 if (err) {
0147 log_err("Failed to call setsockopt(TCP_CONGESTION)");
0148 goto err;
0149 }
0150
0151
0152 optlen = sizeof(buf.cc);
0153 err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen);
0154 if (err) {
0155 log_err("Failed to call getsockopt(TCP_CONGESTION)");
0156 goto err;
0157 }
0158
0159 if (strcmp(buf.cc, "cubic") != 0) {
0160 log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
0161 buf.cc, "cubic");
0162 goto err;
0163 }
0164
0165
0166 memset(&buf, 0, sizeof(buf));
0167 optlen = sizeof(buf.zc);
0168 err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
0169 if (err) {
0170 log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
0171 err, errno);
0172 goto err;
0173 }
0174
0175 memset(&buf, 0, sizeof(buf));
0176 buf.zc.address = 12345;
0177 optlen = sizeof(buf.zc);
0178 errno = 0;
0179 err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
0180 if (errno != EINVAL) {
0181 log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
0182 err, errno);
0183 goto err;
0184 }
0185
0186 free(big_buf);
0187 close(fd);
0188 return 0;
0189 err:
0190 free(big_buf);
0191 close(fd);
0192 return -1;
0193 }
0194
0195 static void run_test(int cgroup_fd)
0196 {
0197 struct sockopt_sk *skel;
0198
0199 skel = sockopt_sk__open_and_load();
0200 if (!ASSERT_OK_PTR(skel, "skel_load"))
0201 goto cleanup;
0202
0203 skel->bss->page_size = getpagesize();
0204
0205 skel->links._setsockopt =
0206 bpf_program__attach_cgroup(skel->progs._setsockopt, cgroup_fd);
0207 if (!ASSERT_OK_PTR(skel->links._setsockopt, "setsockopt_link"))
0208 goto cleanup;
0209
0210 skel->links._getsockopt =
0211 bpf_program__attach_cgroup(skel->progs._getsockopt, cgroup_fd);
0212 if (!ASSERT_OK_PTR(skel->links._getsockopt, "getsockopt_link"))
0213 goto cleanup;
0214
0215 ASSERT_OK(getsetsockopt(), "getsetsockopt");
0216
0217 cleanup:
0218 sockopt_sk__destroy(skel);
0219 }
0220
0221 void test_sockopt_sk(void)
0222 {
0223 int cgroup_fd;
0224
0225 cgroup_fd = test__join_cgroup("/sockopt_sk");
0226 if (CHECK_FAIL(cgroup_fd < 0))
0227 return;
0228
0229 run_test(cgroup_fd);
0230 close(cgroup_fd);
0231 }