1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Isovalent */
#include <stdbool.h>

#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/stddef.h>
#include <linux/if_packet.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>

char LICENSE[] SEC("license") = "GPL";

bool seen_tc1;
bool seen_tc2;
bool seen_tc3;
bool seen_tc4;
bool seen_tc5;
bool seen_tc6;
bool seen_tc7;
bool seen_tc8;

bool set_type;

bool seen_eth;
bool seen_host;
bool seen_mcast;

int mark, prio;
unsigned short headroom, tailroom;

SEC("tc/ingress")
int tc1(struct __sk_buff *skb)
{
	struct ethhdr eth = {};

	if (skb->protocol != __bpf_constant_htons(ETH_P_IP))
		goto out;
	if (bpf_skb_load_bytes(skb, 0, &eth, sizeof(eth)))
		goto out;
	seen_eth = eth.h_proto == bpf_htons(ETH_P_IP);
	seen_host = skb->pkt_type == PACKET_HOST;
	if (seen_host && set_type) {
		eth.h_dest[0] = 4;
		if (bpf_skb_store_bytes(skb, 0, &eth, sizeof(eth), 0))
			goto fail;
		bpf_skb_change_type(skb, PACKET_MULTICAST);
	}
out:
	seen_tc1 = true;
fail:
	return TCX_NEXT;
}

SEC("tc/egress")
int tc2(struct __sk_buff *skb)
{
	seen_tc2 = true;
	return TCX_NEXT;
}

SEC("tc/egress")
int tc3(struct __sk_buff *skb)
{
	seen_tc3 = true;
	return TCX_NEXT;
}

SEC("tc/egress")
int tc4(struct __sk_buff *skb)
{
	seen_tc4 = true;
	return TCX_NEXT;
}

SEC("tc/egress")
int tc5(struct __sk_buff *skb)
{
	seen_tc5 = true;
	return TCX_PASS;
}

SEC("tc/egress")
int tc6(struct __sk_buff *skb)
{
	seen_tc6 = true;
	return TCX_PASS;
}

SEC("tc/ingress")
int tc7(struct __sk_buff *skb)
{
	struct ethhdr eth = {};

	if (skb->protocol != __bpf_constant_htons(ETH_P_IP))
		goto out;
	if (bpf_skb_load_bytes(skb, 0, &eth, sizeof(eth)))
		goto out;
	if (eth.h_dest[0] == 4 && set_type) {
		seen_mcast = skb->pkt_type == PACKET_MULTICAST;
		bpf_skb_change_type(skb, PACKET_HOST);
	}
out:
	seen_tc7 = true;
	return TCX_PASS;
}

struct sk_buff {
	struct net_device *dev;
};

struct net_device {
	unsigned short needed_headroom;
	unsigned short needed_tailroom;
};

SEC("tc/egress")
int tc8(struct __sk_buff *skb)
{
	struct net_device *dev = BPF_CORE_READ((struct sk_buff *)skb, dev);

	seen_tc8 = true;
	mark = skb->mark;
	prio = skb->priority;
	headroom = BPF_CORE_READ(dev, needed_headroom);
	tailroom = BPF_CORE_READ(dev, needed_tailroom);
	return TCX_PASS;
}
我等夜監聽你說多愛我