1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019 Facebook */
5 #include <netinet/in.h>
8 #include "bpf_helpers.h"
9 #include "bpf_endian.h"
11 enum bpf_addr_array_idx {
14 __NR_BPF_ADDR_ARRAY_IDX,
17 enum bpf_result_array_idx {
21 __NR_BPF_RESULT_ARRAY_IDX,
24 enum bpf_linum_array_idx {
27 __NR_BPF_LINUM_ARRAY_IDX,
30 struct bpf_map_def SEC("maps") addr_map = {
31 .type = BPF_MAP_TYPE_ARRAY,
32 .key_size = sizeof(__u32),
33 .value_size = sizeof(struct sockaddr_in6),
34 .max_entries = __NR_BPF_ADDR_ARRAY_IDX,
37 struct bpf_map_def SEC("maps") sock_result_map = {
38 .type = BPF_MAP_TYPE_ARRAY,
39 .key_size = sizeof(__u32),
40 .value_size = sizeof(struct bpf_sock),
41 .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
44 struct bpf_map_def SEC("maps") tcp_sock_result_map = {
45 .type = BPF_MAP_TYPE_ARRAY,
46 .key_size = sizeof(__u32),
47 .value_size = sizeof(struct bpf_tcp_sock),
48 .max_entries = __NR_BPF_RESULT_ARRAY_IDX,
51 struct bpf_map_def SEC("maps") linum_map = {
52 .type = BPF_MAP_TYPE_ARRAY,
53 .key_size = sizeof(__u32),
54 .value_size = sizeof(__u32),
55 .max_entries = __NR_BPF_LINUM_ARRAY_IDX,
58 static bool is_loopback6(__u32 *a6)
60 return !a6[0] && !a6[1] && !a6[2] && a6[3] == bpf_htonl(1);
63 static void skcpy(struct bpf_sock *dst,
64 const struct bpf_sock *src)
66 dst->bound_dev_if = src->bound_dev_if;
67 dst->family = src->family;
68 dst->type = src->type;
69 dst->protocol = src->protocol;
70 dst->mark = src->mark;
71 dst->priority = src->priority;
72 dst->src_ip4 = src->src_ip4;
73 dst->src_ip6[0] = src->src_ip6[0];
74 dst->src_ip6[1] = src->src_ip6[1];
75 dst->src_ip6[2] = src->src_ip6[2];
76 dst->src_ip6[3] = src->src_ip6[3];
77 dst->src_port = src->src_port;
78 dst->dst_ip4 = src->dst_ip4;
79 dst->dst_ip6[0] = src->dst_ip6[0];
80 dst->dst_ip6[1] = src->dst_ip6[1];
81 dst->dst_ip6[2] = src->dst_ip6[2];
82 dst->dst_ip6[3] = src->dst_ip6[3];
83 dst->dst_port = src->dst_port;
84 dst->state = src->state;
87 static void tpcpy(struct bpf_tcp_sock *dst,
88 const struct bpf_tcp_sock *src)
90 dst->snd_cwnd = src->snd_cwnd;
91 dst->srtt_us = src->srtt_us;
92 dst->rtt_min = src->rtt_min;
93 dst->snd_ssthresh = src->snd_ssthresh;
94 dst->rcv_nxt = src->rcv_nxt;
95 dst->snd_nxt = src->snd_nxt;
96 dst->snd_una = src->snd_una;
97 dst->mss_cache = src->mss_cache;
98 dst->ecn_flags = src->ecn_flags;
99 dst->rate_delivered = src->rate_delivered;
100 dst->rate_interval_us = src->rate_interval_us;
101 dst->packets_out = src->packets_out;
102 dst->retrans_out = src->retrans_out;
103 dst->total_retrans = src->total_retrans;
104 dst->segs_in = src->segs_in;
105 dst->data_segs_in = src->data_segs_in;
106 dst->segs_out = src->segs_out;
107 dst->data_segs_out = src->data_segs_out;
108 dst->lost_out = src->lost_out;
109 dst->sacked_out = src->sacked_out;
110 dst->bytes_received = src->bytes_received;
111 dst->bytes_acked = src->bytes_acked;
116 bpf_map_update_elem(&linum_map, &linum_idx, &linum, 0); \
120 SEC("cgroup_skb/egress")
121 int egress_read_sock_fields(struct __sk_buff *skb)
123 __u32 srv_idx = ADDR_SRV_IDX, cli_idx = ADDR_CLI_IDX, result_idx;
124 struct sockaddr_in6 *srv_sa6, *cli_sa6;
125 struct bpf_tcp_sock *tp, *tp_ret;
126 struct bpf_sock *sk, *sk_ret;
127 __u32 linum, linum_idx;
129 linum_idx = EGRESS_LINUM_IDX;
132 if (!sk || sk->state == 10)
135 sk = bpf_sk_fullsock(sk);
136 if (!sk || sk->family != AF_INET6 || sk->protocol != IPPROTO_TCP ||
137 !is_loopback6(sk->src_ip6))
140 tp = bpf_tcp_sock(sk);
144 srv_sa6 = bpf_map_lookup_elem(&addr_map, &srv_idx);
145 cli_sa6 = bpf_map_lookup_elem(&addr_map, &cli_idx);
146 if (!srv_sa6 || !cli_sa6)
149 if (sk->src_port == bpf_ntohs(srv_sa6->sin6_port))
150 result_idx = EGRESS_SRV_IDX;
151 else if (sk->src_port == bpf_ntohs(cli_sa6->sin6_port))
152 result_idx = EGRESS_CLI_IDX;
156 sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx);
157 tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx);
158 if (!sk_ret || !tp_ret)
167 SEC("cgroup_skb/ingress")
168 int ingress_read_sock_fields(struct __sk_buff *skb)
170 __u32 srv_idx = ADDR_SRV_IDX, result_idx = INGRESS_LISTEN_IDX;
171 struct bpf_tcp_sock *tp, *tp_ret;
172 struct bpf_sock *sk, *sk_ret;
173 struct sockaddr_in6 *srv_sa6;
174 __u32 linum, linum_idx;
176 linum_idx = INGRESS_LINUM_IDX;
179 if (!sk || sk->family != AF_INET6 || !is_loopback6(sk->src_ip6))
182 srv_sa6 = bpf_map_lookup_elem(&addr_map, &srv_idx);
183 if (!srv_sa6 || sk->src_port != bpf_ntohs(srv_sa6->sin6_port))
186 if (sk->state != 10 && sk->state != 12)
189 sk = bpf_get_listener_sock(sk);
193 tp = bpf_tcp_sock(sk);
197 sk_ret = bpf_map_lookup_elem(&sock_result_map, &result_idx);
198 tp_ret = bpf_map_lookup_elem(&tcp_sock_result_map, &result_idx);
199 if (!sk_ret || !tp_ret)
208 char _license[] SEC("license") = "GPL";