I'm using https://elixir.bootlin.com/linux/v4.9.137/source/samples/bpf/sockex3_kern.c this example, but instead of the RAW socket, I'm using ordinary AF_INET6/SOCK_STREAM and BPF_PROG_TYPE_SOCKET_FILTER.
I can't understand why load_half is used to read proto. First 32 bits is the length field:
SEC("socket/0")
int bpf_prog(struct __sk_buff *skb)
{
__u32 proto = load_half(skb, 12);
char fmt[] = "PROTO %x\n";
bpf_trace_printk(fmt, sizeof(fmt), proto);
}
Or if I try to do this:
SEC("socket/0")
int bpf_prog(struct __sk_buff *skb)
{
u64 proto = load_half(skb, 12);
char fmt[] = "PROTO %x %u\n";
void *data = (void *)(long)skb->data;
struct ethhdr *eth = data;
void *data_end = (void *)(long)skb->data_end;
...
}
I got "invalid bpf_context access off=80 size=4" error. As I understand I should read all the data from "data" field here.
So, maybe someone can tell me where the first 34 bytes(eth + ip header) was trimmed for current sk_buff? Somewhere in tcp_v4_rcv?
Is it possible to access IP header fields with SOCK_STREAM socket?
UPD: Looks like there is no way to directly access data from the filter:
https://elixir.bootlin.com/linux/v4.9.137/source/net/core/filter.c#L2647
switch (off) {
case offsetof(struct __sk_buff, tc_classid):
case offsetof(struct __sk_buff, data):
case offsetof(struct __sk_buff, data_end):
return false;
}