1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2020 Facebook
5 #include <bpf/bpf_endian.h>
6 #include <bpf/bpf_helpers.h>
8 #include <linux/if_ether.h>
10 #include <linux/in6.h>
11 #include <linux/ipv6.h>
12 #include <linux/tcp.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
17 int _version
SEC("version") = 1;
18 char _license
[] SEC("license") = "GPL";
20 __u16 g_serv_port
= 0;
22 static inline void set_ip(__u32
*dst
, const struct in6_addr
*src
)
24 dst
[0] = src
->in6_u
.u6_addr32
[0];
25 dst
[1] = src
->in6_u
.u6_addr32
[1];
26 dst
[2] = src
->in6_u
.u6_addr32
[2];
27 dst
[3] = src
->in6_u
.u6_addr32
[3];
30 static inline void set_tuple(struct bpf_sock_tuple
*tuple
,
31 const struct ipv6hdr
*ip6h
,
32 const struct tcphdr
*tcph
)
34 set_ip(tuple
->ipv6
.saddr
, &ip6h
->daddr
);
35 set_ip(tuple
->ipv6
.daddr
, &ip6h
->saddr
);
36 tuple
->ipv6
.sport
= tcph
->dest
;
37 tuple
->ipv6
.dport
= tcph
->source
;
40 static inline int is_allowed_peer_cg(struct __sk_buff
*skb
,
41 const struct ipv6hdr
*ip6h
,
42 const struct tcphdr
*tcph
)
44 __u64 cgid
, acgid
, peer_cgid
, peer_acgid
;
45 struct bpf_sock_tuple tuple
;
46 size_t tuple_len
= sizeof(tuple
.ipv6
);
47 struct bpf_sock
*peer_sk
;
49 set_tuple(&tuple
, ip6h
, tcph
);
51 peer_sk
= bpf_sk_lookup_tcp(skb
, &tuple
, tuple_len
,
52 BPF_F_CURRENT_NETNS
, 0);
56 cgid
= bpf_skb_cgroup_id(skb
);
57 peer_cgid
= bpf_sk_cgroup_id(peer_sk
);
59 acgid
= bpf_skb_ancestor_cgroup_id(skb
, 2);
60 peer_acgid
= bpf_sk_ancestor_cgroup_id(peer_sk
, 2);
62 bpf_sk_release(peer_sk
);
64 return cgid
&& cgid
== peer_cgid
&& acgid
&& acgid
== peer_acgid
;
67 SEC("cgroup_skb/ingress")
68 int ingress_lookup(struct __sk_buff
*skb
)
70 __u32 serv_port_key
= 0;
74 if (skb
->protocol
!= bpf_htons(ETH_P_IPV6
))
77 /* For SYN packets coming to listening socket skb->remote_port will be
78 * zero, so IPv6/TCP headers are loaded to identify remote peer
81 if (bpf_skb_load_bytes(skb
, 0, &ip6h
, sizeof(ip6h
)))
84 if (ip6h
.nexthdr
!= IPPROTO_TCP
)
87 if (bpf_skb_load_bytes(skb
, sizeof(ip6h
), &tcph
, sizeof(tcph
)))
93 if (tcph
.dest
!= g_serv_port
)
96 return is_allowed_peer_cg(skb
, &ip6h
, &tcph
);