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/bpf_helpers.h>
16 #include <bpf/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 struct {
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");
37 
38 struct {
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");
44 
45 struct {
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");
51 
52 struct {
53 	__uint(type, BPF_MAP_TYPE_ARRAY);
54 	__uint(max_entries, 1);
55 	__type(key, int);
56 	__type(value, int);
57 } sock_apply_bytes SEC(".maps");
58 
59 struct {
60 	__uint(type, BPF_MAP_TYPE_ARRAY);
61 	__uint(max_entries, 1);
62 	__type(key, int);
63 	__type(value, int);
64 } sock_cork_bytes SEC(".maps");
65 
66 struct {
67 	__uint(type, BPF_MAP_TYPE_ARRAY);
68 	__uint(max_entries, 6);
69 	__type(key, int);
70 	__type(value, int);
71 } sock_bytes SEC(".maps");
72 
73 struct {
74 	__uint(type, BPF_MAP_TYPE_ARRAY);
75 	__uint(max_entries, 1);
76 	__type(key, int);
77 	__type(value, int);
78 } sock_redir_flags SEC(".maps");
79 
80 struct {
81 	__uint(type, BPF_MAP_TYPE_ARRAY);
82 	__uint(max_entries, 3);
83 	__type(key, int);
84 	__type(value, int);
85 } sock_skb_opts SEC(".maps");
86 
87 struct {
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");
93 
94 SEC("sk_skb1")
95 int bpf_prog1(struct __sk_buff *skb)
96 {
97 	int *f, two = 2;
98 
99 	f = bpf_map_lookup_elem(&sock_skb_opts, &two);
100 	if (f && *f) {
101 		return *f;
102 	}
103 	return skb->len;
104 }
105 
106 SEC("sk_skb2")
107 int bpf_prog2(struct __sk_buff *skb)
108 {
109 	__u32 lport = skb->local_port;
110 	__u32 rport = skb->remote_port;
111 	int len, *f, ret, zero = 0;
112 	__u64 flags = 0;
113 
114 	if (lport == 10000)
115 		ret = 10;
116 	else
117 		ret = 1;
118 
119 	len = (__u32)skb->data_end - (__u32)skb->data;
120 	f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
121 	if (f && *f) {
122 		ret = 3;
123 		flags = *f;
124 	}
125 
126 #ifdef SOCKMAP
127 	return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
128 #else
129 	return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);
130 #endif
131 
132 }
133 
134 SEC("sk_skb3")
135 int bpf_prog3(struct __sk_buff *skb)
136 {
137 	const int one = 1;
138 	int err, *f, ret = SK_PASS;
139 	void *data_end;
140 	char *c;
141 
142 	err = bpf_skb_pull_data(skb, 19);
143 	if (err)
144 		goto tls_out;
145 
146 	c = (char *)(long)skb->data;
147 	data_end = (void *)(long)skb->data_end;
148 
149 	if (c + 18 < data_end)
150 		memcpy(&c[13], "PASS", 4);
151 	f = bpf_map_lookup_elem(&sock_skb_opts, &one);
152 	if (f && *f) {
153 		__u64 flags = 0;
154 
155 		ret = 0;
156 		flags = *f;
157 #ifdef SOCKMAP
158 		return bpf_sk_redirect_map(skb, &tls_sock_map, ret, flags);
159 #else
160 		return bpf_sk_redirect_hash(skb, &tls_sock_map, &ret, flags);
161 #endif
162 	}
163 
164 	f = bpf_map_lookup_elem(&sock_skb_opts, &one);
165 	if (f && *f)
166 		ret = SK_DROP;
167 tls_out:
168 	return ret;
169 }
170 
171 SEC("sockops")
172 int bpf_sockmap(struct bpf_sock_ops *skops)
173 {
174 	__u32 lport, rport;
175 	int op, err = 0, index, key, ret;
176 
177 
178 	op = (int) skops->op;
179 
180 	switch (op) {
181 	case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
182 		lport = skops->local_port;
183 		rport = skops->remote_port;
184 
185 		if (lport == 10000) {
186 			ret = 1;
187 #ifdef SOCKMAP
188 			err = bpf_sock_map_update(skops, &sock_map, &ret,
189 						  BPF_NOEXIST);
190 #else
191 			err = bpf_sock_hash_update(skops, &sock_map, &ret,
192 						   BPF_NOEXIST);
193 #endif
194 		}
195 		break;
196 	case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
197 		lport = skops->local_port;
198 		rport = skops->remote_port;
199 
200 		if (bpf_ntohl(rport) == 10001) {
201 			ret = 10;
202 #ifdef SOCKMAP
203 			err = bpf_sock_map_update(skops, &sock_map, &ret,
204 						  BPF_NOEXIST);
205 #else
206 			err = bpf_sock_hash_update(skops, &sock_map, &ret,
207 						   BPF_NOEXIST);
208 #endif
209 		}
210 		break;
211 	default:
212 		break;
213 	}
214 
215 	return 0;
216 }
217 
218 SEC("sk_msg1")
219 int bpf_prog4(struct sk_msg_md *msg)
220 {
221 	int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
222 	int *start, *end, *start_push, *end_push, *start_pop, *pop;
223 
224 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
225 	if (bytes)
226 		bpf_msg_apply_bytes(msg, *bytes);
227 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
228 	if (bytes)
229 		bpf_msg_cork_bytes(msg, *bytes);
230 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
231 	end = bpf_map_lookup_elem(&sock_bytes, &one);
232 	if (start && end)
233 		bpf_msg_pull_data(msg, *start, *end, 0);
234 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
235 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
236 	if (start_push && end_push)
237 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
238 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
239 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
240 	if (start_pop && pop)
241 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
242 	return SK_PASS;
243 }
244 
245 SEC("sk_msg2")
246 int bpf_prog6(struct sk_msg_md *msg)
247 {
248 	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
249 	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
250 	__u64 flags = 0;
251 
252 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
253 	if (bytes)
254 		bpf_msg_apply_bytes(msg, *bytes);
255 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
256 	if (bytes)
257 		bpf_msg_cork_bytes(msg, *bytes);
258 
259 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
260 	end = bpf_map_lookup_elem(&sock_bytes, &one);
261 	if (start && end)
262 		bpf_msg_pull_data(msg, *start, *end, 0);
263 
264 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
265 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
266 	if (start_push && end_push)
267 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
268 
269 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
270 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
271 	if (start_pop && pop)
272 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
273 
274 	f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
275 	if (f && *f) {
276 		key = 2;
277 		flags = *f;
278 	}
279 #ifdef SOCKMAP
280 	return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
281 #else
282 	return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
283 #endif
284 }
285 
286 SEC("sk_msg3")
287 int bpf_prog8(struct sk_msg_md *msg)
288 {
289 	void *data_end = (void *)(long) msg->data_end;
290 	void *data = (void *)(long) msg->data;
291 	int ret = 0, *bytes, zero = 0;
292 
293 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
294 	if (bytes) {
295 		ret = bpf_msg_apply_bytes(msg, *bytes);
296 		if (ret)
297 			return SK_DROP;
298 	} else {
299 		return SK_DROP;
300 	}
301 	return SK_PASS;
302 }
303 SEC("sk_msg4")
304 int bpf_prog9(struct sk_msg_md *msg)
305 {
306 	void *data_end = (void *)(long) msg->data_end;
307 	void *data = (void *)(long) msg->data;
308 	int ret = 0, *bytes, zero = 0;
309 
310 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
311 	if (bytes) {
312 		if (((__u64)data_end - (__u64)data) >= *bytes)
313 			return SK_PASS;
314 		ret = bpf_msg_cork_bytes(msg, *bytes);
315 		if (ret)
316 			return SK_DROP;
317 	}
318 	return SK_PASS;
319 }
320 
321 SEC("sk_msg5")
322 int bpf_prog10(struct sk_msg_md *msg)
323 {
324 	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
325 	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
326 
327 	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
328 	if (bytes)
329 		bpf_msg_apply_bytes(msg, *bytes);
330 	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
331 	if (bytes)
332 		bpf_msg_cork_bytes(msg, *bytes);
333 	start = bpf_map_lookup_elem(&sock_bytes, &zero);
334 	end = bpf_map_lookup_elem(&sock_bytes, &one);
335 	if (start && end)
336 		bpf_msg_pull_data(msg, *start, *end, 0);
337 	start_push = bpf_map_lookup_elem(&sock_bytes, &two);
338 	end_push = bpf_map_lookup_elem(&sock_bytes, &three);
339 	if (start_push && end_push)
340 		bpf_msg_push_data(msg, *start_push, *end_push, 0);
341 	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
342 	pop = bpf_map_lookup_elem(&sock_bytes, &five);
343 	if (start_pop && pop)
344 		bpf_msg_pop_data(msg, *start_pop, *pop, 0);
345 	return SK_DROP;
346 }
347 
348 int _version SEC("version") = 1;
349 char _license[] SEC("license") = "GPL";
350