1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018 Facebook
3 // Copyright (c) 2019 Cloudflare
8 #include <linux/pkt_cls.h>
9 #include <linux/if_ether.h>
12 #include <linux/ipv6.h>
13 #include <sys/socket.h>
14 #include <linux/tcp.h>
16 #include "bpf_helpers.h"
17 #include "bpf_endian.h"
19 struct bpf_map_def
SEC("maps") results
= {
20 .type
= BPF_MAP_TYPE_ARRAY
,
21 .key_size
= sizeof(__u32
),
22 .value_size
= sizeof(__u64
),
26 static __always_inline
void check_syncookie(void *ctx
, void *data
,
29 struct bpf_sock_tuple tup
;
33 struct ipv6hdr
*ipv6h
;
40 if (ethh
+ 1 > data_end
)
43 switch (bpf_ntohs(ethh
->h_proto
)) {
45 ipv4h
= data
+ sizeof(struct ethhdr
);
46 if (ipv4h
+ 1 > data_end
)
52 tcph
= data
+ sizeof(struct ethhdr
) + sizeof(struct iphdr
);
53 if (tcph
+ 1 > data_end
)
56 tup
.ipv4
.saddr
= ipv4h
->saddr
;
57 tup
.ipv4
.daddr
= ipv4h
->daddr
;
58 tup
.ipv4
.sport
= tcph
->source
;
59 tup
.ipv4
.dport
= tcph
->dest
;
61 sk
= bpf_skc_lookup_tcp(ctx
, &tup
, sizeof(tup
.ipv4
),
62 BPF_F_CURRENT_NETNS
, 0);
66 if (sk
->state
!= BPF_TCP_LISTEN
)
69 ret
= bpf_tcp_check_syncookie(sk
, ipv4h
, sizeof(*ipv4h
),
74 ipv6h
= data
+ sizeof(struct ethhdr
);
75 if (ipv6h
+ 1 > data_end
)
78 if (ipv6h
->nexthdr
!= IPPROTO_TCP
)
81 tcph
= data
+ sizeof(struct ethhdr
) + sizeof(struct ipv6hdr
);
82 if (tcph
+ 1 > data_end
)
85 memcpy(tup
.ipv6
.saddr
, &ipv6h
->saddr
, sizeof(tup
.ipv6
.saddr
));
86 memcpy(tup
.ipv6
.daddr
, &ipv6h
->daddr
, sizeof(tup
.ipv6
.daddr
));
87 tup
.ipv6
.sport
= tcph
->source
;
88 tup
.ipv6
.dport
= tcph
->dest
;
90 sk
= bpf_skc_lookup_tcp(ctx
, &tup
, sizeof(tup
.ipv6
),
91 BPF_F_CURRENT_NETNS
, 0);
95 if (sk
->state
!= BPF_TCP_LISTEN
)
98 ret
= bpf_tcp_check_syncookie(sk
, ipv6h
, sizeof(*ipv6h
),
107 bpf_map_update_elem(&results
, &key
, &value
, 0);
113 SEC("clsact/check_syncookie")
114 int check_syncookie_clsact(struct __sk_buff
*skb
)
116 check_syncookie(skb
, (void *)(long)skb
->data
,
117 (void *)(long)skb
->data_end
);
121 SEC("xdp/check_syncookie")
122 int check_syncookie_xdp(struct xdp_md
*ctx
)
124 check_syncookie(ctx
, (void *)(long)ctx
->data
,
125 (void *)(long)ctx
->data_end
);
129 char _license
[] SEC("license") = "GPL";