root/tools/testing/selftests/bpf/prog_tests/sockopt_sk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. getsetsockopt
  2. prog_attach
  3. run_test
  4. test_sockopt_sk

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <test_progs.h>
   3 #include "cgroup_helpers.h"
   4 
   5 #define SOL_CUSTOM                      0xdeadbeef
   6 
   7 static int getsetsockopt(void)
   8 {
   9         int fd, err;
  10         union {
  11                 char u8[4];
  12                 __u32 u32;
  13                 char cc[16]; /* TCP_CA_NAME_MAX */
  14         } buf = {};
  15         socklen_t optlen;
  16 
  17         fd = socket(AF_INET, SOCK_STREAM, 0);
  18         if (fd < 0) {
  19                 log_err("Failed to create socket");
  20                 return -1;
  21         }
  22 
  23         /* IP_TOS - BPF bypass */
  24 
  25         buf.u8[0] = 0x08;
  26         err = setsockopt(fd, SOL_IP, IP_TOS, &buf, 1);
  27         if (err) {
  28                 log_err("Failed to call setsockopt(IP_TOS)");
  29                 goto err;
  30         }
  31 
  32         buf.u8[0] = 0x00;
  33         optlen = 1;
  34         err = getsockopt(fd, SOL_IP, IP_TOS, &buf, &optlen);
  35         if (err) {
  36                 log_err("Failed to call getsockopt(IP_TOS)");
  37                 goto err;
  38         }
  39 
  40         if (buf.u8[0] != 0x08) {
  41                 log_err("Unexpected getsockopt(IP_TOS) buf[0] 0x%02x != 0x08",
  42                         buf.u8[0]);
  43                 goto err;
  44         }
  45 
  46         /* IP_TTL - EPERM */
  47 
  48         buf.u8[0] = 1;
  49         err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
  50         if (!err || errno != EPERM) {
  51                 log_err("Unexpected success from setsockopt(IP_TTL)");
  52                 goto err;
  53         }
  54 
  55         /* SOL_CUSTOM - handled by BPF */
  56 
  57         buf.u8[0] = 0x01;
  58         err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
  59         if (err) {
  60                 log_err("Failed to call setsockopt");
  61                 goto err;
  62         }
  63 
  64         buf.u32 = 0x00;
  65         optlen = 4;
  66         err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
  67         if (err) {
  68                 log_err("Failed to call getsockopt");
  69                 goto err;
  70         }
  71 
  72         if (optlen != 1) {
  73                 log_err("Unexpected optlen %d != 1", optlen);
  74                 goto err;
  75         }
  76         if (buf.u8[0] != 0x01) {
  77                 log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
  78                 goto err;
  79         }
  80 
  81         /* SO_SNDBUF is overwritten */
  82 
  83         buf.u32 = 0x01010101;
  84         err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
  85         if (err) {
  86                 log_err("Failed to call setsockopt(SO_SNDBUF)");
  87                 goto err;
  88         }
  89 
  90         buf.u32 = 0x00;
  91         optlen = 4;
  92         err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
  93         if (err) {
  94                 log_err("Failed to call getsockopt(SO_SNDBUF)");
  95                 goto err;
  96         }
  97 
  98         if (buf.u32 != 0x55AA*2) {
  99                 log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
 100                         buf.u32);
 101                 goto err;
 102         }
 103 
 104         /* TCP_CONGESTION can extend the string */
 105 
 106         strcpy(buf.cc, "nv");
 107         err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
 108         if (err) {
 109                 log_err("Failed to call setsockopt(TCP_CONGESTION)");
 110                 goto err;
 111         }
 112 
 113 
 114         optlen = sizeof(buf.cc);
 115         err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen);
 116         if (err) {
 117                 log_err("Failed to call getsockopt(TCP_CONGESTION)");
 118                 goto err;
 119         }
 120 
 121         if (strcmp(buf.cc, "cubic") != 0) {
 122                 log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
 123                         buf.cc, "cubic");
 124                 goto err;
 125         }
 126 
 127         close(fd);
 128         return 0;
 129 err:
 130         close(fd);
 131         return -1;
 132 }
 133 
 134 static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
 135 {
 136         enum bpf_attach_type attach_type;
 137         enum bpf_prog_type prog_type;
 138         struct bpf_program *prog;
 139         int err;
 140 
 141         err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
 142         if (err) {
 143                 log_err("Failed to deduct types for %s BPF program", title);
 144                 return -1;
 145         }
 146 
 147         prog = bpf_object__find_program_by_title(obj, title);
 148         if (!prog) {
 149                 log_err("Failed to find %s BPF program", title);
 150                 return -1;
 151         }
 152 
 153         err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
 154                               attach_type, 0);
 155         if (err) {
 156                 log_err("Failed to attach %s BPF program", title);
 157                 return -1;
 158         }
 159 
 160         return 0;
 161 }
 162 
 163 static void run_test(int cgroup_fd)
 164 {
 165         struct bpf_prog_load_attr attr = {
 166                 .file = "./sockopt_sk.o",
 167         };
 168         struct bpf_object *obj;
 169         int ignored;
 170         int err;
 171 
 172         err = bpf_prog_load_xattr(&attr, &obj, &ignored);
 173         if (CHECK_FAIL(err))
 174                 return;
 175 
 176         err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt");
 177         if (CHECK_FAIL(err))
 178                 goto close_bpf_object;
 179 
 180         err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt");
 181         if (CHECK_FAIL(err))
 182                 goto close_bpf_object;
 183 
 184         CHECK_FAIL(getsetsockopt());
 185 
 186 close_bpf_object:
 187         bpf_object__close(obj);
 188 }
 189 
 190 void test_sockopt_sk(void)
 191 {
 192         int cgroup_fd;
 193 
 194         cgroup_fd = test__join_cgroup("/sockopt_sk");
 195         if (CHECK_FAIL(cgroup_fd < 0))
 196                 return;
 197 
 198         run_test(cgroup_fd);
 199         close(cgroup_fd);
 200 }

/* [<][>][^][v][top][bottom][index][help] */