环境:ubuntu22,libbpf-bootstrap
背景: 使用libbpf抓取tcp报文的源目IP地址,用kprobe插桩到tcp_v4_connect
#include "vmlinux.h"
#include
#include
#include
char LICENSE[] SEC("license") = "Dual BSD/GPL";
SEC("kprobe/tcp_v4_connect")
int BPF_KPROBE(tcp_v4_connect, struct sock *sk)
{
pid_t pid;
__be32 saddr;
pid = bpf_get_current_pid_tgid() >> 32;
saddr = BPF_CORE_READ(sk, __sk_common.skc_rcv_saddr);
bpf_printk("KPROBE ENTRY pid = %d, ip = %x \n", pid, saddr);
return 0;
}
SEC("kretprobe/tcp_v4_connect")
int BPF_KRETPROBE(tcp_v4_connect_exit, long ret)
{
pid_t pid;
pid = bpf_get_current_pid_tgid() >> 32;
bpf_printk("KPROBE EXIT: pid = %d, ret = %ld\n", pid, ret);
return 0;
}
运行完毕后,查看结果saddr一直等于0,数据不对。
我尝试借鉴BCC的tcpconnect代码,使用saddr =&sk->__sk_common.skc_rcv_saddr和bpf_core_read(&saddr,sizeof(saddr),&sk->__sk_common.skc_rcv_saddr),其结果依然不对。
有人可以帮忙解决一下吗?怎么使用libbpf的BPF_CORE_READ正确读取内核中的sock数据。
数据封装时出现了问题,正确的封装关键代码如下:
//bpf_probe_read(&ipv4_key.saddr, sizeof(ipv4_key.saddr), &sk->__sk_common.skc_rcv_saddr);
struct ipv4_key_t ipv4_key = {.pid = pid};
ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
ipv4_key.daddr = sk->__sk_common.skc_daddr;
ipv4_key.lport = sk->__sk_common.skc_num;
dport = sk->__sk_common.skc_dport;
ipv4_key.dport = ntohs(dport);
ipv4_send_bytes.increment(ipv4_key, size);
将获取到的流量、地址和端口信息,通过bpf中的map.increment()这样一个方法进行封装在BPF_HASH中