1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# tcpconnect Trace TCP connect()s. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: tcpconnect [-h] [-t] [-p PID] 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# All connection attempts are traced, even if they ultimately fail. 10*387f9dfdSAndroid Build Coastguard Worker# 11*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg. 12*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 13*387f9dfdSAndroid Build Coastguard Worker# 14*387f9dfdSAndroid Build Coastguard Worker# 25-Sep-2015 Brendan Gregg Created this. 15*387f9dfdSAndroid Build Coastguard Worker 16*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 17*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 18*387f9dfdSAndroid Build Coastguard Workerimport argparse 19*387f9dfdSAndroid Build Coastguard Worker 20*387f9dfdSAndroid Build Coastguard Worker# arguments 21*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 22*387f9dfdSAndroid Build Coastguard Worker ./tcpconnect # trace all TCP connect()s 23*387f9dfdSAndroid Build Coastguard Worker ./tcpconnect -t # include timestamps 24*387f9dfdSAndroid Build Coastguard Worker ./tcpconnect -p 181 # only trace PID 181 25*387f9dfdSAndroid Build Coastguard Worker""" 26*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 27*387f9dfdSAndroid Build Coastguard Worker description="Trace TCP connects", 28*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 29*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 30*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-t", "--timestamp", action="store_true", 31*387f9dfdSAndroid Build Coastguard Worker help="include timestamp on output") 32*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", 33*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 34*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 35*387f9dfdSAndroid Build Coastguard Workerdebug = 0 36*387f9dfdSAndroid Build Coastguard Worker 37*387f9dfdSAndroid Build Coastguard Worker# define BPF program 38*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 39*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 40*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h> 41*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h> 42*387f9dfdSAndroid Build Coastguard Worker 43*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(currsock, u32, struct sock *); 44*387f9dfdSAndroid Build Coastguard Worker 45*387f9dfdSAndroid Build Coastguard Workerint trace_connect_entry(struct pt_regs *ctx, struct sock *sk) 46*387f9dfdSAndroid Build Coastguard Worker{ 47*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 48*387f9dfdSAndroid Build Coastguard Worker FILTER 49*387f9dfdSAndroid Build Coastguard Worker 50*387f9dfdSAndroid Build Coastguard Worker // stash the sock ptr for lookup on return 51*387f9dfdSAndroid Build Coastguard Worker currsock.update(&pid, &sk); 52*387f9dfdSAndroid Build Coastguard Worker 53*387f9dfdSAndroid Build Coastguard Worker return 0; 54*387f9dfdSAndroid Build Coastguard Worker}; 55*387f9dfdSAndroid Build Coastguard Worker 56*387f9dfdSAndroid Build Coastguard Workerstatic int trace_connect_return(struct pt_regs *ctx, short ipver) 57*387f9dfdSAndroid Build Coastguard Worker{ 58*387f9dfdSAndroid Build Coastguard Worker int ret = PT_REGS_RC(ctx); 59*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 60*387f9dfdSAndroid Build Coastguard Worker 61*387f9dfdSAndroid Build Coastguard Worker struct sock **skpp; 62*387f9dfdSAndroid Build Coastguard Worker skpp = currsock.lookup(&pid); 63*387f9dfdSAndroid Build Coastguard Worker if (skpp == 0) { 64*387f9dfdSAndroid Build Coastguard Worker return 0; // missed entry 65*387f9dfdSAndroid Build Coastguard Worker } 66*387f9dfdSAndroid Build Coastguard Worker 67*387f9dfdSAndroid Build Coastguard Worker if (ret != 0) { 68*387f9dfdSAndroid Build Coastguard Worker // failed to send SYNC packet, may not have populated 69*387f9dfdSAndroid Build Coastguard Worker // socket __sk_common.{skc_rcv_saddr, ...} 70*387f9dfdSAndroid Build Coastguard Worker currsock.delete(&pid); 71*387f9dfdSAndroid Build Coastguard Worker return 0; 72*387f9dfdSAndroid Build Coastguard Worker } 73*387f9dfdSAndroid Build Coastguard Worker 74*387f9dfdSAndroid Build Coastguard Worker // pull in details 75*387f9dfdSAndroid Build Coastguard Worker struct sock *skp = *skpp; 76*387f9dfdSAndroid Build Coastguard Worker u32 saddr = 0, daddr = 0; 77*387f9dfdSAndroid Build Coastguard Worker u16 dport = 0; 78*387f9dfdSAndroid Build Coastguard Worker dport = skp->__sk_common.skc_dport; 79*387f9dfdSAndroid Build Coastguard Worker if (ipver == 4) { 80*387f9dfdSAndroid Build Coastguard Worker saddr = skp->__sk_common.skc_rcv_saddr; 81*387f9dfdSAndroid Build Coastguard Worker daddr = skp->__sk_common.skc_daddr; 82*387f9dfdSAndroid Build Coastguard Worker 83*387f9dfdSAndroid Build Coastguard Worker // output 84*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("4 %x %x %d\\n", saddr, daddr, ntohs(dport)); 85*387f9dfdSAndroid Build Coastguard Worker } else /* 6 */ { 86*387f9dfdSAndroid Build Coastguard Worker // just grab the last 4 bytes for now 87*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&saddr, sizeof(saddr), 88*387f9dfdSAndroid Build Coastguard Worker &skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]); 89*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&daddr, sizeof(daddr), 90*387f9dfdSAndroid Build Coastguard Worker &skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]); 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker // output and flip byte order of addresses 93*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("6 %x %x %d\\n", bpf_ntohl(saddr), 94*387f9dfdSAndroid Build Coastguard Worker bpf_ntohl(daddr), ntohs(dport)); 95*387f9dfdSAndroid Build Coastguard Worker } 96*387f9dfdSAndroid Build Coastguard Worker 97*387f9dfdSAndroid Build Coastguard Worker currsock.delete(&pid); 98*387f9dfdSAndroid Build Coastguard Worker 99*387f9dfdSAndroid Build Coastguard Worker return 0; 100*387f9dfdSAndroid Build Coastguard Worker} 101*387f9dfdSAndroid Build Coastguard Worker 102*387f9dfdSAndroid Build Coastguard Workerint trace_connect_v4_return(struct pt_regs *ctx) 103*387f9dfdSAndroid Build Coastguard Worker{ 104*387f9dfdSAndroid Build Coastguard Worker return trace_connect_return(ctx, 4); 105*387f9dfdSAndroid Build Coastguard Worker} 106*387f9dfdSAndroid Build Coastguard Worker 107*387f9dfdSAndroid Build Coastguard Workerint trace_connect_v6_return(struct pt_regs *ctx) 108*387f9dfdSAndroid Build Coastguard Worker{ 109*387f9dfdSAndroid Build Coastguard Worker return trace_connect_return(ctx, 6); 110*387f9dfdSAndroid Build Coastguard Worker} 111*387f9dfdSAndroid Build Coastguard Worker""" 112*387f9dfdSAndroid Build Coastguard Worker 113*387f9dfdSAndroid Build Coastguard Worker# code substitutions 114*387f9dfdSAndroid Build Coastguard Workerif args.pid: 115*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER', 116*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %s) { return 0; }' % args.pid) 117*387f9dfdSAndroid Build Coastguard Workerelse: 118*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER', '') 119*387f9dfdSAndroid Build Coastguard Workerif debug: 120*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 121*387f9dfdSAndroid Build Coastguard Worker 122*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 123*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 124*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect_entry") 125*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="tcp_v6_connect", fn_name="trace_connect_entry") 126*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="tcp_v4_connect", fn_name="trace_connect_v4_return") 127*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event="tcp_v6_connect", fn_name="trace_connect_v6_return") 128*387f9dfdSAndroid Build Coastguard Worker 129*387f9dfdSAndroid Build Coastguard Worker# header 130*387f9dfdSAndroid Build Coastguard Workerif args.timestamp: 131*387f9dfdSAndroid Build Coastguard Worker print("%-9s" % ("TIME(s)"), end="") 132*387f9dfdSAndroid Build Coastguard Workerprint("%-6s %-12s %-2s %-16s %-16s %-4s" % ("PID", "COMM", "IP", "SADDR", 133*387f9dfdSAndroid Build Coastguard Worker "DADDR", "DPORT")) 134*387f9dfdSAndroid Build Coastguard Worker 135*387f9dfdSAndroid Build Coastguard Workerstart_ts = 0 136*387f9dfdSAndroid Build Coastguard Worker 137*387f9dfdSAndroid Build Coastguard Workerdef inet_ntoa(addr): 138*387f9dfdSAndroid Build Coastguard Worker dq = '' 139*387f9dfdSAndroid Build Coastguard Worker for i in range(0, 4): 140*387f9dfdSAndroid Build Coastguard Worker dq = dq + str(addr & 0xff) 141*387f9dfdSAndroid Build Coastguard Worker if (i != 3): 142*387f9dfdSAndroid Build Coastguard Worker dq = dq + '.' 143*387f9dfdSAndroid Build Coastguard Worker addr = addr >> 8 144*387f9dfdSAndroid Build Coastguard Worker return dq 145*387f9dfdSAndroid Build Coastguard Worker 146*387f9dfdSAndroid Build Coastguard Worker# format output 147*387f9dfdSAndroid Build Coastguard Workerwhile 1: 148*387f9dfdSAndroid Build Coastguard Worker (task, pid, cpu, flags, ts, msg) = b.trace_fields() 149*387f9dfdSAndroid Build Coastguard Worker (ip_s, saddr_hs, daddr_hs, dport_s) = msg.split(" ") 150*387f9dfdSAndroid Build Coastguard Worker 151*387f9dfdSAndroid Build Coastguard Worker if args.timestamp: 152*387f9dfdSAndroid Build Coastguard Worker if start_ts == 0: 153*387f9dfdSAndroid Build Coastguard Worker start_ts = ts 154*387f9dfdSAndroid Build Coastguard Worker print("%-9.3f" % (ts - start_ts), end="") 155*387f9dfdSAndroid Build Coastguard Worker print("%-6d %-12.12s %-2s %-16s %-16s %-4s" % (pid, task, ip_s, 156*387f9dfdSAndroid Build Coastguard Worker inet_ntoa(int(saddr_hs, 16)) if ip_s == "4" else "..." + saddr_hs, 157*387f9dfdSAndroid Build Coastguard Worker inet_ntoa(int(daddr_hs, 16)) if ip_s == "4" else "..." + daddr_hs, 158*387f9dfdSAndroid Build Coastguard Worker dport_s)) 159