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