blob: 8a89469dec0697a77e9b524237c1fe6da188c02a [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;
Paul Chaignoneae0acf2017-08-05 23:04:41 +020058 u32 saddr = skp->__sk_common.skc_rcv_saddr;
59 u32 daddr = skp->__sk_common.skc_daddr;
60 u16 dport = skp->__sk_common.skc_dport;
Brendan Gregg870b1cd2015-09-25 17:01:17 -070061
62 // output
Jean-Tiare Le Bigotd0764aa2016-02-21 23:45:29 +010063 bpf_trace_printk("trace_tcp4connect %x %x %d\\n", saddr, daddr, ntohs(dport));
Brendan Gregg870b1cd2015-09-25 17:01:17 -070064
65 currsock.delete(&pid);
66
67 return 0;
68}
69"""
70
Brendan Gregg870b1cd2015-09-25 17:01:17 -070071# initialize BPF
72b = BPF(text=bpf_text)
73
74# header
Brendan Gregg870b1cd2015-09-25 17:01:17 -070075print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR",
76 "DPORT"))
77
Brendan Gregg870b1cd2015-09-25 17:01:17 -070078def inet_ntoa(addr):
79 dq = ''
80 for i in range(0, 4):
81 dq = dq + str(addr & 0xff)
82 if (i != 3):
83 dq = dq + '.'
84 addr = addr >> 8
85 return dq
86
Jean-Tiare Le Bigotd0764aa2016-02-21 23:45:29 +010087# filter and format output
Brendan Gregg870b1cd2015-09-25 17:01:17 -070088while 1:
Iago López Galeiras5bd242c2016-09-08 16:45:11 +020089 # Read messages from kernel pipe
90 try:
91 (task, pid, cpu, flags, ts, msg) = b.trace_fields()
92 (_tag, saddr_hs, daddr_hs, dport_s) = msg.split(" ")
93 except ValueError:
94 # Ignore messages from other tracers
95 continue
Jean-Tiare Le Bigotd0764aa2016-02-21 23:45:29 +010096
Iago López Galeiras5bd242c2016-09-08 16:45:11 +020097 # Ignore messages from other tracers
98 if _tag != "trace_tcp4connect":
99 continue
Brendan Gregg870b1cd2015-09-25 17:01:17 -0700100
Brendan Gregg870b1cd2015-09-25 17:01:17 -0700101 print("%-6d %-12.12s %-16s %-16s %-4s" % (pid, task,
102 inet_ntoa(int(saddr_hs, 16)),
103 inet_ntoa(int(daddr_hs, 16)),
104 dport_s))