__attribute__((always_inline))
static
bool
skb_revalidate_data(struct __sk_buff
*
skb, uint8_t
*
*
head, uint8_t
*
*
tail, const u32 offset)
{
if
(
*
head
+
offset >
*
tail) {
if
(bpf_skb_pull_data(skb, offset) <
0
) {
return
false;
}
*
head
=
(uint8_t
*
) (
long
) skb
-
>data;
*
tail
=
(uint8_t
*
) (
long
) skb
-
>data_end;
if
(
*
head
+
offset >
*
tail) {
return
false;
}
}
return
true;
}
__attribute__((always_inline))
static
int
parse_packet_tc(struct __sk_buff
*
skb,
bool
ingress)
{
if
(!skb || (NULL
=
=
skb))
return
0
;
/
/
packet pre check
uint8_t
*
packet_start
=
(uint8_t
*
)(
long
)skb
-
>data;
uint8_t
*
packet_end
=
(uint8_t
*
)(
long
)skb
-
>data_end;
if
(packet_start
+
sizeof(struct ethhdr) > packet_end)
return
TC_ACT_UNSPEC;
struct ethhdr
*
eth
=
(struct ethhdr
*
)packet_start;
if
(!eth || (NULL
=
=
eth))
return
TC_ACT_UNSPEC;
/
/
get ip hdr packet
uint32_t hdr_off_len
=
0
;
struct network_ctx net_ctx
=
{
0
, };
const
int
type
=
bpf_ntohs(eth
-
>h_proto);
if
(
type
=
=
ETH_P_IP) {
hdr_off_len
=
sizeof(struct ethhdr)
+
sizeof(struct iphdr);
if
(!skb_revalidate_data(skb, &packet_start, &packet_end, hdr_off_len))
return
TC_ACT_UNSPEC;
struct iphdr
*
ip
=
(void
*
)packet_start
+
sizeof(struct ethhdr);
if
(!ip || (NULL
=
=
ip))
return
TC_ACT_UNSPEC;
net_ctx.local_address
=
ip
-
>saddr;
net_ctx.remote_address
=
ip
-
>daddr;
net_ctx.protocol
=
ip
-
>protocol;
}
else
if
(
type
=
=
ETH_P_IPV6) {
hdr_off_len
=
sizeof(struct ethhdr)
+
sizeof(struct ipv6hdr);
if
(!skb_revalidate_data(skb, &packet_start, &packet_end, hdr_off_len))
return
TC_ACT_UNSPEC;
struct ipv6hdr
*
ip6
=
(void
*
)packet_start
+
sizeof(struct ethhdr);
if
(!ip6 || (NULL
=
=
ip6))
return
TC_ACT_UNSPEC;
net_ctx.local_address_v6
=
ip6
-
>saddr;
net_ctx.remote_address_v6
=
ip6
-
>daddr;
net_ctx.protocol
=
ip6
-
>nexthdr;
}
else
return
TC_ACT_UNSPEC;
/
/
get network hdr packet
if
(IPPROTO_TCP
=
=
net_ctx.protocol) {
if
(!skb_revalidate_data(skb, &packet_start, &packet_end, hdr_off_len
+
sizeof(struct tcphdr)))
return
TC_ACT_UNSPEC;
struct tcphdr
*
tcp
=
(void
*
)packet_start
+
hdr_off_len;
if
(!tcp || (NULL
=
=
tcp))
return
TC_ACT_UNSPEC;
net_ctx.local_port
=
tcp
-
>source;
net_ctx.remote_port
=
tcp
-
>dest;
}
else
if
(IPPROTO_UDP
=
=
net_ctx.protocol) {
if
(!skb_revalidate_data(skb, &packet_start, &packet_end, hdr_off_len
+
sizeof(struct udphdr)))
return
TC_ACT_UNSPEC;
struct udphdr
*
udp
=
(void
*
)packet_start
+
hdr_off_len;
if
(!udp || (NULL
=
=
udp))
return
TC_ACT_UNSPEC;
net_ctx.local_port
=
udp
-
>source;
net_ctx.remote_port
=
udp
-
>dest;
}
else
return
TC_ACT_UNSPEC;
net_ctx.pid
=
0
;
net_ctx.ingress
=
ingress;
net_ctx.packet_size
=
skb
-
>
len
;
net_ctx.ifindex
=
skb
-
>ifindex;
net_ctx.timestamp
=
bpf_ktime_get_ns();
const size_t pkt_size
=
sizeof(net_ctx);
bpf_perf_event_output(skb, &eventMap, BPF_F_CURRENT_CPU, &net_ctx, pkt_size);
if
(
type
=
=
ETH_P_IP) {
const char fmt_str[]
=
"[eBPF tc] %s"
;
const char fmt_str_local[]
=
" local: %u:%d\t"
;
const char fmt_str_remote[]
=
"remote: %u:%d\n"
;
if
(IPPROTO_UDP
=
=
net_ctx.protocol) {
const char chproto[]
=
"UDP"
;
bpf_trace_printk(fmt_str, sizeof(fmt_str), chproto);
}
else
if
(IPPROTO_TCP
=
=
net_ctx.protocol){
const char chproto[]
=
"TCP"
;
bpf_trace_printk(fmt_str, sizeof(fmt_str), chproto);
}
else
{
const char chproto[]
=
"Unknown"
;
bpf_trace_printk(fmt_str, sizeof(fmt_str), chproto);
}
bpf_trace_printk(fmt_str_local, sizeof(fmt_str_local), net_ctx.local_address, net_ctx.local_port);
bpf_trace_printk(fmt_str_remote, sizeof(fmt_str_remote), net_ctx.remote_address, net_ctx.remote_port);
}
return
TC_ACT_UNSPEC;
};