blob: 8640875f0e07d6cb73f1cc6dc06219bdb278b2ff [file] [log] [blame]
rtoax57a86aa2021-09-12 13:33:37 +08001#!/usr/bin/python
2# @lint-avoid-python-3-compatibility-imports
3#
4# undump Dump UNIX socket packets.
5# For Linux, uses BCC, eBPF. Embedded C.
6# USAGE: undump [-h] [-t] [-p PID]
7#
8# This uses dynamic tracing of kernel functions, and will need to be updated
9# to match kernel changes.
10#
11# Copyright (c) 2021 Rong Tao.
12# Licensed under the GPL License, Version 2.0
13#
14# 27-Aug-2021 Rong Tao Created this.
rtoax4615a3f2021-09-17 18:38:24 +080015# 17-Sep-2021 Rong Tao Simplify according to chenhengqi's suggestion
16# https://github.com/iovisor/bcc/pull/3615
rtoax57a86aa2021-09-12 13:33:37 +080017#
18from __future__ import print_function
19from bcc import BPF
20from bcc.containers import filter_by_containers
21from bcc.utils import printb
22import argparse
23from socket import inet_ntop, ntohs, AF_INET, AF_INET6
24from struct import pack
25from time import sleep
26from datetime import datetime
27import sys
28
29# arguments
30examples = """examples:
31 ./undump # trace/dump all UNIX packets
rtoax57a86aa2021-09-12 13:33:37 +080032 ./undump -p 181 # only trace/dump PID 181
33"""
34parser = argparse.ArgumentParser(
35 description="Dump UNIX socket packets",
36 formatter_class=argparse.RawDescriptionHelpFormatter,
37 epilog=examples)
38
rtoax57a86aa2021-09-12 13:33:37 +080039parser.add_argument("-p", "--pid",
40 help="trace this PID only")
41args = parser.parse_args()
42
43# define BPF program
44bpf_text = """
45#include <uapi/linux/ptrace.h>
46#include <net/sock.h>
47#include <bcc/proto.h>
48#include <linux/aio.h>
49#include <linux/socket.h>
50#include <linux/net.h>
51#include <linux/fs.h>
52#include <linux/mount.h>
53#include <linux/module.h>
54#include <net/sock.h>
55#include <net/af_unix.h>
56
rtoax57a86aa2021-09-12 13:33:37 +080057#define MAX_PKT 512
58struct recv_data_t {
59 u32 recv_len;
60 u8 pkt[MAX_PKT];
61};
62
63// single element per-cpu array to hold the current event off the stack
rtoax4615a3f2021-09-17 18:38:24 +080064BPF_PERCPU_ARRAY(unix_data, struct recv_data_t, 1);
rtoax57a86aa2021-09-12 13:33:37 +080065
66BPF_PERF_OUTPUT(unix_recv_events);
67
rtoax57a86aa2021-09-12 13:33:37 +080068int trace_unix_stream_read_actor(struct pt_regs *ctx)
69{
70 u32 zero = 0;
71 int ret = PT_REGS_RC(ctx);
72 u64 pid_tgid = bpf_get_current_pid_tgid();
73 u32 pid = pid_tgid >> 32;
74 u32 tid = pid_tgid;
75
76 FILTER_PID
77
78 struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
79
80 struct recv_data_t *data = unix_data.lookup(&zero);
81 if (!data)
82 return 0;
83
84 unsigned int data_len = skb->len;
85 if(data_len > MAX_PKT)
86 return 0;
87
88 void *iodata = (void *)skb->data;
89 data->recv_len = data_len;
90
91 bpf_probe_read(data->pkt, data_len, iodata);
92 unix_recv_events.perf_submit(ctx, data, data_len+sizeof(u32));
93
94 return 0;
95}
96"""
97
98if args.pid:
99 bpf_text = bpf_text.replace('FILTER_PID',
100 'if (pid != %s) { return 0; }' % args.pid)
101
102bpf_text = bpf_text.replace('FILTER_PID', '')
103
104# process event
rtoax57a86aa2021-09-12 13:33:37 +0800105def print_recv_pkg(cpu, data, size):
106 event = b["unix_recv_events"].event(data)
rtoax4615a3f2021-09-17 18:38:24 +0800107 if args.pid:
108 print("PID \033[1;31m%s\033[m " % args.pid, end="")
109 print("Recv \033[1;31m%d\033[m bytes" % event.recv_len)
110
111 print(" ", end="")
rtoax57a86aa2021-09-12 13:33:37 +0800112 for i in range(0, event.recv_len):
113 print("%02x " % event.pkt[i], end="")
114 sys.stdout.flush()
115 if (i+1)%16 == 0:
116 print("")
rtoax4615a3f2021-09-17 18:38:24 +0800117 print(" ", end="")
118 print("")
119
rtoax57a86aa2021-09-12 13:33:37 +0800120# initialize BPF
121b = BPF(text=bpf_text)
rtoax57a86aa2021-09-12 13:33:37 +0800122b.attach_kprobe(event="unix_stream_read_actor", fn_name="trace_unix_stream_read_actor")
123
rtoax4615a3f2021-09-17 18:38:24 +0800124if args.pid:
125 print("Tracing \033[1;31mPID=%s\033[m UNIX socket packets ... Hit Ctrl-C to end" % args.pid)
126else:
127 print("Tracing UNIX socket packets ... Hit Ctrl-C to end")
rtoax57a86aa2021-09-12 13:33:37 +0800128
rtoax57a86aa2021-09-12 13:33:37 +0800129start_ts = 0
130
131# read events
rtoax57a86aa2021-09-12 13:33:37 +0800132b["unix_recv_events"].open_perf_buffer(print_recv_pkg)
133
134while True:
135 try:
136 b.perf_buffer_poll()
137 except KeyboardInterrupt:
138 exit()