blob: fdada97c20b977265dc6f7a55db4bfa1f92df715 [file] [log] [blame]
Brendan Gregg870b1cd2015-09-25 17:01:17 -07001#!/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# Copyright (c) 2015 Brendan Gregg.
9# Licensed under the Apache License, Version 2.0 (the "License")
10#
11# 25-Sep-2015 Brendan Gregg Created this.
12
13from __future__ import print_function
14from bcc import BPF
15import argparse
16
17# arguments
18examples = """examples:
19 ./tcpv4connect # trace all open() syscalls
20 ./tcpv4connect -t # include timestamps
21 ./tcpv4connect -p 181 # only trace PID 181
22"""
23parser = argparse.ArgumentParser(
24 description="Trace TCP IPv4 connects",
25 formatter_class=argparse.RawDescriptionHelpFormatter,
26 epilog=examples)
27parser.add_argument("-t", "--timestamp", action="store_true",
28 help="include timestamp on output")
29parser.add_argument("-p", "--pid",
30 help="trace this PID only")
31args = parser.parse_args()
32debug = 0
33
34# define BPF program
35bpf_text = """
36#include <uapi/linux/ptrace.h>
37#include <net/sock.h>
38#include <bcc/proto.h>
39
40BPF_HASH(currsock, u32, struct sock *);
41
42int kprobe__tcp_v4_connect(struct pt_regs *ctx, struct sock *sk)
43{
44 u32 pid = bpf_get_current_pid_tgid();
45 FILTER
46
47 // stash the sock ptr for lookup on return
48 currsock.update(&pid, &sk);
49
50 return 0;
51};
52
53int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
54{
55 int ret = ctx->ax;
56 u32 pid = bpf_get_current_pid_tgid();
57
58 struct sock **skpp;
59 skpp = currsock.lookup(&pid);
60 if (skpp == 0) {
61 return 0; // missed entry
62 }
63
64 // pull in details
65 struct sock *skp = *skpp;
66 u32 saddr = 0, daddr = 0;
67 u16 dport = 0;
68 bpf_probe_read(&saddr, sizeof(saddr), &skp->__sk_common.skc_rcv_saddr);
69 bpf_probe_read(&daddr, sizeof(daddr), &skp->__sk_common.skc_daddr);
70 bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);
71
72 // output
73 bpf_trace_printk("%x %x %d\\n", saddr, daddr, ntohs(dport));
74
75 currsock.delete(&pid);
76
77 return 0;
78}
79"""
80
81# code substitutions
82if args.pid:
83 bpf_text = bpf_text.replace('FILTER',
84 'if (pid != %s) { return 0; }' % args.pid)
85else:
86 bpf_text = bpf_text.replace('FILTER', '')
87if debug:
88 print(bpf_text)
89
90# initialize BPF
91b = BPF(text=bpf_text)
92
93# header
94if args.timestamp:
95 print("%-9s" % ("TIME(s)"), end="")
96print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR",
97 "DPORT"))
98
99start_ts = 0
100
101def inet_ntoa(addr):
102 dq = ''
103 for i in range(0, 4):
104 dq = dq + str(addr & 0xff)
105 if (i != 3):
106 dq = dq + '.'
107 addr = addr >> 8
108 return dq
109
110# format output
111while 1:
112 (task, pid, cpu, flags, ts, msg) = b.trace_fields()
113 (saddr_hs, daddr_hs, dport_s) = msg.split(" ")
114
115 if args.timestamp:
116 if start_ts == 0:
117 start_ts = ts
118 print("%-9.3f" % (ts - start_ts), end="")
119 print("%-6d %-12.12s %-16s %-16s %-4s" % (pid, task,
120 inet_ntoa(int(saddr_hs, 16)),
121 inet_ntoa(int(daddr_hs, 16)),
122 dport_s))