ICMP packet tracer using BCC
#!/usr/bin/python | |
bpf_text = """ | |
#include <linux/ptrace.h> | |
#include <linux/sched.h> /* For TASK_COMM_LEN */ | |
#include <linux/icmp.h> | |
#include <linux/netdevice.h> | |
struct probe_icmp_data_t | |
{ | |
u64 timestamp_ns; | |
u32 tgid; | |
u32 pid; | |
char comm[TASK_COMM_LEN]; | |
int v0; | |
}; | |
BPF_PERF_OUTPUT(probe_icmp_events); | |
static inline unsigned char *my_skb_transport_header(const struct sk_buff *skb) | |
{ | |
return skb->head + skb->transport_header; | |
} | |
static inline struct icmphdr *my_icmp_hdr(const struct sk_buff *skb) | |
{ | |
return (struct icmphdr *)my_skb_transport_header(skb); | |
} | |
int probe_icmp(struct pt_regs *ctx, struct sk_buff *skb) | |
{ | |
u64 __pid_tgid = bpf_get_current_pid_tgid(); | |
u32 __tgid = __pid_tgid >> 32; | |
u32 __pid = __pid_tgid; // implicit cast to u32 for bottom half | |
struct probe_icmp_data_t __data = {0}; | |
__data.timestamp_ns = bpf_ktime_get_ns(); | |
__data.tgid = __tgid; | |
__data.pid = __pid; | |
bpf_get_current_comm(&__data.comm, sizeof(__data.comm)); | |
__be16 seq; | |
bpf_probe_read(&seq, sizeof(seq), &my_icmp_hdr(skb)->un.echo.sequence); | |
__data.v0 = (int)seq; | |
probe_icmp_events.perf_submit(ctx, &__data, sizeof(__data)); | |
return 0; | |
} | |
""" | |
from bcc import BPF | |
import ctypes as ct | |
class Data_icmp(ct.Structure): | |
_fields_ = [ | |
("timestamp_ns", ct.c_ulonglong), | |
("tgid", ct.c_uint), | |
("pid", ct.c_uint), | |
("comm", ct.c_char * 16), # TASK_COMM_LEN | |
('v0', ct.c_uint), | |
] | |
b = BPF(text=bpf_text) | |
def print_icmp_event(cpu, data, size): | |
#event = b["probe_icmp_events"].event(data) | |
event = ct.cast(data, ct.POINTER(Data_icmp)).contents | |
print("%-7d %-7d %-15s %s" % | |
(event.tgid, event.pid, | |
event.comm.decode('utf-8', 'replace'), | |
event.v0)) | |
b.attach_kprobe(event="icmp_echo", fn_name="probe_icmp") | |
b["probe_icmp_events"].open_perf_buffer(print_icmp_event) | |
while 1: | |
try: | |
b.kprobe_poll() | |
except KeyboardInterrupt: | |
exit() |
This comment has been minimized.
This comment has been minimized.
replace
it works for kernel 4.18.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
When I ran this program in linux 5.7.7(centos 7.6), I got this error:
HINT: The invalid mem access 'inv' error can happen if you try to dereference memory without first using bpf_probe_read_kernel() to copy it to the BPF stack. Sometimes the bpf_probe_read_kernel() is automatic by the bcc rewriter, other times you'll need to be explicit.
And when i change the bpf_probe_read to bpf_probe_read_kernel it works