xref: /aosp_15_r20/external/bcc/examples/tracing/tcpv4connect.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1#!/usr/bin/python
2#
3# tcpv4connect	Trace TCP IPv4 connect()s.
4#		For Linux, uses BCC, eBPF. Embedded C.
5#
6# USAGE: tcpv4connect [-h] [-t] [-p PID]
7#
8# This is provided as a basic example of TCP connection & socket tracing.
9#
10# All IPv4 connection attempts are traced, even if they ultimately fail.
11#
12# Copyright (c) 2015 Brendan Gregg.
13# Licensed under the Apache License, Version 2.0 (the "License")
14#
15# 15-Oct-2015	Brendan Gregg	Created this.
16
17from __future__ import print_function
18from bcc import BPF
19from bcc.utils import printb
20
21# define BPF program
22bpf_text = """
23#include <uapi/linux/ptrace.h>
24#include <net/sock.h>
25#include <bcc/proto.h>
26
27BPF_HASH(currsock, u32, struct sock *);
28
29int kprobe__tcp_v4_connect(struct pt_regs *ctx, struct sock *sk)
30{
31	u32 pid = bpf_get_current_pid_tgid();
32
33	// stash the sock ptr for lookup on return
34	currsock.update(&pid, &sk);
35
36	return 0;
37};
38
39int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
40{
41	int ret = PT_REGS_RC(ctx);
42	u32 pid = bpf_get_current_pid_tgid();
43
44	struct sock **skpp;
45	skpp = currsock.lookup(&pid);
46	if (skpp == 0) {
47		return 0;	// missed entry
48	}
49
50	if (ret != 0) {
51		// failed to send SYNC packet, may not have populated
52		// socket __sk_common.{skc_rcv_saddr, ...}
53		currsock.delete(&pid);
54		return 0;
55	}
56
57	// pull in details
58	struct sock *skp = *skpp;
59	u32 saddr = skp->__sk_common.skc_rcv_saddr;
60	u32 daddr = skp->__sk_common.skc_daddr;
61	u16 dport = skp->__sk_common.skc_dport;
62
63	// output
64	bpf_trace_printk("trace_tcp4connect %x %x %d\\n", saddr, daddr, ntohs(dport));
65
66	currsock.delete(&pid);
67
68	return 0;
69}
70"""
71
72# initialize BPF
73b = BPF(text=bpf_text)
74
75# header
76print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR",
77    "DPORT"))
78
79def inet_ntoa(addr):
80	dq = b''
81	for i in range(0, 4):
82		dq = dq + str(addr & 0xff).encode()
83		if (i != 3):
84			dq = dq + b'.'
85		addr = addr >> 8
86	return dq
87
88# filter and format output
89while 1:
90	# Read messages from kernel pipe
91	try:
92	    (task, pid, cpu, flags, ts, msg) = b.trace_fields()
93	    (_tag, saddr_hs, daddr_hs, dport_s) = msg.split(b" ")
94	except ValueError:
95	    # Ignore messages from other tracers
96	    continue
97	except KeyboardInterrupt:
98	    exit()
99
100	# Ignore messages from other tracers
101	if _tag.decode() != "trace_tcp4connect":
102	    continue
103
104	printb(b"%-6d %-12.12s %-16s %-16s %-4s" % (pid, task,
105	    inet_ntoa(int(saddr_hs, 16)),
106	    inet_ntoa(int(daddr_hs, 16)),
107	    dport_s))
108