eBPF:将 UDP 负载和源 IP 打印为十六进制
eBPF: printing UDP payload and source IP as hex
我是 eBPF 的新手,想学习如何做一些基本的事情。我的问题是如何为我的 eBPF 代码编写 C 代码,以便以十六进制打印 (bpf_trace_printk
) 获取的数据包的 UPD 有效载荷。我试过没有运气。这是我当前的代码:
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;
}
特别注意最后一行的痕迹。你能帮我看看如何以十六进制格式打印 UDP 负载以及源 IP 吗?
谢谢。
我强烈建议在用户空间post进行这种处理; bpf_trace_printk
无论如何都不适用于生产环境(请参阅它在系统日志中留下的大警告)。使用 bpf_trace_printk
.
打印 UDP 有效负载也将是困难且低效的
到用户空间post-process,你可以依赖bpf_skb_output
,或者它在密件抄送中的更高级别的对应物,perf_submit_skb()
.这将允许您将数据包传递给用户空间,然后用户空间可以显示其 UDP 负载。
您可以在 bcc 存储库中找到 tutorial and an example。
您可以在 BPF 端做什么:
- 以 IP 地址格式打印
src_ip
相当容易。可以关注this Whosebug answer.
- 您无法打印完整的、可变长度的 UDP 负载,但您可以通过将前 N 个字节传递给
bpf_trace_printk
来打印它们,如下所示。
__u32 *data = payload;
bpf_trace_printk("payload= %x %x %x\n", *data, *(data+1), *(data+2));
我是 eBPF 的新手,想学习如何做一些基本的事情。我的问题是如何为我的 eBPF 代码编写 C 代码,以便以十六进制打印 (bpf_trace_printk
) 获取的数据包的 UPD 有效载荷。我试过没有运气。这是我当前的代码:
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;
}
特别注意最后一行的痕迹。你能帮我看看如何以十六进制格式打印 UDP 负载以及源 IP 吗?
谢谢。
我强烈建议在用户空间post进行这种处理; bpf_trace_printk
无论如何都不适用于生产环境(请参阅它在系统日志中留下的大警告)。使用 bpf_trace_printk
.
到用户空间post-process,你可以依赖bpf_skb_output
,或者它在密件抄送中的更高级别的对应物,perf_submit_skb()
.这将允许您将数据包传递给用户空间,然后用户空间可以显示其 UDP 负载。
您可以在 bcc 存储库中找到 tutorial and an example。
您可以在 BPF 端做什么:
- 以 IP 地址格式打印
src_ip
相当容易。可以关注this Whosebug answer. - 您无法打印完整的、可变长度的 UDP 负载,但您可以通过将前 N 个字节传递给
bpf_trace_printk
来打印它们,如下所示。
__u32 *data = payload;
bpf_trace_printk("payload= %x %x %x\n", *data, *(data+1), *(data+2));