我正试图编写一个小程序,利用Linux的跟踪点sys_enter_recvfrom
和sys_enter_sendto
来显示系统上发生的HTTP请求和响应对。
首先,我定义了以下可以容纳HTTP对象的C结构,因此可以是请求或响应:
struct http_obj {
char comm[TASK_COMM_LEN];
int fd;
char *buff;
char *addr_data;
int size;
};
以下是我的跟踪点:
TRACEPOINT_PROBE(syscalls, sys_enter_recvfrom) {
return do_trace(args, args->fd, args->ubuf, args->addr);
}
TRACEPOINT_PROBE(syscalls, sys_enter_sendto){
return do_trace(args, args->fd, args->buff, args->addr);
}
以下是获取sys_enter_<syscall>
跟踪点的args
的函数:
static inline int do_trace(void* ctx, int fd, char *ubuf, struct sockaddr *addr)
{
// Built event for userland
struct http_obj evt = {};
bpf_get_current_comm(evt.comm, TASK_COMM_LEN);
evt.fd = fd;
evt.buff = (char *) ubuf;
evt.size = sizeof(ubuf);
evt.addr_data = (char *) addr->sa_data;
// send to userland
http_obj.perf_submit(ctx, &evt, sizeof(evt));
return 0;
}
使用python中的bcc
库,我只是打印发送到userland的字段的值。问题是缓冲区和事件地址总是空的。注意,字段是存在的,如果我们在/sys/kernel/debug/tracing/events/syscalls/sys_enter_recvfrom
上执行cat
,我们得到:
field:int __syscall_nr; offset:8; size:4; signed:1;
field:int fd; offset:16; size:8; signed:0;
field:void __attribute__((user)) * buff; offset:24; size:8; signed:0;
field:size_t len; offset:32; size:8; signed:0;
field:unsigned int flags; offset:40; size:8; signed:0;
field:struct sockaddr __attribute__((user)) * addr; offset:48; size:8; signed:0;
field:int addr_len; offset:56; size:8; signed:0;
有什么建议吗?
问题是缓冲区和事件地址总是空的。
这并不意外,您看到的是通过系统调用传递给内核的来自用户空间的参数。缓冲区是空的,因为内核应该在运行该跟踪点之后将数据包内容写入缓冲区。地址是可选字段,根据recvfrom
:的手册页允许为空
If the caller is not interested in the source address, src_addr and addrlen should be specified as NULL.
我建议使用TC程序来检查交通