From: chantra Date: Sat, 10 Sep 2016 16:44:50 +0000 (-0700) Subject: [tcpconnect] filter traced connection based on destination ports X-Git-Tag: v0.3.0~196^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=52938058460cadac111234b92fd0018c03327e92;p=platform%2Fupstream%2Fbcc.git [tcpconnect] filter traced connection based on destination ports Test: While running: while [ 1 ]; do nc -w 1 100.127.0.1 80; nc -w 1 100.127.0.1 81; done root@vagrant:/mnt/bcc# ./tools/tcpconnect.py PID COMM IP SADDR DADDR DPORT 19978 nc 4 10.0.2.15 100.127.0.1 80 19979 nc 4 10.0.2.15 100.127.0.1 81 19980 nc 4 10.0.2.15 100.127.0.1 80 19981 nc 4 10.0.2.15 100.127.0.1 81 root@vagrant:/mnt/bcc# ./tools/tcpconnect.py -P 80 PID COMM IP SADDR DADDR DPORT 19987 nc 4 10.0.2.15 100.127.0.1 80 19989 nc 4 10.0.2.15 100.127.0.1 80 19991 nc 4 10.0.2.15 100.127.0.1 80 19993 nc 4 10.0.2.15 100.127.0.1 80 19995 nc 4 10.0.2.15 100.127.0.1 80 root@vagrant:/mnt/bcc# ./tools/tcpconnect.py -P 80,81 PID COMM IP SADDR DADDR DPORT 8725 nc 4 10.0.2.15 100.127.0.1 80 8726 nc 4 10.0.2.15 100.127.0.1 81 8727 nc 4 10.0.2.15 100.127.0.1 80 8728 nc 4 10.0.2.15 100.127.0.1 81 8729 nc 4 10.0.2.15 100.127.0.1 80 Fixes #681 --- diff --git a/man/man8/tcpconnect.8 b/man/man8/tcpconnect.8 index 27780ae..eb1f4ad 100644 --- a/man/man8/tcpconnect.8 +++ b/man/man8/tcpconnect.8 @@ -2,7 +2,7 @@ .SH NAME tcpconnect \- Trace TCP active connections (connect()). Uses Linux eBPF/bcc. .SH SYNOPSIS -.B tcpconnect [\-h] [\-t] [\-x] [\-p PID] +.B tcpconnect [\-h] [\-t] [\-x] [\-p PID] [-P PORT] .SH DESCRIPTION This tool traces active TCP connections (eg, via a connect() syscall; accept() are passive connections). This can be useful for general @@ -27,6 +27,9 @@ Include a timestamp column. .TP \-p PID Trace this process ID only (filtered in-kernel). +.TP +\-P PORT +Comma-separated list of destination ports to trace (filtered in-kernel). .SH EXAMPLES .TP Trace all active TCP connections: @@ -40,6 +43,10 @@ Trace all TCP connects, and include timestamps: Trace PID 181 only: # .B tcpconnect \-p 181 +.TP +Trace ports 80 and 81 only: +# +.B tcpconnect \-P 80,81 .SH FIELDS .TP TIME(s) diff --git a/tools/tcpconnect.py b/tools/tcpconnect.py index 7615167..5b7f187 100755 --- a/tools/tcpconnect.py +++ b/tools/tcpconnect.py @@ -4,7 +4,7 @@ # tcpconnect Trace TCP connect()s. # For Linux, uses BCC, eBPF. Embedded C. # -# USAGE: tcpconnect [-h] [-t] [-p PID] +# USAGE: tcpconnect [-h] [-t] [-p PID] [-P PORT [PORT ...]] # # All connection attempts are traced, even if they ultimately fail. # @@ -20,7 +20,7 @@ from __future__ import print_function from bcc import BPF import argparse -from socket import inet_ntop, AF_INET, AF_INET6 +from socket import inet_ntop, ntohs, AF_INET, AF_INET6 from struct import pack import ctypes as ct @@ -29,6 +29,8 @@ examples = """examples: ./tcpconnect # trace all TCP connect()s ./tcpconnect -t # include timestamps ./tcpconnect -p 181 # only trace PID 181 + ./tcpconnect -P 80 # only trace port 80 + ./tcpconnect -P 80,81 # only trace port 80 and 81 """ parser = argparse.ArgumentParser( description="Trace TCP connects", @@ -38,6 +40,8 @@ parser.add_argument("-t", "--timestamp", action="store_true", help="include timestamp on output") parser.add_argument("-p", "--pid", help="trace this PID only") +parser.add_argument("-P", "--port", + help="comma-separated list of destination ports to trace.") args = parser.parse_args() debug = 0 @@ -76,7 +80,7 @@ BPF_PERF_OUTPUT(ipv6_events); int trace_connect_entry(struct pt_regs *ctx, struct sock *sk) { u32 pid = bpf_get_current_pid_tgid(); - FILTER + FILTER_PID // stash the sock ptr for lookup on return currsock.update(&pid, &sk); @@ -107,6 +111,8 @@ static int trace_connect_return(struct pt_regs *ctx, short ipver) u16 dport = 0; bpf_probe_read(&dport, sizeof(dport), &skp->__sk_common.skc_dport); + FILTER_PORT + if (ipver == 4) { struct ipv4_data_t data4 = {.pid = pid, .ip = ipver}; data4.ts_us = bpf_ktime_get_ns() / 1000; @@ -148,10 +154,17 @@ int trace_connect_v6_return(struct pt_regs *ctx) # code substitutions if args.pid: - bpf_text = bpf_text.replace('FILTER', + bpf_text = bpf_text.replace('FILTER_PID', 'if (pid != %s) { return 0; }' % args.pid) -else: - bpf_text = bpf_text.replace('FILTER', '') +if args.port: + dports = [int(dport) for dport in args.port.split(',')] + dports_if = ' && '.join(['dport != %d' % ntohs(dport) for dport in dports]) + bpf_text = bpf_text.replace('FILTER_PORT', + 'if (%s) { currsock.delete(&pid); return 0; }' % dports_if) + +bpf_text = bpf_text.replace('FILTER_PID', '') +bpf_text = bpf_text.replace('FILTER_PORT', '') + if debug: print(bpf_text) diff --git a/tools/tcpconnect_example.txt b/tools/tcpconnect_example.txt index 4e6cf41..6d2f8f8 100644 --- a/tools/tcpconnect_example.txt +++ b/tools/tcpconnect_example.txt @@ -41,7 +41,7 @@ process to various other addresses. A few connections occur every minute. USAGE message: # ./tcpconnect -h -usage: tcpconnect [-h] [-t] [-p PID] +usage: tcpconnect [-h] [-t] [-p PID] [-P PORT] Trace TCP connects @@ -49,8 +49,12 @@ optional arguments: -h, --help show this help message and exit -t, --timestamp include timestamp on output -p PID, --pid PID trace this PID only + -P PORT, --port PORT + comma-separated list of destination ports to trace. examples: ./tcpconnect # trace all TCP connect()s ./tcpconnect -t # include timestamps ./tcpconnect -p 181 # only trace PID 181 + ./tcpconnect -P 80 # only trace port 80 + ./tcpconnect -P 80,81 # only trace port 80 and 81