~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/progs/bind6_prog.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 
  3 #include <string.h>
  4 
  5 #include <linux/stddef.h>
  6 #include <linux/bpf.h>
  7 #include <linux/in.h>
  8 #include <linux/in6.h>
  9 #include <linux/if.h>
 10 #include <errno.h>
 11 
 12 #include <bpf/bpf_helpers.h>
 13 #include <bpf/bpf_endian.h>
 14 
 15 #include "bind_prog.h"
 16 
 17 #define SERV6_IP_0              0xfaceb00c /* face:b00c:1234:5678::abcd */
 18 #define SERV6_IP_1              0x12345678
 19 #define SERV6_IP_2              0x00000000
 20 #define SERV6_IP_3              0x0000abcd
 21 #define SERV6_PORT              6060
 22 #define SERV6_REWRITE_IP_0      0x00000000
 23 #define SERV6_REWRITE_IP_1      0x00000000
 24 #define SERV6_REWRITE_IP_2      0x00000000
 25 #define SERV6_REWRITE_IP_3      0x00000001
 26 #define SERV6_REWRITE_PORT      6666
 27 
 28 #ifndef IFNAMSIZ
 29 #define IFNAMSIZ 16
 30 #endif
 31 
 32 static __inline int bind_to_device(struct bpf_sock_addr *ctx)
 33 {
 34         char veth1[IFNAMSIZ] = "test_sock_addr1";
 35         char veth2[IFNAMSIZ] = "test_sock_addr2";
 36         char missing[IFNAMSIZ] = "nonexistent_dev";
 37         char del_bind[IFNAMSIZ] = "";
 38         int veth1_idx, veth2_idx;
 39 
 40         if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 41                            &veth1, sizeof(veth1)))
 42                 return 1;
 43         if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 44                            &veth1_idx, sizeof(veth1_idx)) || !veth1_idx)
 45                 return 1;
 46         if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 47                            &veth2, sizeof(veth2)))
 48                 return 1;
 49         if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 50                            &veth2_idx, sizeof(veth2_idx)) || !veth2_idx ||
 51             veth1_idx == veth2_idx)
 52                 return 1;
 53         if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 54                            &missing, sizeof(missing)) != -ENODEV)
 55                 return 1;
 56         if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 57                            &veth1_idx, sizeof(veth1_idx)))
 58                 return 1;
 59         if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 60                            &del_bind, sizeof(del_bind)))
 61                 return 1;
 62 
 63         return 0;
 64 }
 65 
 66 static __inline int bind_reuseport(struct bpf_sock_addr *ctx)
 67 {
 68         int val = 1;
 69 
 70         if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 71                            &val, sizeof(val)))
 72                 return 1;
 73         if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 74                            &val, sizeof(val)) || !val)
 75                 return 1;
 76         val = 0;
 77         if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 78                            &val, sizeof(val)))
 79                 return 1;
 80         if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 81                            &val, sizeof(val)) || val)
 82                 return 1;
 83 
 84         return 0;
 85 }
 86 
 87 static __inline int misc_opts(struct bpf_sock_addr *ctx, int opt)
 88 {
 89         int old, tmp, new = 0xeb9f;
 90 
 91         /* Socket in test case has guarantee that old never equals to new. */
 92         if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)) ||
 93             old == new)
 94                 return 1;
 95         if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &new, sizeof(new)))
 96                 return 1;
 97         if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &tmp, sizeof(tmp)) ||
 98             tmp != new)
 99                 return 1;
100         if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)))
101                 return 1;
102 
103         return 0;
104 }
105 
106 SEC("cgroup/bind6")
107 int bind_v6_prog(struct bpf_sock_addr *ctx)
108 {
109         struct bpf_sock *sk;
110         __u32 user_ip6;
111         __u16 user_port;
112         int i;
113 
114         sk = ctx->sk;
115         if (!sk)
116                 return 0;
117 
118         if (sk->family != AF_INET6)
119                 return 0;
120 
121         if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
122                 return 0;
123 
124         if (ctx->user_ip6[0] != bpf_htonl(SERV6_IP_0) ||
125             ctx->user_ip6[1] != bpf_htonl(SERV6_IP_1) ||
126             ctx->user_ip6[2] != bpf_htonl(SERV6_IP_2) ||
127             ctx->user_ip6[3] != bpf_htonl(SERV6_IP_3) ||
128             ctx->user_port != bpf_htons(SERV6_PORT))
129                 return 0;
130 
131         // u8 narrow loads:
132         for (i = 0; i < 4; i++) {
133                 user_ip6 = 0;
134                 user_ip6 |= load_byte(ctx->user_ip6[i], 0, sizeof(user_ip6));
135                 user_ip6 |= load_byte(ctx->user_ip6[i], 1, sizeof(user_ip6));
136                 user_ip6 |= load_byte(ctx->user_ip6[i], 2, sizeof(user_ip6));
137                 user_ip6 |= load_byte(ctx->user_ip6[i], 3, sizeof(user_ip6));
138                 if (ctx->user_ip6[i] != user_ip6)
139                         return 0;
140         }
141 
142         user_port = 0;
143         user_port |= load_byte(ctx->user_port, 0, sizeof(user_port));
144         user_port |= load_byte(ctx->user_port, 1, sizeof(user_port));
145         if (ctx->user_port != user_port)
146                 return 0;
147 
148         // u16 narrow loads:
149         for (i = 0; i < 4; i++) {
150                 user_ip6 = 0;
151                 user_ip6 |= load_word(ctx->user_ip6[i], 0, sizeof(user_ip6));
152                 user_ip6 |= load_word(ctx->user_ip6[i], 1, sizeof(user_ip6));
153                 if (ctx->user_ip6[i] != user_ip6)
154                         return 0;
155         }
156 
157         /* Bind to device and unbind it. */
158         if (bind_to_device(ctx))
159                 return 0;
160 
161         /* Test for misc socket options. */
162         if (misc_opts(ctx, SO_MARK) || misc_opts(ctx, SO_PRIORITY))
163                 return 0;
164 
165         /* Set reuseport and unset */
166         if (bind_reuseport(ctx))
167                 return 0;
168 
169         ctx->user_ip6[0] = bpf_htonl(SERV6_REWRITE_IP_0);
170         ctx->user_ip6[1] = bpf_htonl(SERV6_REWRITE_IP_1);
171         ctx->user_ip6[2] = bpf_htonl(SERV6_REWRITE_IP_2);
172         ctx->user_ip6[3] = bpf_htonl(SERV6_REWRITE_IP_3);
173         ctx->user_port = bpf_htons(SERV6_REWRITE_PORT);
174 
175         return 1;
176 }
177 
178 SEC("cgroup/bind6")
179 int bind_v6_deny_prog(struct bpf_sock_addr *ctx)
180 {
181         return 0;
182 }
183 
184 char _license[] SEC("license") = "GPL";
185 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php