blob: 036ef726e77f9e214455224a3bc6da21721f2a28 [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#
Brendan Greggf06d3b42015-10-15 17:21:32 -07008# 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#
Brendan Gregg870b1cd2015-09-25 17:01:17 -070012# Copyright (c) 2015 Brendan Gregg.
13# Licensed under the Apache License, Version 2.0 (the "License")
14#
Brendan Greggf06d3b42015-10-15 17:21:32 -070015# 15-Oct-2015 Brendan Gregg Created this.
Brendan Gregg870b1cd2015-09-25 17:01:17 -070016
17from __future__ import print_function
18from bcc import BPF
Brendan Gregg870b1cd2015-09-25 17:01:17 -070019
20# define BPF program
21bpf_text = """
22#include <uapi/linux/ptrace.h>
23#include <net/sock.h>
24#include <bcc/proto.h>
25
26BPF_HASH(currsock, u32, struct sock *);
27
28int kprobe__tcp_v4_connect(struct pt_regs *ctx, struct sock *sk)
29{
30 u32 pid = bpf_get_current_pid_tgid();
Brendan Gregg870b1cd2015-09-25 17:01:17 -070031
32 // stash the sock ptr for lookup on return
33 currsock.update(&pid, &sk);
34
35 return 0;
36};
37
38int kretprobe__tcp_v4_connect(struct pt_regs *ctx)
39{
Naveen N. Rao4afa96a2016-05-03 14:54:21 +053040 int ret = PT_REGS_RC(ctx);
Brendan Gregg870b1cd2015-09-25 17:01:17 -070041 u32 pid = bpf_get_current_pid_tgid();
42
43 struct sock **skpp;
44 skpp = currsock.lookup(&pid);
45 if (skpp == 0) {
46 return 0; // missed entry
47 }
48
Yonghong Song366eb2e2015-10-07 08:59:42 -070049 if (ret != 0) {
Brendan Greggf06d3b42015-10-15 17:21:32 -070050 // failed to send SYNC packet, may not have populated
51 // socket __sk_common.{skc_rcv_saddr, ...}
Yonghong Song366eb2e2015-10-07 08:59:42 -070052 currsock.delete(&pid);
53 return 0;
54 }
55
Brendan Gregg870b1cd2015-09-25 17:01:17 -070056 // pull in details
57 struct sock *skp = *skpp;
58 u32 saddr = 0, daddr = 0;
59 u16 dport = 0;
60 bpf_probe_read(&saddr, sizeof(saddr), &skp->__sk_common.skc_rcv_saddr);
61 bpf_probe_read(&daddr, sizeof(daddr), &skp->__sk_common.skc_daddr);
62 bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport);
63
64 // output
Jean-Tiare Le Bigotd0764aa2016-02-21 23:45:29 +010065 bpf_trace_printk("trace_tcp4connect %x %x %d\\n", saddr, daddr, ntohs(dport));
Brendan Gregg870b1cd2015-09-25 17:01:17 -070066
67 currsock.delete(&pid);
68
69 return 0;
70}
71"""
72
Brendan Gregg870b1cd2015-09-25 17:01:17 -070073# initialize BPF
74b = BPF(text=bpf_text)
75
76# header
Brendan Gregg870b1cd2015-09-25 17:01:17 -070077print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR",
78 "DPORT"))
79
Brendan Gregg870b1cd2015-09-25 17:01:17 -070080def inet_ntoa(addr):
81 dq = ''
82 for i in range(0, 4):
83 dq = dq + str(addr & 0xff)
84 if (i != 3):
85 dq = dq + '.'
86 addr = addr >> 8
87 return dq
88
Jean-Tiare Le Bigotd0764aa2016-02-21 23:45:29 +010089# filter and format output
Brendan Gregg870b1cd2015-09-25 17:01:17 -070090while 1:
Jean-Tiare Le Bigotd0764aa2016-02-21 23:45:29 +010091 # Read messages from kernel pipe
92 try:
93 (task, pid, cpu, flags, ts, msg) = b.trace_fields()
94 (_tag, saddr_hs, daddr_hs, dport_s) = msg.split(" ")
95 except ValueError:
96 # Ignore messages from other tracers
97 continue
98
99 # Ignore messages from other tracers
100 if _tag != "trace_tcp4connect":
101 continue
Brendan Gregg870b1cd2015-09-25 17:01:17 -0700102
Brendan Gregg870b1cd2015-09-25 17:01:17 -0700103 print("%-6d %-12.12s %-16s %-16s %-4s" % (pid, task,
104 inet_ntoa(int(saddr_hs, 16)),
105 inet_ntoa(int(daddr_hs, 16)),
106 dport_s))