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