Reputation: 73
I am new in eBPF and want to learn how to do a few basic things. My question is how to write in the C code for my eBPF code in order to print (bpf_trace_printk
) the UPD payload of an obtained packet in HEX. I have tried with no luck. Here is my current code:
int udppingpong(struct __sk_buff *skb)
{
void *data = (void *)(long)skb->data;
void *data_end = (void *)(long)skb->data_end;
struct ethhdr *eth = data;
struct iphdr *ip;
struct udphdr *udpdata;
if ((void *)eth + sizeof(*eth) > data_end) {
return TC_ACT_UNSPEC;
}
ip = data + sizeof(*eth);
if ((void *)ip + sizeof(*ip) > data_end) {
return TC_ACT_UNSPEC;
}
udpdata = (void *)ip + sizeof(*ip);
if ((void *)udpdata + sizeof(*udpdata) > data_end) {
return TC_ACT_UNSPEC;
}
if (eth->h_proto != htons(ETH_P_IP)) {
return TC_ACT_UNSPEC;
}
if (ip->protocol != IPPROTO_UDP) {
return TC_ACT_UNSPEC;
}
unsigned int payload_size;
unsigned char *payload;
payload_size = ntohs(udpdata->len) - sizeof(*udpdata);
payload = (unsigned char *)udpdata + sizeof(*udpdata);
if ((void *)payload + payload_size > data_end) {
return TC_ACT_UNSPEC;
}
__be16 port = udpdata->dest;
__be16 portToFilter = htons(7878);
if (port != portToFilter) {
return TC_ACT_OK;
}
__u32 src_ip = ip->saddr;
bpf_trace_printk("proto= %d, src= %lu\n", ip->protocol, src_ip); // --> This shows in decimal and network format (reversed), how to show actual IP like 1.2.3.4?
bpf_trace_printk("payload= %02x\n", payload); // --> HOW? I need it in hex to compare what is received
return TC_ACT_OK;
}
Special attention to the final lines with the traces. Could you help me on how to print the UDP payload in hex format as well as the source IP?
Thanks.
Upvotes: 2
Views: 2688
Reputation: 13133
I would strongly recommend doing this sort of post processing in userspace; bpf_trace_printk
isn't meant for production environment anyway (see the large warnings it leaves in syslogs). It will also be difficult and inefficient to print the UDP payload with bpf_trace_printk
.
To post-process in userspace, you can rely on bpf_skb_output
, or its higher-level counterpart in bcc, perf_submit_skb()
. That will allow you to pass the packet to userspace, which can then display its UDP payload.
You can find a tutorial and an example on the bcc repository.
What you can do on the BPF side:
src_ip
in the IP address format is fairly easy. You can follow this StackOverflow answer.bpf_trace_printk
as follows.__u32 *data = payload;
bpf_trace_printk("payload= %x %x %x\n", *data, *(data+1), *(data+2));
Upvotes: 3