1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
3 #include <stddef.h>
4 #include <string.h>
5 #include <linux/bpf.h>
6 #include <linux/if_ether.h>
7 #include <linux/if_packet.h>
8 #include <linux/ip.h>
9 #include <linux/ipv6.h>
10 #include <linux/in.h>
11 #include <linux/udp.h>
12 #include <linux/tcp.h>
13 #include <linux/pkt_cls.h>
14 #include <sys/socket.h>
15 #include "bpf_helpers.h"
16 #include "bpf_endian.h"
17
18 /* Sockmap sample program connects a client and a backend together
19 * using cgroups.
20 *
21 * client:X <---> frontend:80 client:X <---> backend:80
22 *
23 * For simplicity we hard code values here and bind 1:1. The hard
24 * coded values are part of the setup in sockmap.sh script that
25 * is associated with this BPF program.
26 *
27 * The bpf_printk is verbose and prints information as connections
28 * are established and verdicts are decided.
29 */
30
31 #define bpf_printk(fmt, ...) \
32 ({ \
33 char ____fmt[] = fmt; \
34 bpf_trace_printk(____fmt, sizeof(____fmt), \
35 ##__VA_ARGS__); \
36 })
37
38 struct bpf_map_def SEC("maps") sock_map = {
39 .type = TEST_MAP_TYPE,
40 .key_size = sizeof(int),
41 .value_size = sizeof(int),
42 .max_entries = 20,
43 };
44
45 struct bpf_map_def SEC("maps") sock_map_txmsg = {
46 .type = TEST_MAP_TYPE,
47 .key_size = sizeof(int),
48 .value_size = sizeof(int),
49 .max_entries = 20,
50 };
51
52 struct bpf_map_def SEC("maps") sock_map_redir = {
53 .type = TEST_MAP_TYPE,
54 .key_size = sizeof(int),
55 .value_size = sizeof(int),
56 .max_entries = 20,
57 };
58
59 struct bpf_map_def SEC("maps") sock_apply_bytes = {
60 .type = BPF_MAP_TYPE_ARRAY,
61 .key_size = sizeof(int),
62 .value_size = sizeof(int),
63 .max_entries = 1
64 };
65
66 struct bpf_map_def SEC("maps") sock_cork_bytes = {
67 .type = BPF_MAP_TYPE_ARRAY,
68 .key_size = sizeof(int),
69 .value_size = sizeof(int),
70 .max_entries = 1
71 };
72
73 struct bpf_map_def SEC("maps") sock_bytes = {
74 .type = BPF_MAP_TYPE_ARRAY,
75 .key_size = sizeof(int),
76 .value_size = sizeof(int),
77 .max_entries = 4
78 };
79
80 struct bpf_map_def SEC("maps") sock_redir_flags = {
81 .type = BPF_MAP_TYPE_ARRAY,
82 .key_size = sizeof(int),
83 .value_size = sizeof(int),
84 .max_entries = 1
85 };
86
87 struct bpf_map_def SEC("maps") sock_skb_opts = {
88 .type = BPF_MAP_TYPE_ARRAY,
89 .key_size = sizeof(int),
90 .value_size = sizeof(int),
91 .max_entries = 1
92 };
93
94 SEC("sk_skb1")
bpf_prog1(struct __sk_buff * skb)95 int bpf_prog1(struct __sk_buff *skb)
96 {
97 return skb->len;
98 }
99
100 SEC("sk_skb2")
bpf_prog2(struct __sk_buff * skb)101 int bpf_prog2(struct __sk_buff *skb)
102 {
103 __u32 lport = skb->local_port;
104 __u32 rport = skb->remote_port;
105 int len, *f, ret, zero = 0;
106 __u64 flags = 0;
107
108 if (lport == 10000)
109 ret = 10;
110 else
111 ret = 1;
112
113 len = (__u32)skb->data_end - (__u32)skb->data;
114 f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
115 if (f && *f) {
116 ret = 3;
117 flags = *f;
118 }
119
120 bpf_printk("sk_skb2: redirect(%iB) flags=%i\n",
121 len, flags);
122 #ifdef SOCKMAP
123 return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
124 #else
125 return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);
126 #endif
127
128 }
129
130 SEC("sockops")
bpf_sockmap(struct bpf_sock_ops * skops)131 int bpf_sockmap(struct bpf_sock_ops *skops)
132 {
133 __u32 lport, rport;
134 int op, err = 0, index, key, ret;
135
136
137 op = (int) skops->op;
138
139 switch (op) {
140 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
141 lport = skops->local_port;
142 rport = skops->remote_port;
143
144 if (lport == 10000) {
145 ret = 1;
146 #ifdef SOCKMAP
147 err = bpf_sock_map_update(skops, &sock_map, &ret,
148 BPF_NOEXIST);
149 #else
150 err = bpf_sock_hash_update(skops, &sock_map, &ret,
151 BPF_NOEXIST);
152 #endif
153 bpf_printk("passive(%i -> %i) map ctx update err: %d\n",
154 lport, bpf_ntohl(rport), err);
155 }
156 break;
157 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
158 lport = skops->local_port;
159 rport = skops->remote_port;
160
161 if (bpf_ntohl(rport) == 10001) {
162 ret = 10;
163 #ifdef SOCKMAP
164 err = bpf_sock_map_update(skops, &sock_map, &ret,
165 BPF_NOEXIST);
166 #else
167 err = bpf_sock_hash_update(skops, &sock_map, &ret,
168 BPF_NOEXIST);
169 #endif
170 bpf_printk("active(%i -> %i) map ctx update err: %d\n",
171 lport, bpf_ntohl(rport), err);
172 }
173 break;
174 default:
175 break;
176 }
177
178 return 0;
179 }
180
181 SEC("sk_msg1")
bpf_prog4(struct sk_msg_md * msg)182 int bpf_prog4(struct sk_msg_md *msg)
183 {
184 int *bytes, zero = 0, one = 1, two = 2, three = 3;
185 int *start, *end, *start_push, *end_push;
186
187 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
188 if (bytes)
189 bpf_msg_apply_bytes(msg, *bytes);
190 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
191 if (bytes)
192 bpf_msg_cork_bytes(msg, *bytes);
193 start = bpf_map_lookup_elem(&sock_bytes, &zero);
194 end = bpf_map_lookup_elem(&sock_bytes, &one);
195 if (start && end)
196 bpf_msg_pull_data(msg, *start, *end, 0);
197 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
198 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
199 if (start_push && end_push)
200 bpf_msg_push_data(msg, *start_push, *end_push, 0);
201 return SK_PASS;
202 }
203
204 SEC("sk_msg2")
bpf_prog5(struct sk_msg_md * msg)205 int bpf_prog5(struct sk_msg_md *msg)
206 {
207 int zero = 0, one = 1, two = 2, three = 3;
208 int *start, *end, *start_push, *end_push;
209 int *bytes, len1, len2 = 0, len3;
210 int err1 = -1, err2 = -1;
211
212 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
213 if (bytes)
214 err1 = bpf_msg_apply_bytes(msg, *bytes);
215 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
216 if (bytes)
217 err2 = bpf_msg_cork_bytes(msg, *bytes);
218 len1 = (__u64)msg->data_end - (__u64)msg->data;
219 start = bpf_map_lookup_elem(&sock_bytes, &zero);
220 end = bpf_map_lookup_elem(&sock_bytes, &one);
221 if (start && end) {
222 int err;
223
224 bpf_printk("sk_msg2: pull(%i:%i)\n",
225 start ? *start : 0, end ? *end : 0);
226 err = bpf_msg_pull_data(msg, *start, *end, 0);
227 if (err)
228 bpf_printk("sk_msg2: pull_data err %i\n",
229 err);
230 len2 = (__u64)msg->data_end - (__u64)msg->data;
231 bpf_printk("sk_msg2: length update %i->%i\n",
232 len1, len2);
233 }
234
235 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
236 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
237 if (start_push && end_push) {
238 int err;
239
240 bpf_printk("sk_msg2: push(%i:%i)\n",
241 start_push ? *start_push : 0,
242 end_push ? *end_push : 0);
243 err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
244 if (err)
245 bpf_printk("sk_msg2: push_data err %i\n", err);
246 len3 = (__u64)msg->data_end - (__u64)msg->data;
247 bpf_printk("sk_msg2: length push_update %i->%i\n",
248 len2 ? len2 : len1, len3);
249 }
250
251 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
252 len1, err1, err2);
253 return SK_PASS;
254 }
255
256 SEC("sk_msg3")
bpf_prog6(struct sk_msg_md * msg)257 int bpf_prog6(struct sk_msg_md *msg)
258 {
259 int *bytes, *start, *end, *start_push, *end_push, *f;
260 int zero = 0, one = 1, two = 2, three = 3, key = 0;
261 __u64 flags = 0;
262
263 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
264 if (bytes)
265 bpf_msg_apply_bytes(msg, *bytes);
266 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
267 if (bytes)
268 bpf_msg_cork_bytes(msg, *bytes);
269
270 start = bpf_map_lookup_elem(&sock_bytes, &zero);
271 end = bpf_map_lookup_elem(&sock_bytes, &one);
272 if (start && end)
273 bpf_msg_pull_data(msg, *start, *end, 0);
274
275 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
276 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
277 if (start_push && end_push)
278 bpf_msg_push_data(msg, *start_push, *end_push, 0);
279
280 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
281 if (f && *f) {
282 key = 2;
283 flags = *f;
284 }
285 #ifdef SOCKMAP
286 return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
287 #else
288 return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
289 #endif
290 }
291
292 SEC("sk_msg4")
bpf_prog7(struct sk_msg_md * msg)293 int bpf_prog7(struct sk_msg_md *msg)
294 {
295 int zero = 0, one = 1, two = 2, three = 3, len1, len2 = 0, len3;
296 int *bytes, *start, *end, *start_push, *end_push, *f;
297 int err1 = 0, err2 = 0, key = 0;
298 __u64 flags = 0;
299
300 int err;
301 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
302 if (bytes)
303 err1 = bpf_msg_apply_bytes(msg, *bytes);
304 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
305 if (bytes)
306 err2 = bpf_msg_cork_bytes(msg, *bytes);
307 len1 = (__u64)msg->data_end - (__u64)msg->data;
308
309 start = bpf_map_lookup_elem(&sock_bytes, &zero);
310 end = bpf_map_lookup_elem(&sock_bytes, &one);
311 if (start && end) {
312 bpf_printk("sk_msg2: pull(%i:%i)\n",
313 start ? *start : 0, end ? *end : 0);
314 err = bpf_msg_pull_data(msg, *start, *end, 0);
315 if (err)
316 bpf_printk("sk_msg2: pull_data err %i\n",
317 err);
318 len2 = (__u64)msg->data_end - (__u64)msg->data;
319 bpf_printk("sk_msg2: length update %i->%i\n",
320 len1, len2);
321 }
322
323 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
324 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
325 if (start_push && end_push) {
326 bpf_printk("sk_msg4: push(%i:%i)\n",
327 start_push ? *start_push : 0,
328 end_push ? *end_push : 0);
329 err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
330 if (err)
331 bpf_printk("sk_msg4: push_data err %i\n",
332 err);
333 len3 = (__u64)msg->data_end - (__u64)msg->data;
334 bpf_printk("sk_msg4: length push_update %i->%i\n",
335 len2 ? len2 : len1, len3);
336 }
337
338 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
339 if (f && *f) {
340 key = 2;
341 flags = *f;
342 }
343 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
344 len1, flags, err1 ? err1 : err2);
345 #ifdef SOCKMAP
346 err = bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
347 #else
348 err = bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
349 #endif
350 bpf_printk("sk_msg3: err %i\n", err);
351 return err;
352 }
353
354 SEC("sk_msg5")
bpf_prog8(struct sk_msg_md * msg)355 int bpf_prog8(struct sk_msg_md *msg)
356 {
357 void *data_end = (void *)(long) msg->data_end;
358 void *data = (void *)(long) msg->data;
359 int ret = 0, *bytes, zero = 0;
360
361 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
362 if (bytes) {
363 ret = bpf_msg_apply_bytes(msg, *bytes);
364 if (ret)
365 return SK_DROP;
366 } else {
367 return SK_DROP;
368 }
369 return SK_PASS;
370 }
371 SEC("sk_msg6")
bpf_prog9(struct sk_msg_md * msg)372 int bpf_prog9(struct sk_msg_md *msg)
373 {
374 void *data_end = (void *)(long) msg->data_end;
375 void *data = (void *)(long) msg->data;
376 int ret = 0, *bytes, zero = 0;
377
378 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
379 if (bytes) {
380 if (((__u64)data_end - (__u64)data) >= *bytes)
381 return SK_PASS;
382 ret = bpf_msg_cork_bytes(msg, *bytes);
383 if (ret)
384 return SK_DROP;
385 }
386 return SK_PASS;
387 }
388
389 SEC("sk_msg7")
bpf_prog10(struct sk_msg_md * msg)390 int bpf_prog10(struct sk_msg_md *msg)
391 {
392 int *bytes, *start, *end, *start_push, *end_push;
393 int zero = 0, one = 1, two = 2, three = 3;
394
395 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
396 if (bytes)
397 bpf_msg_apply_bytes(msg, *bytes);
398 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
399 if (bytes)
400 bpf_msg_cork_bytes(msg, *bytes);
401 start = bpf_map_lookup_elem(&sock_bytes, &zero);
402 end = bpf_map_lookup_elem(&sock_bytes, &one);
403 if (start && end)
404 bpf_msg_pull_data(msg, *start, *end, 0);
405 start_push = bpf_map_lookup_elem(&sock_bytes, &two);
406 end_push = bpf_map_lookup_elem(&sock_bytes, &three);
407 if (start_push && end_push)
408 bpf_msg_push_data(msg, *start_push, *end_push, 0);
409
410 return SK_DROP;
411 }
412
413 int _version SEC("version") = 1;
414 char _license[] SEC("license") = "GPL";
415