1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
6 #include <linux/if_ether.h>
7 #include <linux/if_packet.h>
9 #include <linux/ipv6.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/bpf_helpers.h>
16 #include <bpf/bpf_endian.h>
18 /* Sockmap sample program connects a client and a backend together
21 * client:X <---> frontend:80 client:X <---> backend:80
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.
27 * The bpf_printk is verbose and prints information as connections
28 * are established and verdicts are decided.
32 __uint(type
, TEST_MAP_TYPE
);
33 __uint(max_entries
, 20);
34 __uint(key_size
, sizeof(int));
35 __uint(value_size
, sizeof(int));
36 } sock_map
SEC(".maps");
39 __uint(type
, TEST_MAP_TYPE
);
40 __uint(max_entries
, 20);
41 __uint(key_size
, sizeof(int));
42 __uint(value_size
, sizeof(int));
43 } sock_map_txmsg
SEC(".maps");
46 __uint(type
, TEST_MAP_TYPE
);
47 __uint(max_entries
, 20);
48 __uint(key_size
, sizeof(int));
49 __uint(value_size
, sizeof(int));
50 } sock_map_redir
SEC(".maps");
53 __uint(type
, BPF_MAP_TYPE_ARRAY
);
54 __uint(max_entries
, 1);
57 } sock_apply_bytes
SEC(".maps");
60 __uint(type
, BPF_MAP_TYPE_ARRAY
);
61 __uint(max_entries
, 1);
64 } sock_cork_bytes
SEC(".maps");
67 __uint(type
, BPF_MAP_TYPE_ARRAY
);
68 __uint(max_entries
, 6);
71 } sock_bytes
SEC(".maps");
74 __uint(type
, BPF_MAP_TYPE_ARRAY
);
75 __uint(max_entries
, 1);
78 } sock_redir_flags
SEC(".maps");
81 __uint(type
, BPF_MAP_TYPE_ARRAY
);
82 __uint(max_entries
, 3);
85 } sock_skb_opts
SEC(".maps");
88 __uint(type
, TEST_MAP_TYPE
);
89 __uint(max_entries
, 20);
90 __uint(key_size
, sizeof(int));
91 __uint(value_size
, sizeof(int));
92 } tls_sock_map
SEC(".maps");
95 int bpf_prog1(struct __sk_buff
*skb
)
99 f
= bpf_map_lookup_elem(&sock_skb_opts
, &two
);
107 int bpf_prog2(struct __sk_buff
*skb
)
109 __u32 lport
= skb
->local_port
;
110 __u32 rport
= skb
->remote_port
;
111 int len
, *f
, ret
, zero
= 0;
119 len
= (__u32
)skb
->data_end
- (__u32
)skb
->data
;
120 f
= bpf_map_lookup_elem(&sock_skb_opts
, &zero
);
127 return bpf_sk_redirect_map(skb
, &sock_map
, ret
, flags
);
129 return bpf_sk_redirect_hash(skb
, &sock_map
, &ret
, flags
);
134 static inline void bpf_write_pass(struct __sk_buff
*skb
, int offset
)
136 int err
= bpf_skb_pull_data(skb
, 6 + offset
);
143 c
= (char *)(long)skb
->data
;
144 data_end
= (void *)(long)skb
->data_end
;
146 if (c
+ 5 + offset
< data_end
)
147 memcpy(c
+ offset
, "PASS", 4);
151 int bpf_prog3(struct __sk_buff
*skb
)
153 int err
, *f
, ret
= SK_PASS
;
156 f
= bpf_map_lookup_elem(&sock_skb_opts
, &one
);
163 err
= bpf_skb_adjust_room(skb
, -13, 0, 0);
166 err
= bpf_skb_adjust_room(skb
, 4, 0, 0);
169 bpf_write_pass(skb
, 0);
171 return bpf_sk_redirect_map(skb
, &tls_sock_map
, ret
, flags
);
173 return bpf_sk_redirect_hash(skb
, &tls_sock_map
, &ret
, flags
);
176 f
= bpf_map_lookup_elem(&sock_skb_opts
, &one
);
179 err
= bpf_skb_adjust_room(skb
, 4, 0, 0);
182 bpf_write_pass(skb
, 13);
188 int bpf_sockmap(struct bpf_sock_ops
*skops
)
191 int op
, err
= 0, index
, key
, ret
;
194 op
= (int) skops
->op
;
197 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB
:
198 lport
= skops
->local_port
;
199 rport
= skops
->remote_port
;
201 if (lport
== 10000) {
204 err
= bpf_sock_map_update(skops
, &sock_map
, &ret
,
207 err
= bpf_sock_hash_update(skops
, &sock_map
, &ret
,
212 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB
:
213 lport
= skops
->local_port
;
214 rport
= skops
->remote_port
;
216 if (bpf_ntohl(rport
) == 10001) {
219 err
= bpf_sock_map_update(skops
, &sock_map
, &ret
,
222 err
= bpf_sock_hash_update(skops
, &sock_map
, &ret
,
235 int bpf_prog4(struct sk_msg_md
*msg
)
237 int *bytes
, zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5;
238 int *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
;
240 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
242 bpf_msg_apply_bytes(msg
, *bytes
);
243 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
245 bpf_msg_cork_bytes(msg
, *bytes
);
246 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
247 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
249 bpf_msg_pull_data(msg
, *start
, *end
, 0);
250 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
251 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
252 if (start_push
&& end_push
)
253 bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
254 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
255 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
256 if (start_pop
&& pop
)
257 bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
262 int bpf_prog6(struct sk_msg_md
*msg
)
264 int zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5, key
= 0;
265 int *bytes
, *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
, *f
;
268 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
270 bpf_msg_apply_bytes(msg
, *bytes
);
271 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
273 bpf_msg_cork_bytes(msg
, *bytes
);
275 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
276 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
278 bpf_msg_pull_data(msg
, *start
, *end
, 0);
280 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
281 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
282 if (start_push
&& end_push
)
283 bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
285 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
286 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
287 if (start_pop
&& pop
)
288 bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
290 f
= bpf_map_lookup_elem(&sock_redir_flags
, &zero
);
296 return bpf_msg_redirect_map(msg
, &sock_map_redir
, key
, flags
);
298 return bpf_msg_redirect_hash(msg
, &sock_map_redir
, &key
, flags
);
303 int bpf_prog8(struct sk_msg_md
*msg
)
305 void *data_end
= (void *)(long) msg
->data_end
;
306 void *data
= (void *)(long) msg
->data
;
307 int ret
= 0, *bytes
, zero
= 0;
309 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
311 ret
= bpf_msg_apply_bytes(msg
, *bytes
);
320 int bpf_prog9(struct sk_msg_md
*msg
)
322 void *data_end
= (void *)(long) msg
->data_end
;
323 void *data
= (void *)(long) msg
->data
;
324 int ret
= 0, *bytes
, zero
= 0;
326 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
328 if (((__u64
)data_end
- (__u64
)data
) >= *bytes
)
330 ret
= bpf_msg_cork_bytes(msg
, *bytes
);
338 int bpf_prog10(struct sk_msg_md
*msg
)
340 int *bytes
, *start
, *end
, *start_push
, *end_push
, *start_pop
, *pop
;
341 int zero
= 0, one
= 1, two
= 2, three
= 3, four
= 4, five
= 5;
343 bytes
= bpf_map_lookup_elem(&sock_apply_bytes
, &zero
);
345 bpf_msg_apply_bytes(msg
, *bytes
);
346 bytes
= bpf_map_lookup_elem(&sock_cork_bytes
, &zero
);
348 bpf_msg_cork_bytes(msg
, *bytes
);
349 start
= bpf_map_lookup_elem(&sock_bytes
, &zero
);
350 end
= bpf_map_lookup_elem(&sock_bytes
, &one
);
352 bpf_msg_pull_data(msg
, *start
, *end
, 0);
353 start_push
= bpf_map_lookup_elem(&sock_bytes
, &two
);
354 end_push
= bpf_map_lookup_elem(&sock_bytes
, &three
);
355 if (start_push
&& end_push
)
356 bpf_msg_push_data(msg
, *start_push
, *end_push
, 0);
357 start_pop
= bpf_map_lookup_elem(&sock_bytes
, &four
);
358 pop
= bpf_map_lookup_elem(&sock_bytes
, &five
);
359 if (start_pop
&& pop
)
360 bpf_msg_pop_data(msg
, *start_pop
, *pop
, 0);
364 int _version
SEC("version") = 1;
365 char _license
[] SEC("license") = "GPL";