1
2
3
4
5
6
7
8
9
10
11
12#include <uapi/linux/bpf.h>
13#include <uapi/linux/if_ether.h>
14#include <uapi/linux/if_packet.h>
15#include <uapi/linux/ip.h>
16#include "../../tools/testing/selftests/bpf/bpf_helpers.h"
17#include "../../tools/testing/selftests/bpf/bpf_endian.h"
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#define bpf_printk(fmt, ...) \
33({ \
34 char ____fmt[] = fmt; \
35 bpf_trace_printk(____fmt, sizeof(____fmt), \
36 ##__VA_ARGS__); \
37})
38
39struct bpf_map_def SEC("maps") sock_map = {
40 .type = BPF_MAP_TYPE_SOCKMAP,
41 .key_size = sizeof(int),
42 .value_size = sizeof(int),
43 .max_entries = 20,
44};
45
46struct bpf_map_def SEC("maps") sock_map_txmsg = {
47 .type = BPF_MAP_TYPE_SOCKMAP,
48 .key_size = sizeof(int),
49 .value_size = sizeof(int),
50 .max_entries = 20,
51};
52
53struct bpf_map_def SEC("maps") sock_map_redir = {
54 .type = BPF_MAP_TYPE_SOCKMAP,
55 .key_size = sizeof(int),
56 .value_size = sizeof(int),
57 .max_entries = 20,
58};
59
60struct bpf_map_def SEC("maps") sock_apply_bytes = {
61 .type = BPF_MAP_TYPE_ARRAY,
62 .key_size = sizeof(int),
63 .value_size = sizeof(int),
64 .max_entries = 1
65};
66
67struct bpf_map_def SEC("maps") sock_cork_bytes = {
68 .type = BPF_MAP_TYPE_ARRAY,
69 .key_size = sizeof(int),
70 .value_size = sizeof(int),
71 .max_entries = 1
72};
73
74struct bpf_map_def SEC("maps") sock_pull_bytes = {
75 .type = BPF_MAP_TYPE_ARRAY,
76 .key_size = sizeof(int),
77 .value_size = sizeof(int),
78 .max_entries = 2
79};
80
81struct bpf_map_def SEC("maps") sock_redir_flags = {
82 .type = BPF_MAP_TYPE_ARRAY,
83 .key_size = sizeof(int),
84 .value_size = sizeof(int),
85 .max_entries = 1
86};
87
88struct bpf_map_def SEC("maps") sock_skb_opts = {
89 .type = BPF_MAP_TYPE_ARRAY,
90 .key_size = sizeof(int),
91 .value_size = sizeof(int),
92 .max_entries = 1
93};
94
95SEC("sk_skb1")
96int bpf_prog1(struct __sk_buff *skb)
97{
98 return skb->len;
99}
100
101SEC("sk_skb2")
102int bpf_prog2(struct __sk_buff *skb)
103{
104 __u32 lport = skb->local_port;
105 __u32 rport = skb->remote_port;
106 int len, *f, ret, zero = 0;
107 __u64 flags = 0;
108
109 if (lport == 10000)
110 ret = 10;
111 else
112 ret = 1;
113
114 len = (__u32)skb->data_end - (__u32)skb->data;
115 f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
116 if (f && *f) {
117 ret = 3;
118 flags = *f;
119 }
120
121 bpf_printk("sk_skb2: redirect(%iB) flags=%i\n",
122 len, flags);
123 return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
124}
125
126SEC("sockops")
127int bpf_sockmap(struct bpf_sock_ops *skops)
128{
129 __u32 lport, rport;
130 int op, err = 0, index, key, ret;
131
132
133 op = (int) skops->op;
134
135 switch (op) {
136 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
137 lport = skops->local_port;
138 rport = skops->remote_port;
139
140 if (lport == 10000) {
141 ret = 1;
142 err = bpf_sock_map_update(skops, &sock_map, &ret,
143 BPF_NOEXIST);
144 bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
145 lport, bpf_ntohl(rport), err);
146 }
147 break;
148 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
149 lport = skops->local_port;
150 rport = skops->remote_port;
151
152 if (bpf_ntohl(rport) == 10001) {
153 ret = 10;
154 err = bpf_sock_map_update(skops, &sock_map, &ret,
155 BPF_NOEXIST);
156 bpf_printk("active(%i -> %i) map ctx update err: %d\n",
157 lport, bpf_ntohl(rport), err);
158 }
159 break;
160 default:
161 break;
162 }
163
164 return 0;
165}
166
167SEC("sk_msg1")
168int bpf_prog4(struct sk_msg_md *msg)
169{
170 int *bytes, zero = 0, one = 1;
171 int *start, *end;
172
173 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
174 if (bytes)
175 bpf_msg_apply_bytes(msg, *bytes);
176 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
177 if (bytes)
178 bpf_msg_cork_bytes(msg, *bytes);
179 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
180 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
181 if (start && end)
182 bpf_msg_pull_data(msg, *start, *end, 0);
183 return SK_PASS;
184}
185
186SEC("sk_msg2")
187int bpf_prog5(struct sk_msg_md *msg)
188{
189 int err1 = -1, err2 = -1, zero = 0, one = 1;
190 int *bytes, *start, *end, len1, len2;
191
192 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
193 if (bytes)
194 err1 = bpf_msg_apply_bytes(msg, *bytes);
195 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
196 if (bytes)
197 err2 = bpf_msg_cork_bytes(msg, *bytes);
198 len1 = (__u64)msg->data_end - (__u64)msg->data;
199 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
200 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
201 if (start && end) {
202 int err;
203
204 bpf_printk("sk_msg2: pull(%i:%i)\n",
205 start ? *start : 0, end ? *end : 0);
206 err = bpf_msg_pull_data(msg, *start, *end, 0);
207 if (err)
208 bpf_printk("sk_msg2: pull_data err %i\n",
209 err);
210 len2 = (__u64)msg->data_end - (__u64)msg->data;
211 bpf_printk("sk_msg2: length update %i->%i\n",
212 len1, len2);
213 }
214 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
215 len1, err1, err2);
216 return SK_PASS;
217}
218
219SEC("sk_msg3")
220int bpf_prog6(struct sk_msg_md *msg)
221{
222 int *bytes, zero = 0, one = 1, key = 0;
223 int *start, *end, *f;
224 __u64 flags = 0;
225
226 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
227 if (bytes)
228 bpf_msg_apply_bytes(msg, *bytes);
229 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
230 if (bytes)
231 bpf_msg_cork_bytes(msg, *bytes);
232 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
233 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
234 if (start && end)
235 bpf_msg_pull_data(msg, *start, *end, 0);
236 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
237 if (f && *f) {
238 key = 2;
239 flags = *f;
240 }
241 return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
242}
243
244SEC("sk_msg4")
245int bpf_prog7(struct sk_msg_md *msg)
246{
247 int err1 = 0, err2 = 0, zero = 0, one = 1, key = 0;
248 int *f, *bytes, *start, *end, len1, len2;
249 __u64 flags = 0;
250
251 int err;
252 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
253 if (bytes)
254 err1 = bpf_msg_apply_bytes(msg, *bytes);
255 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
256 if (bytes)
257 err2 = bpf_msg_cork_bytes(msg, *bytes);
258 len1 = (__u64)msg->data_end - (__u64)msg->data;
259 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
260 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
261 if (start && end) {
262
263 bpf_printk("sk_msg2: pull(%i:%i)\n",
264 start ? *start : 0, end ? *end : 0);
265 err = bpf_msg_pull_data(msg, *start, *end, 0);
266 if (err)
267 bpf_printk("sk_msg2: pull_data err %i\n",
268 err);
269 len2 = (__u64)msg->data_end - (__u64)msg->data;
270 bpf_printk("sk_msg2: length update %i->%i\n",
271 len1, len2);
272 }
273 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
274 if (f && *f) {
275 key = 2;
276 flags = *f;
277 }
278 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
279 len1, flags, err1 ? err1 : err2);
280 err = bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
281 bpf_printk("sk_msg3: err %i\n", err);
282 return err;
283}
284
285SEC("sk_msg5")
286int bpf_prog8(struct sk_msg_md *msg)
287{
288 void *data_end = (void *)(long) msg->data_end;
289 void *data = (void *)(long) msg->data;
290 int ret = 0, *bytes, zero = 0;
291
292 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
293 if (bytes) {
294 ret = bpf_msg_apply_bytes(msg, *bytes);
295 if (ret)
296 return SK_DROP;
297 } else {
298 return SK_DROP;
299 }
300 return SK_PASS;
301}
302SEC("sk_msg6")
303int bpf_prog9(struct sk_msg_md *msg)
304{
305 void *data_end = (void *)(long) msg->data_end;
306 void *data = (void *)(long) msg->data;
307 int ret = 0, *bytes, zero = 0;
308
309 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
310 if (bytes) {
311 if (((__u64)data_end - (__u64)data) >= *bytes)
312 return SK_PASS;
313 ret = bpf_msg_cork_bytes(msg, *bytes);
314 if (ret)
315 return SK_DROP;
316 }
317 return SK_PASS;
318}
319
320SEC("sk_msg7")
321int bpf_prog10(struct sk_msg_md *msg)
322{
323 int *bytes, zero = 0, one = 1;
324 int *start, *end;
325
326 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
327 if (bytes)
328 bpf_msg_apply_bytes(msg, *bytes);
329 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
330 if (bytes)
331 bpf_msg_cork_bytes(msg, *bytes);
332 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
333 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
334 if (start && end)
335 bpf_msg_pull_data(msg, *start, *end, 0);
336
337 return SK_DROP;
338}
339
340
341char _license[] SEC("license") = "GPL";
342