1
2
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
19
20
21
22
23
24
25
26
27
28
29
30
31#define bpf_printk(fmt, ...) \
32({ \
33 char ____fmt[] = fmt; \
34 bpf_trace_printk(____fmt, sizeof(____fmt), \
35 ##__VA_ARGS__); \
36})
37
38struct 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
45struct 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
52struct 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
59struct 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
66struct 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
73struct bpf_map_def SEC("maps") sock_pull_bytes = {
74 .type = BPF_MAP_TYPE_ARRAY,
75 .key_size = sizeof(int),
76 .value_size = sizeof(int),
77 .max_entries = 2
78};
79
80struct 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
87struct 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
94SEC("sk_skb1")
95int bpf_prog1(struct __sk_buff *skb)
96{
97 return skb->len;
98}
99
100SEC("sk_skb2")
101int 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
130SEC("sockops")
131int 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
181SEC("sk_msg1")
182int bpf_prog4(struct sk_msg_md *msg)
183{
184 int *bytes, zero = 0, one = 1;
185 int *start, *end;
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_pull_bytes, &zero);
194 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
195 if (start && end)
196 bpf_msg_pull_data(msg, *start, *end, 0);
197 return SK_PASS;
198}
199
200SEC("sk_msg2")
201int bpf_prog5(struct sk_msg_md *msg)
202{
203 int err1 = -1, err2 = -1, zero = 0, one = 1;
204 int *bytes, *start, *end, len1, len2;
205
206 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
207 if (bytes)
208 err1 = bpf_msg_apply_bytes(msg, *bytes);
209 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
210 if (bytes)
211 err2 = bpf_msg_cork_bytes(msg, *bytes);
212 len1 = (__u64)msg->data_end - (__u64)msg->data;
213 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
214 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
215 if (start && end) {
216 int err;
217
218 bpf_printk("sk_msg2: pull(%i:%i)\n",
219 start ? *start : 0, end ? *end : 0);
220 err = bpf_msg_pull_data(msg, *start, *end, 0);
221 if (err)
222 bpf_printk("sk_msg2: pull_data err %i\n",
223 err);
224 len2 = (__u64)msg->data_end - (__u64)msg->data;
225 bpf_printk("sk_msg2: length update %i->%i\n",
226 len1, len2);
227 }
228 bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
229 len1, err1, err2);
230 return SK_PASS;
231}
232
233SEC("sk_msg3")
234int bpf_prog6(struct sk_msg_md *msg)
235{
236 int *bytes, zero = 0, one = 1, key = 0;
237 int *start, *end, *f;
238 __u64 flags = 0;
239
240 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
241 if (bytes)
242 bpf_msg_apply_bytes(msg, *bytes);
243 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
244 if (bytes)
245 bpf_msg_cork_bytes(msg, *bytes);
246 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
247 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
248 if (start && end)
249 bpf_msg_pull_data(msg, *start, *end, 0);
250 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
251 if (f && *f) {
252 key = 2;
253 flags = *f;
254 }
255#ifdef SOCKMAP
256 return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
257#else
258 return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
259#endif
260}
261
262SEC("sk_msg4")
263int bpf_prog7(struct sk_msg_md *msg)
264{
265 int err1 = 0, err2 = 0, zero = 0, one = 1, key = 0;
266 int *f, *bytes, *start, *end, len1, len2;
267 __u64 flags = 0;
268
269 int err;
270 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
271 if (bytes)
272 err1 = bpf_msg_apply_bytes(msg, *bytes);
273 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
274 if (bytes)
275 err2 = bpf_msg_cork_bytes(msg, *bytes);
276 len1 = (__u64)msg->data_end - (__u64)msg->data;
277 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
278 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
279 if (start && end) {
280
281 bpf_printk("sk_msg2: pull(%i:%i)\n",
282 start ? *start : 0, end ? *end : 0);
283 err = bpf_msg_pull_data(msg, *start, *end, 0);
284 if (err)
285 bpf_printk("sk_msg2: pull_data err %i\n",
286 err);
287 len2 = (__u64)msg->data_end - (__u64)msg->data;
288 bpf_printk("sk_msg2: length update %i->%i\n",
289 len1, len2);
290 }
291 f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
292 if (f && *f) {
293 key = 2;
294 flags = *f;
295 }
296 bpf_printk("sk_msg3: redirect(%iB) flags=%i err=%i\n",
297 len1, flags, err1 ? err1 : err2);
298#ifdef SOCKMAP
299 err = bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
300#else
301 err = bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
302#endif
303 bpf_printk("sk_msg3: err %i\n", err);
304 return err;
305}
306
307SEC("sk_msg5")
308int bpf_prog8(struct sk_msg_md *msg)
309{
310 void *data_end = (void *)(long) msg->data_end;
311 void *data = (void *)(long) msg->data;
312 int ret = 0, *bytes, zero = 0;
313
314 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
315 if (bytes) {
316 ret = bpf_msg_apply_bytes(msg, *bytes);
317 if (ret)
318 return SK_DROP;
319 } else {
320 return SK_DROP;
321 }
322 return SK_PASS;
323}
324SEC("sk_msg6")
325int bpf_prog9(struct sk_msg_md *msg)
326{
327 void *data_end = (void *)(long) msg->data_end;
328 void *data = (void *)(long) msg->data;
329 int ret = 0, *bytes, zero = 0;
330
331 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
332 if (bytes) {
333 if (((__u64)data_end - (__u64)data) >= *bytes)
334 return SK_PASS;
335 ret = bpf_msg_cork_bytes(msg, *bytes);
336 if (ret)
337 return SK_DROP;
338 }
339 return SK_PASS;
340}
341
342SEC("sk_msg7")
343int bpf_prog10(struct sk_msg_md *msg)
344{
345 int *bytes, zero = 0, one = 1;
346 int *start, *end;
347
348 bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
349 if (bytes)
350 bpf_msg_apply_bytes(msg, *bytes);
351 bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
352 if (bytes)
353 bpf_msg_cork_bytes(msg, *bytes);
354 start = bpf_map_lookup_elem(&sock_pull_bytes, &zero);
355 end = bpf_map_lookup_elem(&sock_pull_bytes, &one);
356 if (start && end)
357 bpf_msg_pull_data(msg, *start, *end, 0);
358
359 return SK_DROP;
360}
361
362int _version SEC("version") = 1;
363char _license[] SEC("license") = "GPL";
364