inspektor-gadget

Форк
0
127 строк · 3.1 Кб
1
// SPDX-License-Identifier: GPL-2.0
2
// Copyright (c) 2022 Francis Laniel <flaniel@linux.microsoft.com>
3
#include <vmlinux.h>
4
#include <bpf/bpf_helpers.h>
5
#include <bpf/bpf_core_read.h>
6
#include <bpf/bpf_tracing.h>
7
#include <bpf/bpf_endian.h>
8

9
#include "tcptop.h"
10
#include <gadget/mntns_filter.h>
11

12
/* Taken from kernel include/linux/socket.h. */
13
#define AF_INET 2 /* Internet IP Protocol 	*/
14
#define AF_INET6 10 /* IP version 6			*/
15

16
const volatile pid_t target_pid = 0;
17
const volatile int target_family = -1;
18

19
struct {
20
	__uint(type, BPF_MAP_TYPE_HASH);
21
	__uint(max_entries, 10240);
22
	__type(key, struct ip_key_t);
23
	__type(value, struct traffic_t);
24
} ip_map SEC(".maps");
25

26
static int probe_ip(bool receiving, struct sock *sk, size_t size)
27
{
28
	struct ip_key_t ip_key = {};
29
	struct traffic_t *trafficp;
30
	u64 mntns_id;
31
	u16 family;
32
	u32 pid;
33

34
	pid = bpf_get_current_pid_tgid() >> 32;
35
	if (target_pid != 0 && target_pid != pid)
36
		return 0;
37

38
	family = BPF_CORE_READ(sk, __sk_common.skc_family);
39
	if (target_family != -1 && target_family != family)
40
		return 0;
41

42
	/* drop */
43
	if (family != AF_INET && family != AF_INET6)
44
		return 0;
45

46
	mntns_id = gadget_get_mntns_id();
47

48
	if (gadget_should_discard_mntns_id(mntns_id))
49
		return 0;
50

51
	ip_key.pid = pid;
52
	bpf_get_current_comm(&ip_key.name, sizeof(ip_key.name));
53
	ip_key.lport = BPF_CORE_READ(sk, __sk_common.skc_num);
54
	ip_key.dport = bpf_ntohs(BPF_CORE_READ(sk, __sk_common.skc_dport));
55
	ip_key.family = family;
56
	ip_key.mntnsid = mntns_id;
57

58
	if (family == AF_INET) {
59
		bpf_probe_read_kernel(&ip_key.saddr,
60
				      sizeof(sk->__sk_common.skc_rcv_saddr),
61
				      &sk->__sk_common.skc_rcv_saddr);
62
		bpf_probe_read_kernel(&ip_key.daddr,
63
				      sizeof(sk->__sk_common.skc_daddr),
64
				      &sk->__sk_common.skc_daddr);
65
	} else {
66
		/*
67
		 * family == AF_INET6,
68
		 * we already checked above family is correct.
69
		 */
70
		bpf_probe_read_kernel(
71
			&ip_key.saddr,
72
			sizeof(sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32),
73
			&sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
74
		bpf_probe_read_kernel(
75
			&ip_key.daddr,
76
			sizeof(sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32),
77
			&sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
78
	}
79

80
	trafficp = bpf_map_lookup_elem(&ip_map, &ip_key);
81
	if (!trafficp) {
82
		struct traffic_t zero;
83

84
		if (receiving) {
85
			zero.sent = 0;
86
			zero.received = size;
87
		} else {
88
			zero.sent = size;
89
			zero.received = 0;
90
		}
91

92
		bpf_map_update_elem(&ip_map, &ip_key, &zero, BPF_NOEXIST);
93
	} else {
94
		if (receiving)
95
			trafficp->received += size;
96
		else
97
			trafficp->sent += size;
98

99
		bpf_map_update_elem(&ip_map, &ip_key, trafficp, BPF_EXIST);
100
	}
101

102
	return 0;
103
}
104

105
SEC("kprobe/tcp_sendmsg")
106
int BPF_KPROBE(ig_toptcp_sdmsg, struct sock *sk, struct msghdr *msg,
107
	       size_t size)
108
{
109
	return probe_ip(false, sk, size);
110
}
111

112
/*
113
 * tcp_recvmsg() would be obvious to trace, but is less suitable because:
114
 * - we'd need to trace both entry and return, to have both sock and size
115
 * - misses tcp_read_sock() traffic
116
 * we'd much prefer tracepoints once they are available.
117
 */
118
SEC("kprobe/tcp_cleanup_rbuf")
119
int BPF_KPROBE(ig_toptcp_clean, struct sock *sk, int copied)
120
{
121
	if (copied <= 0)
122
		return 0;
123

124
	return probe_ip(true, sk, copied);
125
}
126

127
char LICENSE[] SEC("license") = "GPL";
128

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.