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 19 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(); 31 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{ 40 int ret = PT_REGS_RC(ctx); 41 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 49 if (ret != 0) { 50 // failed to send SYNC packet, may not have populated 51 // socket __sk_common.{skc_rcv_saddr, ...} 52 currsock.delete(&pid); 53 return 0; 54 } 55 56 // pull in details 57 struct sock *skp = *skpp; 58 u32 saddr = skp->__sk_common.skc_rcv_saddr; 59 u32 daddr = skp->__sk_common.skc_daddr; 60 u16 dport = skp->__sk_common.skc_dport; 61 62 // output 63 bpf_trace_printk("trace_tcp4connect %x %x %d\\n", saddr, daddr, ntohs(dport)); 64 65 currsock.delete(&pid); 66 67 return 0; 68} 69""" 70 71# initialize BPF 72b = BPF(text=bpf_text) 73 74# header 75print("%-6s %-12s %-16s %-16s %-4s" % ("PID", "COMM", "SADDR", "DADDR", 76 "DPORT")) 77 78def 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 87# filter and format output 88while 1: 89 # 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 96 97 # Ignore messages from other tracers 98 if _tag != "trace_tcp4connect": 99 continue 100 101 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)) 105