xref: /aosp_15_r20/external/bcc/libbpf-tools/tcpconnect.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2020 Anton Protopopov
3*387f9dfdSAndroid Build Coastguard Worker //
4*387f9dfdSAndroid Build Coastguard Worker // Based on tcpconnect(8) from BCC by Brendan Gregg
5*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
6*387f9dfdSAndroid Build Coastguard Worker 
7*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
8*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_core_read.h>
9*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_tracing.h>
10*387f9dfdSAndroid Build Coastguard Worker 
11*387f9dfdSAndroid Build Coastguard Worker #include "maps.bpf.h"
12*387f9dfdSAndroid Build Coastguard Worker #include "tcpconnect.h"
13*387f9dfdSAndroid Build Coastguard Worker 
14*387f9dfdSAndroid Build Coastguard Worker const volatile int filter_ports[MAX_PORTS];
15*387f9dfdSAndroid Build Coastguard Worker const volatile int filter_ports_len = 0;
16*387f9dfdSAndroid Build Coastguard Worker const volatile uid_t filter_uid = -1;
17*387f9dfdSAndroid Build Coastguard Worker const volatile pid_t filter_pid = 0;
18*387f9dfdSAndroid Build Coastguard Worker const volatile bool do_count = 0;
19*387f9dfdSAndroid Build Coastguard Worker const volatile bool source_port = 0;
20*387f9dfdSAndroid Build Coastguard Worker 
21*387f9dfdSAndroid Build Coastguard Worker /* Define here, because there are conflicts with include files */
22*387f9dfdSAndroid Build Coastguard Worker #define AF_INET		2
23*387f9dfdSAndroid Build Coastguard Worker #define AF_INET6	10
24*387f9dfdSAndroid Build Coastguard Worker 
25*387f9dfdSAndroid Build Coastguard Worker struct {
26*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
27*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
28*387f9dfdSAndroid Build Coastguard Worker 	__type(key, u32);
29*387f9dfdSAndroid Build Coastguard Worker 	__type(value, struct sock *);
30*387f9dfdSAndroid Build Coastguard Worker } sockets SEC(".maps");
31*387f9dfdSAndroid Build Coastguard Worker 
32*387f9dfdSAndroid Build Coastguard Worker struct {
33*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
34*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
35*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct ipv4_flow_key);
36*387f9dfdSAndroid Build Coastguard Worker 	__type(value, u64);
37*387f9dfdSAndroid Build Coastguard Worker } ipv4_count SEC(".maps");
38*387f9dfdSAndroid Build Coastguard Worker 
39*387f9dfdSAndroid Build Coastguard Worker struct {
40*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
41*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
42*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct ipv6_flow_key);
43*387f9dfdSAndroid Build Coastguard Worker 	__type(value, u64);
44*387f9dfdSAndroid Build Coastguard Worker } ipv6_count SEC(".maps");
45*387f9dfdSAndroid Build Coastguard Worker 
46*387f9dfdSAndroid Build Coastguard Worker struct {
47*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
48*387f9dfdSAndroid Build Coastguard Worker 	__uint(key_size, sizeof(u32));
49*387f9dfdSAndroid Build Coastguard Worker 	__uint(value_size, sizeof(u32));
50*387f9dfdSAndroid Build Coastguard Worker } events SEC(".maps");
51*387f9dfdSAndroid Build Coastguard Worker 
filter_port(__u16 port)52*387f9dfdSAndroid Build Coastguard Worker static __always_inline bool filter_port(__u16 port)
53*387f9dfdSAndroid Build Coastguard Worker {
54*387f9dfdSAndroid Build Coastguard Worker 	int i;
55*387f9dfdSAndroid Build Coastguard Worker 
56*387f9dfdSAndroid Build Coastguard Worker 	if (filter_ports_len == 0)
57*387f9dfdSAndroid Build Coastguard Worker 		return false;
58*387f9dfdSAndroid Build Coastguard Worker 
59*387f9dfdSAndroid Build Coastguard Worker 	for (i = 0; i < filter_ports_len && i < MAX_PORTS; i++) {
60*387f9dfdSAndroid Build Coastguard Worker 		if (port == filter_ports[i])
61*387f9dfdSAndroid Build Coastguard Worker 			return false;
62*387f9dfdSAndroid Build Coastguard Worker 	}
63*387f9dfdSAndroid Build Coastguard Worker 	return true;
64*387f9dfdSAndroid Build Coastguard Worker }
65*387f9dfdSAndroid Build Coastguard Worker 
66*387f9dfdSAndroid Build Coastguard Worker static __always_inline int
enter_tcp_connect(struct pt_regs * ctx,struct sock * sk)67*387f9dfdSAndroid Build Coastguard Worker enter_tcp_connect(struct pt_regs *ctx, struct sock *sk)
68*387f9dfdSAndroid Build Coastguard Worker {
69*387f9dfdSAndroid Build Coastguard Worker 	__u64 pid_tgid = bpf_get_current_pid_tgid();
70*387f9dfdSAndroid Build Coastguard Worker 	__u32 pid = pid_tgid >> 32;
71*387f9dfdSAndroid Build Coastguard Worker 	__u32 tid = pid_tgid;
72*387f9dfdSAndroid Build Coastguard Worker 	__u32 uid;
73*387f9dfdSAndroid Build Coastguard Worker 
74*387f9dfdSAndroid Build Coastguard Worker 	if (filter_pid && pid != filter_pid)
75*387f9dfdSAndroid Build Coastguard Worker 		return 0;
76*387f9dfdSAndroid Build Coastguard Worker 
77*387f9dfdSAndroid Build Coastguard Worker 	uid = bpf_get_current_uid_gid();
78*387f9dfdSAndroid Build Coastguard Worker 	if (filter_uid != (uid_t) -1 && uid != filter_uid)
79*387f9dfdSAndroid Build Coastguard Worker 		return 0;
80*387f9dfdSAndroid Build Coastguard Worker 
81*387f9dfdSAndroid Build Coastguard Worker 	bpf_map_update_elem(&sockets, &tid, &sk, 0);
82*387f9dfdSAndroid Build Coastguard Worker 	return 0;
83*387f9dfdSAndroid Build Coastguard Worker }
84*387f9dfdSAndroid Build Coastguard Worker 
count_v4(struct sock * sk,__u16 sport,__u16 dport)85*387f9dfdSAndroid Build Coastguard Worker static  __always_inline void count_v4(struct sock *sk, __u16 sport, __u16 dport)
86*387f9dfdSAndroid Build Coastguard Worker {
87*387f9dfdSAndroid Build Coastguard Worker 	struct ipv4_flow_key key = {};
88*387f9dfdSAndroid Build Coastguard Worker 	static __u64 zero;
89*387f9dfdSAndroid Build Coastguard Worker 	__u64 *val;
90*387f9dfdSAndroid Build Coastguard Worker 
91*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&key.saddr, sk, __sk_common.skc_rcv_saddr);
92*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&key.daddr, sk, __sk_common.skc_daddr);
93*387f9dfdSAndroid Build Coastguard Worker 	key.sport = sport;
94*387f9dfdSAndroid Build Coastguard Worker 	key.dport = dport;
95*387f9dfdSAndroid Build Coastguard Worker 	val = bpf_map_lookup_or_try_init(&ipv4_count, &key, &zero);
96*387f9dfdSAndroid Build Coastguard Worker 	if (val)
97*387f9dfdSAndroid Build Coastguard Worker 		__atomic_add_fetch(val, 1, __ATOMIC_RELAXED);
98*387f9dfdSAndroid Build Coastguard Worker }
99*387f9dfdSAndroid Build Coastguard Worker 
count_v6(struct sock * sk,__u16 sport,__u16 dport)100*387f9dfdSAndroid Build Coastguard Worker static __always_inline void count_v6(struct sock *sk, __u16 sport, __u16 dport)
101*387f9dfdSAndroid Build Coastguard Worker {
102*387f9dfdSAndroid Build Coastguard Worker 	struct ipv6_flow_key key = {};
103*387f9dfdSAndroid Build Coastguard Worker 	static const __u64 zero;
104*387f9dfdSAndroid Build Coastguard Worker 	__u64 *val;
105*387f9dfdSAndroid Build Coastguard Worker 
106*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&key.saddr, sk,
107*387f9dfdSAndroid Build Coastguard Worker 			   __sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
108*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&key.daddr, sk,
109*387f9dfdSAndroid Build Coastguard Worker 			   __sk_common.skc_v6_daddr.in6_u.u6_addr32);
110*387f9dfdSAndroid Build Coastguard Worker 	key.sport = sport;
111*387f9dfdSAndroid Build Coastguard Worker 	key.dport = dport;
112*387f9dfdSAndroid Build Coastguard Worker 
113*387f9dfdSAndroid Build Coastguard Worker 	val = bpf_map_lookup_or_try_init(&ipv6_count, &key, &zero);
114*387f9dfdSAndroid Build Coastguard Worker 	if (val)
115*387f9dfdSAndroid Build Coastguard Worker 		__atomic_add_fetch(val, 1, __ATOMIC_RELAXED);
116*387f9dfdSAndroid Build Coastguard Worker }
117*387f9dfdSAndroid Build Coastguard Worker 
118*387f9dfdSAndroid Build Coastguard Worker static __always_inline void
trace_v4(struct pt_regs * ctx,pid_t pid,struct sock * sk,__u16 sport,__u16 dport)119*387f9dfdSAndroid Build Coastguard Worker trace_v4(struct pt_regs *ctx, pid_t pid, struct sock *sk, __u16 sport, __u16 dport)
120*387f9dfdSAndroid Build Coastguard Worker {
121*387f9dfdSAndroid Build Coastguard Worker 	struct event event = {};
122*387f9dfdSAndroid Build Coastguard Worker 
123*387f9dfdSAndroid Build Coastguard Worker 	event.af = AF_INET;
124*387f9dfdSAndroid Build Coastguard Worker 	event.pid = pid;
125*387f9dfdSAndroid Build Coastguard Worker 	event.uid = bpf_get_current_uid_gid();
126*387f9dfdSAndroid Build Coastguard Worker 	event.ts_us = bpf_ktime_get_ns() / 1000;
127*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&event.saddr_v4, sk, __sk_common.skc_rcv_saddr);
128*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&event.daddr_v4, sk, __sk_common.skc_daddr);
129*387f9dfdSAndroid Build Coastguard Worker 	event.sport = sport;
130*387f9dfdSAndroid Build Coastguard Worker 	event.dport = dport;
131*387f9dfdSAndroid Build Coastguard Worker 	bpf_get_current_comm(event.task, sizeof(event.task));
132*387f9dfdSAndroid Build Coastguard Worker 
133*387f9dfdSAndroid Build Coastguard Worker 	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU,
134*387f9dfdSAndroid Build Coastguard Worker 			      &event, sizeof(event));
135*387f9dfdSAndroid Build Coastguard Worker }
136*387f9dfdSAndroid Build Coastguard Worker 
137*387f9dfdSAndroid Build Coastguard Worker static __always_inline void
trace_v6(struct pt_regs * ctx,pid_t pid,struct sock * sk,__u16 sport,__u16 dport)138*387f9dfdSAndroid Build Coastguard Worker trace_v6(struct pt_regs *ctx, pid_t pid, struct sock *sk, __u16 sport, __u16 dport)
139*387f9dfdSAndroid Build Coastguard Worker {
140*387f9dfdSAndroid Build Coastguard Worker 	struct event event = {};
141*387f9dfdSAndroid Build Coastguard Worker 
142*387f9dfdSAndroid Build Coastguard Worker 	event.af = AF_INET6;
143*387f9dfdSAndroid Build Coastguard Worker 	event.pid = pid;
144*387f9dfdSAndroid Build Coastguard Worker 	event.uid = bpf_get_current_uid_gid();
145*387f9dfdSAndroid Build Coastguard Worker 	event.ts_us = bpf_ktime_get_ns() / 1000;
146*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&event.saddr_v6, sk,
147*387f9dfdSAndroid Build Coastguard Worker 			   __sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
148*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&event.daddr_v6, sk,
149*387f9dfdSAndroid Build Coastguard Worker 			   __sk_common.skc_v6_daddr.in6_u.u6_addr32);
150*387f9dfdSAndroid Build Coastguard Worker 	event.sport = sport;
151*387f9dfdSAndroid Build Coastguard Worker 	event.dport = dport;
152*387f9dfdSAndroid Build Coastguard Worker 	bpf_get_current_comm(event.task, sizeof(event.task));
153*387f9dfdSAndroid Build Coastguard Worker 
154*387f9dfdSAndroid Build Coastguard Worker 	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU,
155*387f9dfdSAndroid Build Coastguard Worker 			      &event, sizeof(event));
156*387f9dfdSAndroid Build Coastguard Worker }
157*387f9dfdSAndroid Build Coastguard Worker 
158*387f9dfdSAndroid Build Coastguard Worker static __always_inline int
exit_tcp_connect(struct pt_regs * ctx,int ret,int ip_ver)159*387f9dfdSAndroid Build Coastguard Worker exit_tcp_connect(struct pt_regs *ctx, int ret, int ip_ver)
160*387f9dfdSAndroid Build Coastguard Worker {
161*387f9dfdSAndroid Build Coastguard Worker 	__u64 pid_tgid = bpf_get_current_pid_tgid();
162*387f9dfdSAndroid Build Coastguard Worker 	__u32 pid = pid_tgid >> 32;
163*387f9dfdSAndroid Build Coastguard Worker 	__u32 tid = pid_tgid;
164*387f9dfdSAndroid Build Coastguard Worker 	struct sock **skpp;
165*387f9dfdSAndroid Build Coastguard Worker 	struct sock *sk;
166*387f9dfdSAndroid Build Coastguard Worker 	__u16 sport = 0;
167*387f9dfdSAndroid Build Coastguard Worker 	__u16 dport;
168*387f9dfdSAndroid Build Coastguard Worker 
169*387f9dfdSAndroid Build Coastguard Worker 	skpp = bpf_map_lookup_elem(&sockets, &tid);
170*387f9dfdSAndroid Build Coastguard Worker 	if (!skpp)
171*387f9dfdSAndroid Build Coastguard Worker 		return 0;
172*387f9dfdSAndroid Build Coastguard Worker 
173*387f9dfdSAndroid Build Coastguard Worker 	if (ret)
174*387f9dfdSAndroid Build Coastguard Worker 		goto end;
175*387f9dfdSAndroid Build Coastguard Worker 
176*387f9dfdSAndroid Build Coastguard Worker 	sk = *skpp;
177*387f9dfdSAndroid Build Coastguard Worker 
178*387f9dfdSAndroid Build Coastguard Worker 	if (source_port)
179*387f9dfdSAndroid Build Coastguard Worker 		BPF_CORE_READ_INTO(&sport, sk, __sk_common.skc_num);
180*387f9dfdSAndroid Build Coastguard Worker 	BPF_CORE_READ_INTO(&dport, sk, __sk_common.skc_dport);
181*387f9dfdSAndroid Build Coastguard Worker 
182*387f9dfdSAndroid Build Coastguard Worker 	if (filter_port(dport))
183*387f9dfdSAndroid Build Coastguard Worker 		goto end;
184*387f9dfdSAndroid Build Coastguard Worker 
185*387f9dfdSAndroid Build Coastguard Worker 	if (do_count) {
186*387f9dfdSAndroid Build Coastguard Worker 		if (ip_ver == 4)
187*387f9dfdSAndroid Build Coastguard Worker 			count_v4(sk, sport, dport);
188*387f9dfdSAndroid Build Coastguard Worker 		else
189*387f9dfdSAndroid Build Coastguard Worker 			count_v6(sk, sport, dport);
190*387f9dfdSAndroid Build Coastguard Worker 	} else {
191*387f9dfdSAndroid Build Coastguard Worker 		if (ip_ver == 4)
192*387f9dfdSAndroid Build Coastguard Worker 			trace_v4(ctx, pid, sk, sport, dport);
193*387f9dfdSAndroid Build Coastguard Worker 		else
194*387f9dfdSAndroid Build Coastguard Worker 			trace_v6(ctx, pid, sk, sport, dport);
195*387f9dfdSAndroid Build Coastguard Worker 	}
196*387f9dfdSAndroid Build Coastguard Worker 
197*387f9dfdSAndroid Build Coastguard Worker end:
198*387f9dfdSAndroid Build Coastguard Worker 	bpf_map_delete_elem(&sockets, &tid);
199*387f9dfdSAndroid Build Coastguard Worker 	return 0;
200*387f9dfdSAndroid Build Coastguard Worker }
201*387f9dfdSAndroid Build Coastguard Worker 
202*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/tcp_v4_connect")
BPF_KPROBE(tcp_v4_connect,struct sock * sk)203*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(tcp_v4_connect, struct sock *sk)
204*387f9dfdSAndroid Build Coastguard Worker {
205*387f9dfdSAndroid Build Coastguard Worker 	return enter_tcp_connect(ctx, sk);
206*387f9dfdSAndroid Build Coastguard Worker }
207*387f9dfdSAndroid Build Coastguard Worker 
208*387f9dfdSAndroid Build Coastguard Worker SEC("kretprobe/tcp_v4_connect")
BPF_KRETPROBE(tcp_v4_connect_ret,int ret)209*387f9dfdSAndroid Build Coastguard Worker int BPF_KRETPROBE(tcp_v4_connect_ret, int ret)
210*387f9dfdSAndroid Build Coastguard Worker {
211*387f9dfdSAndroid Build Coastguard Worker 	return exit_tcp_connect(ctx, ret, 4);
212*387f9dfdSAndroid Build Coastguard Worker }
213*387f9dfdSAndroid Build Coastguard Worker 
214*387f9dfdSAndroid Build Coastguard Worker SEC("kprobe/tcp_v6_connect")
BPF_KPROBE(tcp_v6_connect,struct sock * sk)215*387f9dfdSAndroid Build Coastguard Worker int BPF_KPROBE(tcp_v6_connect, struct sock *sk)
216*387f9dfdSAndroid Build Coastguard Worker {
217*387f9dfdSAndroid Build Coastguard Worker 	return enter_tcp_connect(ctx, sk);
218*387f9dfdSAndroid Build Coastguard Worker }
219*387f9dfdSAndroid Build Coastguard Worker 
220*387f9dfdSAndroid Build Coastguard Worker SEC("kretprobe/tcp_v6_connect")
BPF_KRETPROBE(tcp_v6_connect_ret,int ret)221*387f9dfdSAndroid Build Coastguard Worker int BPF_KRETPROBE(tcp_v6_connect_ret, int ret)
222*387f9dfdSAndroid Build Coastguard Worker {
223*387f9dfdSAndroid Build Coastguard Worker 	return exit_tcp_connect(ctx, ret, 6);
224*387f9dfdSAndroid Build Coastguard Worker }
225*387f9dfdSAndroid Build Coastguard Worker 
226*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
227