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