1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2016 VMware
3  * Copyright (c) 2016 Facebook
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public
7  * License as published by the Free Software Foundation.
8  */
9 #include <stddef.h>
10 #include <string.h>
11 #include <arpa/inet.h>
12 #include <linux/bpf.h>
13 #include <linux/if_ether.h>
14 #include <linux/if_packet.h>
15 #include <linux/ip.h>
16 #include <linux/ipv6.h>
17 #include <linux/types.h>
18 #include <linux/socket.h>
19 #include <linux/pkt_cls.h>
20 #include <linux/erspan.h>
21 #include <bpf/bpf_helpers.h>
22 #include <bpf/bpf_endian.h>
23 
24 #define ERROR(ret) do {\
25 		char fmt[] = "ERROR line:%d ret:%d\n";\
26 		bpf_trace_printk(fmt, sizeof(fmt), __LINE__, ret); \
27 	} while (0)
28 
29 struct geneve_opt {
30 	__be16	opt_class;
31 	__u8	type;
32 	__u8	length:5;
33 	__u8	r3:1;
34 	__u8	r2:1;
35 	__u8	r1:1;
36 	__u8	opt_data[8]; /* hard-coded to 8 byte */
37 };
38 
39 struct vxlan_metadata {
40 	__u32     gbp;
41 };
42 
43 struct {
44 	__uint(type, BPF_MAP_TYPE_ARRAY);
45 	__uint(max_entries, 1);
46 	__type(key, __u32);
47 	__type(value, __u32);
48 } local_ip_map SEC(".maps");
49 
50 
51 SEC("tc")
52 int gre_set_tunnel(struct __sk_buff *skb)
53 {
54 	int ret;
55 	struct bpf_tunnel_key key;
56 
57 	__builtin_memset(&key, 0x0, sizeof(key));
58 	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
59 	key.tunnel_id = 2;
60 	key.tunnel_tos = 0;
61 	key.tunnel_ttl = 64;
62 
63 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
64 				     BPF_F_ZERO_CSUM_TX | BPF_F_SEQ_NUMBER);
65 	if (ret < 0) {
66 		ERROR(ret);
67 		return TC_ACT_SHOT;
68 	}
69 
70 	return TC_ACT_OK;
71 }
72 
73 SEC("tc")
74 int gre_get_tunnel(struct __sk_buff *skb)
75 {
76 	int ret;
77 	struct bpf_tunnel_key key;
78 	char fmt[] = "key %d remote ip 0x%x\n";
79 
80 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
81 	if (ret < 0) {
82 		ERROR(ret);
83 		return TC_ACT_SHOT;
84 	}
85 
86 	bpf_trace_printk(fmt, sizeof(fmt), key.tunnel_id, key.remote_ipv4);
87 	return TC_ACT_OK;
88 }
89 
90 SEC("tc")
91 int ip6gretap_set_tunnel(struct __sk_buff *skb)
92 {
93 	struct bpf_tunnel_key key;
94 	int ret;
95 
96 	__builtin_memset(&key, 0x0, sizeof(key));
97 	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
98 	key.tunnel_id = 2;
99 	key.tunnel_tos = 0;
100 	key.tunnel_ttl = 64;
101 	key.tunnel_label = 0xabcde;
102 
103 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
104 				     BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX |
105 				     BPF_F_SEQ_NUMBER);
106 	if (ret < 0) {
107 		ERROR(ret);
108 		return TC_ACT_SHOT;
109 	}
110 
111 	return TC_ACT_OK;
112 }
113 
114 SEC("tc")
115 int ip6gretap_get_tunnel(struct __sk_buff *skb)
116 {
117 	char fmt[] = "key %d remote ip6 ::%x label %x\n";
118 	struct bpf_tunnel_key key;
119 	int ret;
120 
121 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
122 				     BPF_F_TUNINFO_IPV6);
123 	if (ret < 0) {
124 		ERROR(ret);
125 		return TC_ACT_SHOT;
126 	}
127 
128 	bpf_trace_printk(fmt, sizeof(fmt),
129 			 key.tunnel_id, key.remote_ipv6[3], key.tunnel_label);
130 
131 	return TC_ACT_OK;
132 }
133 
134 SEC("tc")
135 int erspan_set_tunnel(struct __sk_buff *skb)
136 {
137 	struct bpf_tunnel_key key;
138 	struct erspan_metadata md;
139 	int ret;
140 
141 	__builtin_memset(&key, 0x0, sizeof(key));
142 	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
143 	key.tunnel_id = 2;
144 	key.tunnel_tos = 0;
145 	key.tunnel_ttl = 64;
146 
147 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
148 				     BPF_F_ZERO_CSUM_TX);
149 	if (ret < 0) {
150 		ERROR(ret);
151 		return TC_ACT_SHOT;
152 	}
153 
154 	__builtin_memset(&md, 0, sizeof(md));
155 #ifdef ERSPAN_V1
156 	md.version = 1;
157 	md.u.index = bpf_htonl(123);
158 #else
159 	__u8 direction = 1;
160 	__u8 hwid = 7;
161 
162 	md.version = 2;
163 	md.u.md2.dir = direction;
164 	md.u.md2.hwid = hwid & 0xf;
165 	md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
166 #endif
167 
168 	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
169 	if (ret < 0) {
170 		ERROR(ret);
171 		return TC_ACT_SHOT;
172 	}
173 
174 	return TC_ACT_OK;
175 }
176 
177 SEC("tc")
178 int erspan_get_tunnel(struct __sk_buff *skb)
179 {
180 	char fmt[] = "key %d remote ip 0x%x erspan version %d\n";
181 	struct bpf_tunnel_key key;
182 	struct erspan_metadata md;
183 	__u32 index;
184 	int ret;
185 
186 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
187 	if (ret < 0) {
188 		ERROR(ret);
189 		return TC_ACT_SHOT;
190 	}
191 
192 	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
193 	if (ret < 0) {
194 		ERROR(ret);
195 		return TC_ACT_SHOT;
196 	}
197 
198 	bpf_trace_printk(fmt, sizeof(fmt),
199 			key.tunnel_id, key.remote_ipv4, md.version);
200 
201 #ifdef ERSPAN_V1
202 	char fmt2[] = "\tindex %x\n";
203 
204 	index = bpf_ntohl(md.u.index);
205 	bpf_trace_printk(fmt2, sizeof(fmt2), index);
206 #else
207 	char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
208 
209 	bpf_trace_printk(fmt2, sizeof(fmt2),
210 			 md.u.md2.dir,
211 			 (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
212 			 bpf_ntohl(md.u.md2.timestamp));
213 #endif
214 
215 	return TC_ACT_OK;
216 }
217 
218 SEC("tc")
219 int ip4ip6erspan_set_tunnel(struct __sk_buff *skb)
220 {
221 	struct bpf_tunnel_key key;
222 	struct erspan_metadata md;
223 	int ret;
224 
225 	__builtin_memset(&key, 0x0, sizeof(key));
226 	key.remote_ipv6[3] = bpf_htonl(0x11);
227 	key.tunnel_id = 2;
228 	key.tunnel_tos = 0;
229 	key.tunnel_ttl = 64;
230 
231 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
232 				     BPF_F_TUNINFO_IPV6);
233 	if (ret < 0) {
234 		ERROR(ret);
235 		return TC_ACT_SHOT;
236 	}
237 
238 	__builtin_memset(&md, 0, sizeof(md));
239 
240 #ifdef ERSPAN_V1
241 	md.u.index = bpf_htonl(123);
242 	md.version = 1;
243 #else
244 	__u8 direction = 0;
245 	__u8 hwid = 17;
246 
247 	md.version = 2;
248 	md.u.md2.dir = direction;
249 	md.u.md2.hwid = hwid & 0xf;
250 	md.u.md2.hwid_upper = (hwid >> 4) & 0x3;
251 #endif
252 
253 	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
254 	if (ret < 0) {
255 		ERROR(ret);
256 		return TC_ACT_SHOT;
257 	}
258 
259 	return TC_ACT_OK;
260 }
261 
262 SEC("tc")
263 int ip4ip6erspan_get_tunnel(struct __sk_buff *skb)
264 {
265 	char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n";
266 	struct bpf_tunnel_key key;
267 	struct erspan_metadata md;
268 	__u32 index;
269 	int ret;
270 
271 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
272 				     BPF_F_TUNINFO_IPV6);
273 	if (ret < 0) {
274 		ERROR(ret);
275 		return TC_ACT_SHOT;
276 	}
277 
278 	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
279 	if (ret < 0) {
280 		ERROR(ret);
281 		return TC_ACT_SHOT;
282 	}
283 
284 	bpf_trace_printk(fmt, sizeof(fmt),
285 			key.tunnel_id, key.remote_ipv4, md.version);
286 
287 #ifdef ERSPAN_V1
288 	char fmt2[] = "\tindex %x\n";
289 
290 	index = bpf_ntohl(md.u.index);
291 	bpf_trace_printk(fmt2, sizeof(fmt2), index);
292 #else
293 	char fmt2[] = "\tdirection %d hwid %x timestamp %u\n";
294 
295 	bpf_trace_printk(fmt2, sizeof(fmt2),
296 			 md.u.md2.dir,
297 			 (md.u.md2.hwid_upper << 4) + md.u.md2.hwid,
298 			 bpf_ntohl(md.u.md2.timestamp));
299 #endif
300 
301 	return TC_ACT_OK;
302 }
303 
304 SEC("tc")
305 int vxlan_set_tunnel_dst(struct __sk_buff *skb)
306 {
307 	int ret;
308 	struct bpf_tunnel_key key;
309 	struct vxlan_metadata md;
310 	__u32 index = 0;
311 	__u32 *local_ip = NULL;
312 
313 	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
314 	if (!local_ip) {
315 		log_err(ret);
316 		return TC_ACT_SHOT;
317 	}
318 
319 	__builtin_memset(&key, 0x0, sizeof(key));
320 	key.local_ipv4 = 0xac100164; /* 172.16.1.100 */
321 	key.remote_ipv4 = *local_ip;
322 	key.tunnel_id = 2;
323 	key.tunnel_tos = 0;
324 	key.tunnel_ttl = 64;
325 
326 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
327 				     BPF_F_ZERO_CSUM_TX);
328 	if (ret < 0) {
329 		log_err(ret);
330 		return TC_ACT_SHOT;
331 	}
332 
333 	md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
334 	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
335 	if (ret < 0) {
336 		log_err(ret);
337 		return TC_ACT_SHOT;
338 	}
339 
340 	return TC_ACT_OK;
341 }
342 
343 SEC("tc")
344 int vxlan_set_tunnel_src(struct __sk_buff *skb)
345 {
346 	int ret;
347 	struct bpf_tunnel_key key;
348 	struct vxlan_metadata md;
349 	__u32 index = 0;
350 	__u32 *local_ip = NULL;
351 
352 	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
353 	if (!local_ip) {
354 		ERROR(ret);
355 		return TC_ACT_SHOT;
356 	}
357 
358 	__builtin_memset(&key, 0x0, sizeof(key));
359 	key.local_ipv4 = *local_ip;
360 	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
361 	key.tunnel_id = 2;
362 	key.tunnel_tos = 0;
363 	key.tunnel_ttl = 64;
364 
365 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
366 				     BPF_F_ZERO_CSUM_TX);
367 	if (ret < 0) {
368 		ERROR(ret);
369 		return TC_ACT_SHOT;
370 	}
371 
372 	md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */
373 	ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md));
374 	if (ret < 0) {
375 		ERROR(ret);
376 		return TC_ACT_SHOT;
377 	}
378 
379 	return TC_ACT_OK;
380 }
381 
382 SEC("tc")
383 int vxlan_get_tunnel_src(struct __sk_buff *skb)
384 {
385 	int ret;
386 	struct bpf_tunnel_key key;
387 	struct vxlan_metadata md;
388 	char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n";
389 	char fmt2[] = "local ip 0x%x\n";
390 	__u32 index = 0;
391 	__u32 *local_ip = NULL;
392 
393 	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
394 	if (!local_ip) {
395 		ERROR(ret);
396 		return TC_ACT_SHOT;
397 	}
398 
399 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
400 	if (ret < 0) {
401 		ERROR(ret);
402 		return TC_ACT_SHOT;
403 	}
404 
405 	ret = bpf_skb_get_tunnel_opt(skb, &md, sizeof(md));
406 	if (ret < 0) {
407 		ERROR(ret);
408 		return TC_ACT_SHOT;
409 	}
410 
411 	if (key.local_ipv4 != *local_ip || md.gbp != 0x800FF) {
412 		bpf_printk("vxlan key %d local ip 0x%x remote ip 0x%x gbp 0x%x\n",
413 			   key.tunnel_id, key.local_ipv4,
414 			   key.remote_ipv4, md.gbp);
415 		bpf_printk("local_ip 0x%x\n", *local_ip);
416 		log_err(ret);
417 		return TC_ACT_SHOT;
418 	}
419 
420 	return TC_ACT_OK;
421 }
422 
423 SEC("tc")
424 int ip6vxlan_set_tunnel_dst(struct __sk_buff *skb)
425 {
426 	struct bpf_tunnel_key key;
427 	int ret;
428 	__u32 index = 0;
429 	__u32 *local_ip;
430 
431 	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
432 	if (!local_ip) {
433 		log_err(ret);
434 		return TC_ACT_SHOT;
435 	}
436 
437 	__builtin_memset(&key, 0x0, sizeof(key));
438 	key.local_ipv6[3] = bpf_htonl(0x11); /* ::11 */
439 	key.remote_ipv6[3] = bpf_htonl(*local_ip);
440 	key.tunnel_id = 22;
441 	key.tunnel_tos = 0;
442 	key.tunnel_ttl = 64;
443 
444 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
445 				     BPF_F_TUNINFO_IPV6);
446 	if (ret < 0) {
447 		log_err(ret);
448 		return TC_ACT_SHOT;
449 	}
450 
451 	return TC_ACT_OK;
452 }
453 
454 SEC("tc")
455 int ip6vxlan_set_tunnel_src(struct __sk_buff *skb)
456 {
457 	struct bpf_tunnel_key key;
458 	int ret;
459 	__u32 index = 0;
460 	__u32 *local_ip;
461 
462 	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
463 	if (!local_ip) {
464 		ERROR(ret);
465 		return TC_ACT_SHOT;
466 	}
467 
468 	__builtin_memset(&key, 0x0, sizeof(key));
469 	key.local_ipv6[3] = bpf_htonl(*local_ip);
470 	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
471 	key.tunnel_id = 22;
472 	key.tunnel_tos = 0;
473 	key.tunnel_ttl = 64;
474 
475 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
476 				     BPF_F_TUNINFO_IPV6);
477 	if (ret < 0) {
478 		ERROR(ret);
479 		return TC_ACT_SHOT;
480 	}
481 
482 	return TC_ACT_OK;
483 }
484 
485 SEC("tc")
486 int ip6vxlan_get_tunnel_src(struct __sk_buff *skb)
487 {
488 	char fmt[] = "key %d remote ip6 ::%x label %x\n";
489 	char fmt2[] = "local ip6 ::%x\n";
490 	struct bpf_tunnel_key key;
491 	int ret;
492 	__u32 index = 0;
493 	__u32 *local_ip;
494 
495 	local_ip = bpf_map_lookup_elem(&local_ip_map, &index);
496 	if (!local_ip) {
497 		ERROR(ret);
498 		return TC_ACT_SHOT;
499 	}
500 
501 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
502 				     BPF_F_TUNINFO_IPV6);
503 	if (ret < 0) {
504 		ERROR(ret);
505 		return TC_ACT_SHOT;
506 	}
507 
508 	if (bpf_ntohl(key.local_ipv6[3]) != *local_ip) {
509 		bpf_trace_printk(fmt, sizeof(fmt),
510 				 key.tunnel_id,
511 				 key.remote_ipv6[3], key.tunnel_label);
512 		bpf_trace_printk(fmt2, sizeof(fmt2), key.local_ipv6[3]);
513 		ERROR(ret);
514 		return TC_ACT_SHOT;
515 	}
516 
517 	return TC_ACT_OK;
518 }
519 
520 SEC("tc")
521 int geneve_set_tunnel(struct __sk_buff *skb)
522 {
523 	int ret;
524 	struct bpf_tunnel_key key;
525 	struct geneve_opt gopt;
526 
527 	__builtin_memset(&key, 0x0, sizeof(key));
528 	key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
529 	key.tunnel_id = 2;
530 	key.tunnel_tos = 0;
531 	key.tunnel_ttl = 64;
532 
533 	__builtin_memset(&gopt, 0x0, sizeof(gopt));
534 	gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
535 	gopt.type = 0x08;
536 	gopt.r1 = 0;
537 	gopt.r2 = 0;
538 	gopt.r3 = 0;
539 	gopt.length = 2; /* 4-byte multiple */
540 	*(int *) &gopt.opt_data = bpf_htonl(0xdeadbeef);
541 
542 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
543 				     BPF_F_ZERO_CSUM_TX);
544 	if (ret < 0) {
545 		ERROR(ret);
546 		return TC_ACT_SHOT;
547 	}
548 
549 	ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
550 	if (ret < 0) {
551 		ERROR(ret);
552 		return TC_ACT_SHOT;
553 	}
554 
555 	return TC_ACT_OK;
556 }
557 
558 SEC("tc")
559 int geneve_get_tunnel(struct __sk_buff *skb)
560 {
561 	int ret;
562 	struct bpf_tunnel_key key;
563 	struct geneve_opt gopt;
564 	char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
565 
566 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
567 	if (ret < 0) {
568 		ERROR(ret);
569 		return TC_ACT_SHOT;
570 	}
571 
572 	ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
573 	if (ret < 0)
574 		gopt.opt_class = 0;
575 
576 	bpf_trace_printk(fmt, sizeof(fmt),
577 			key.tunnel_id, key.remote_ipv4, gopt.opt_class);
578 	return TC_ACT_OK;
579 }
580 
581 SEC("tc")
582 int ip6geneve_set_tunnel(struct __sk_buff *skb)
583 {
584 	struct bpf_tunnel_key key;
585 	struct geneve_opt gopt;
586 	int ret;
587 
588 	__builtin_memset(&key, 0x0, sizeof(key));
589 	key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
590 	key.tunnel_id = 22;
591 	key.tunnel_tos = 0;
592 	key.tunnel_ttl = 64;
593 
594 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
595 				     BPF_F_TUNINFO_IPV6);
596 	if (ret < 0) {
597 		ERROR(ret);
598 		return TC_ACT_SHOT;
599 	}
600 
601 	__builtin_memset(&gopt, 0x0, sizeof(gopt));
602 	gopt.opt_class = bpf_htons(0x102); /* Open Virtual Networking (OVN) */
603 	gopt.type = 0x08;
604 	gopt.r1 = 0;
605 	gopt.r2 = 0;
606 	gopt.r3 = 0;
607 	gopt.length = 2; /* 4-byte multiple */
608 	*(int *) &gopt.opt_data = bpf_htonl(0xfeedbeef);
609 
610 	ret = bpf_skb_set_tunnel_opt(skb, &gopt, sizeof(gopt));
611 	if (ret < 0) {
612 		ERROR(ret);
613 		return TC_ACT_SHOT;
614 	}
615 
616 	return TC_ACT_OK;
617 }
618 
619 SEC("tc")
620 int ip6geneve_get_tunnel(struct __sk_buff *skb)
621 {
622 	char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n";
623 	struct bpf_tunnel_key key;
624 	struct geneve_opt gopt;
625 	int ret;
626 
627 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
628 				     BPF_F_TUNINFO_IPV6);
629 	if (ret < 0) {
630 		ERROR(ret);
631 		return TC_ACT_SHOT;
632 	}
633 
634 	ret = bpf_skb_get_tunnel_opt(skb, &gopt, sizeof(gopt));
635 	if (ret < 0)
636 		gopt.opt_class = 0;
637 
638 	bpf_trace_printk(fmt, sizeof(fmt),
639 			key.tunnel_id, key.remote_ipv4, gopt.opt_class);
640 
641 	return TC_ACT_OK;
642 }
643 
644 SEC("tc")
645 int ipip_set_tunnel(struct __sk_buff *skb)
646 {
647 	struct bpf_tunnel_key key = {};
648 	void *data = (void *)(long)skb->data;
649 	struct iphdr *iph = data;
650 	void *data_end = (void *)(long)skb->data_end;
651 	int ret;
652 
653 	/* single length check */
654 	if (data + sizeof(*iph) > data_end) {
655 		ERROR(1);
656 		return TC_ACT_SHOT;
657 	}
658 
659 	key.tunnel_ttl = 64;
660 	if (iph->protocol == IPPROTO_ICMP) {
661 		key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */
662 	}
663 
664 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0);
665 	if (ret < 0) {
666 		ERROR(ret);
667 		return TC_ACT_SHOT;
668 	}
669 
670 	return TC_ACT_OK;
671 }
672 
673 SEC("tc")
674 int ipip_get_tunnel(struct __sk_buff *skb)
675 {
676 	int ret;
677 	struct bpf_tunnel_key key;
678 	char fmt[] = "remote ip 0x%x\n";
679 
680 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0);
681 	if (ret < 0) {
682 		ERROR(ret);
683 		return TC_ACT_SHOT;
684 	}
685 
686 	bpf_trace_printk(fmt, sizeof(fmt), key.remote_ipv4);
687 	return TC_ACT_OK;
688 }
689 
690 SEC("tc")
691 int ipip6_set_tunnel(struct __sk_buff *skb)
692 {
693 	struct bpf_tunnel_key key = {};
694 	void *data = (void *)(long)skb->data;
695 	struct iphdr *iph = data;
696 	void *data_end = (void *)(long)skb->data_end;
697 	int ret;
698 
699 	/* single length check */
700 	if (data + sizeof(*iph) > data_end) {
701 		ERROR(1);
702 		return TC_ACT_SHOT;
703 	}
704 
705 	__builtin_memset(&key, 0x0, sizeof(key));
706 	key.tunnel_ttl = 64;
707 	if (iph->protocol == IPPROTO_ICMP) {
708 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
709 	}
710 
711 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
712 				     BPF_F_TUNINFO_IPV6);
713 	if (ret < 0) {
714 		ERROR(ret);
715 		return TC_ACT_SHOT;
716 	}
717 
718 	return TC_ACT_OK;
719 }
720 
721 SEC("tc")
722 int ipip6_get_tunnel(struct __sk_buff *skb)
723 {
724 	int ret;
725 	struct bpf_tunnel_key key;
726 	char fmt[] = "remote ip6 %x::%x\n";
727 
728 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
729 				     BPF_F_TUNINFO_IPV6);
730 	if (ret < 0) {
731 		ERROR(ret);
732 		return TC_ACT_SHOT;
733 	}
734 
735 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
736 			 bpf_htonl(key.remote_ipv6[3]));
737 	return TC_ACT_OK;
738 }
739 
740 SEC("tc")
741 int ip6ip6_set_tunnel(struct __sk_buff *skb)
742 {
743 	struct bpf_tunnel_key key = {};
744 	void *data = (void *)(long)skb->data;
745 	struct ipv6hdr *iph = data;
746 	void *data_end = (void *)(long)skb->data_end;
747 	int ret;
748 
749 	/* single length check */
750 	if (data + sizeof(*iph) > data_end) {
751 		ERROR(1);
752 		return TC_ACT_SHOT;
753 	}
754 
755 	key.tunnel_ttl = 64;
756 	if (iph->nexthdr == 58 /* NEXTHDR_ICMP */) {
757 		key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */
758 	}
759 
760 	ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key),
761 				     BPF_F_TUNINFO_IPV6);
762 	if (ret < 0) {
763 		ERROR(ret);
764 		return TC_ACT_SHOT;
765 	}
766 
767 	return TC_ACT_OK;
768 }
769 
770 SEC("tc")
771 int ip6ip6_get_tunnel(struct __sk_buff *skb)
772 {
773 	int ret;
774 	struct bpf_tunnel_key key;
775 	char fmt[] = "remote ip6 %x::%x\n";
776 
777 	ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key),
778 				     BPF_F_TUNINFO_IPV6);
779 	if (ret < 0) {
780 		ERROR(ret);
781 		return TC_ACT_SHOT;
782 	}
783 
784 	bpf_trace_printk(fmt, sizeof(fmt), bpf_htonl(key.remote_ipv6[0]),
785 			 bpf_htonl(key.remote_ipv6[3]));
786 	return TC_ACT_OK;
787 }
788 
789 SEC("tc")
790 int xfrm_get_state(struct __sk_buff *skb)
791 {
792 	struct bpf_xfrm_state x;
793 	char fmt[] = "reqid %d spi 0x%x remote ip 0x%x\n";
794 	int ret;
795 
796 	ret = bpf_skb_get_xfrm_state(skb, 0, &x, sizeof(x), 0);
797 	if (ret < 0)
798 		return TC_ACT_OK;
799 
800 	bpf_trace_printk(fmt, sizeof(fmt), x.reqid, bpf_ntohl(x.spi),
801 			 bpf_ntohl(x.remote_ipv4));
802 	return TC_ACT_OK;
803 }
804 
805 char _license[] SEC("license") = "GPL";
806