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# tcpaccept Trace TCP accept()s. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: tcpaccept [-h] [-t] [-p PID] 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# This uses dynamic tracing of the kernel inet_csk_accept() socket function 10*387f9dfdSAndroid Build Coastguard Worker# (from tcp_prot.accept), and will need to be modified to match kernel changes. 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# IPv4 addresses are printed as dotted quads. For IPv6 addresses, the last four 13*387f9dfdSAndroid Build Coastguard Worker# bytes are printed after "..."; check for future versions with better IPv6 14*387f9dfdSAndroid Build Coastguard Worker# support. 15*387f9dfdSAndroid Build Coastguard Worker# 16*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg. 17*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 18*387f9dfdSAndroid Build Coastguard Worker# 19*387f9dfdSAndroid Build Coastguard Worker# 13-Oct-2015 Brendan Gregg Created this. 20*387f9dfdSAndroid Build Coastguard Worker 21*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 22*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 23*387f9dfdSAndroid Build Coastguard Workerimport argparse 24*387f9dfdSAndroid Build Coastguard Worker 25*387f9dfdSAndroid Build Coastguard Worker# arguments 26*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 27*387f9dfdSAndroid Build Coastguard Worker ./tcpaccept # trace all TCP accept()s 28*387f9dfdSAndroid Build Coastguard Worker ./tcpaccept -t # include timestamps 29*387f9dfdSAndroid Build Coastguard Worker ./tcpaccept -p 181 # only trace PID 181 30*387f9dfdSAndroid Build Coastguard Worker""" 31*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 32*387f9dfdSAndroid Build Coastguard Worker description="Trace TCP accepts", 33*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 34*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 35*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-t", "--timestamp", action="store_true", 36*387f9dfdSAndroid Build Coastguard Worker help="include timestamp on output") 37*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", 38*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 39*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 40*387f9dfdSAndroid Build Coastguard Workerdebug = 0 41*387f9dfdSAndroid Build Coastguard Worker 42*387f9dfdSAndroid Build Coastguard Worker# define BPF program 43*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 44*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 45*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h> 46*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h> 47*387f9dfdSAndroid Build Coastguard Worker 48*387f9dfdSAndroid Build Coastguard Workerint kretprobe__inet_csk_accept(struct pt_regs *ctx) 49*387f9dfdSAndroid Build Coastguard Worker{ 50*387f9dfdSAndroid Build Coastguard Worker struct sock *newsk = (struct sock *)PT_REGS_RC(ctx); 51*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 52*387f9dfdSAndroid Build Coastguard Worker 53*387f9dfdSAndroid Build Coastguard Worker if (newsk == NULL) 54*387f9dfdSAndroid Build Coastguard Worker return 0; 55*387f9dfdSAndroid Build Coastguard Worker 56*387f9dfdSAndroid Build Coastguard Worker // check this is TCP 57*387f9dfdSAndroid Build Coastguard Worker u8 protocol = 0; 58*387f9dfdSAndroid Build Coastguard Worker // workaround for reading the sk_protocol bitfield: 59*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&protocol, 1, (void *)((long)&newsk->sk_wmem_queued) - 3); 60*387f9dfdSAndroid Build Coastguard Worker if (protocol != IPPROTO_TCP) 61*387f9dfdSAndroid Build Coastguard Worker return 0; 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker // pull in details 64*387f9dfdSAndroid Build Coastguard Worker u16 family = 0, lport = 0; 65*387f9dfdSAndroid Build Coastguard Worker u32 saddr = 0, daddr = 0; 66*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&family, sizeof(family), &newsk->__sk_common.skc_family); 67*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&lport, sizeof(lport), &newsk->__sk_common.skc_num); 68*387f9dfdSAndroid Build Coastguard Worker if (family == AF_INET) { 69*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&saddr, sizeof(saddr), 70*387f9dfdSAndroid Build Coastguard Worker &newsk->__sk_common.skc_rcv_saddr); 71*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&daddr, sizeof(daddr), 72*387f9dfdSAndroid Build Coastguard Worker &newsk->__sk_common.skc_daddr); 73*387f9dfdSAndroid Build Coastguard Worker 74*387f9dfdSAndroid Build Coastguard Worker // output 75*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("4 %x %x %d\\n", daddr, saddr, lport); 76*387f9dfdSAndroid Build Coastguard Worker } else if (family == AF_INET6) { 77*387f9dfdSAndroid Build Coastguard Worker // just grab the last 4 bytes for now 78*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&saddr, sizeof(saddr), 79*387f9dfdSAndroid Build Coastguard Worker &newsk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32[3]); 80*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&daddr, sizeof(daddr), 81*387f9dfdSAndroid Build Coastguard Worker &newsk->__sk_common.skc_v6_daddr.in6_u.u6_addr32[3]); 82*387f9dfdSAndroid Build Coastguard Worker 83*387f9dfdSAndroid Build Coastguard Worker // output and flip byte order of addresses 84*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("6 %x %x %d\\n", bpf_ntohl(daddr), 85*387f9dfdSAndroid Build Coastguard Worker bpf_ntohl(saddr), lport); 86*387f9dfdSAndroid Build Coastguard Worker } 87*387f9dfdSAndroid Build Coastguard Worker // else drop 88*387f9dfdSAndroid Build Coastguard Worker 89*387f9dfdSAndroid Build Coastguard Worker return 0; 90*387f9dfdSAndroid Build Coastguard Worker} 91*387f9dfdSAndroid Build Coastguard Worker""" 92*387f9dfdSAndroid Build Coastguard Worker 93*387f9dfdSAndroid Build Coastguard Worker# code substitutions 94*387f9dfdSAndroid Build Coastguard Workerif args.pid: 95*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER', 96*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %s) { return 0; }' % args.pid) 97*387f9dfdSAndroid Build Coastguard Workerelse: 98*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER', '') 99*387f9dfdSAndroid Build Coastguard Workerif debug: 100*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 101*387f9dfdSAndroid Build Coastguard Worker 102*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 103*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 104*387f9dfdSAndroid Build Coastguard Worker 105*387f9dfdSAndroid Build Coastguard Worker# header 106*387f9dfdSAndroid Build Coastguard Workerif args.timestamp: 107*387f9dfdSAndroid Build Coastguard Worker print("%-9s" % ("TIME(s)"), end="") 108*387f9dfdSAndroid Build Coastguard Workerprint("%-6s %-12s %-2s %-16s %-16s %-4s" % ("PID", "COMM", "IP", "RADDR", 109*387f9dfdSAndroid Build Coastguard Worker "LADDR", "LPORT")) 110*387f9dfdSAndroid Build Coastguard Worker 111*387f9dfdSAndroid Build Coastguard Workerstart_ts = 0 112*387f9dfdSAndroid Build Coastguard Worker 113*387f9dfdSAndroid Build Coastguard Workerdef inet_ntoa(addr): 114*387f9dfdSAndroid Build Coastguard Worker dq = '' 115*387f9dfdSAndroid Build Coastguard Worker for i in range(0, 4): 116*387f9dfdSAndroid Build Coastguard Worker dq = dq + str(addr & 0xff) 117*387f9dfdSAndroid Build Coastguard Worker if (i != 3): 118*387f9dfdSAndroid Build Coastguard Worker dq = dq + '.' 119*387f9dfdSAndroid Build Coastguard Worker addr = addr >> 8 120*387f9dfdSAndroid Build Coastguard Worker return dq 121*387f9dfdSAndroid Build Coastguard Worker 122*387f9dfdSAndroid Build Coastguard Worker# format output 123*387f9dfdSAndroid Build Coastguard Workerwhile 1: 124*387f9dfdSAndroid Build Coastguard Worker (task, pid, cpu, flags, ts, msg) = b.trace_fields() 125*387f9dfdSAndroid Build Coastguard Worker (ip_s, raddr_hs, laddr_hs, lport_s) = msg.split(" ") 126*387f9dfdSAndroid Build Coastguard Worker 127*387f9dfdSAndroid Build Coastguard Worker if args.timestamp: 128*387f9dfdSAndroid Build Coastguard Worker if start_ts == 0: 129*387f9dfdSAndroid Build Coastguard Worker start_ts = ts 130*387f9dfdSAndroid Build Coastguard Worker print("%-9.3f" % (ts - start_ts), end="") 131*387f9dfdSAndroid Build Coastguard Worker print("%-6d %-12.12s %-2s %-16s %-16s %-4s" % (pid, task, ip_s, 132*387f9dfdSAndroid Build Coastguard Worker inet_ntoa(int(raddr_hs, 16)) if ip_s == "4" else "..." + raddr_hs, 133*387f9dfdSAndroid Build Coastguard Worker inet_ntoa(int(laddr_hs, 16)) if ip_s == "4" else "..." + laddr_hs, 134*387f9dfdSAndroid Build Coastguard Worker lport_s)) 135