linux/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2018 Facebook
   3// Copyright (c) 2019 Cloudflare
   4
   5#include <string.h>
   6
   7#include <linux/bpf.h>
   8#include <linux/pkt_cls.h>
   9#include <linux/if_ether.h>
  10#include <linux/in.h>
  11#include <linux/ip.h>
  12#include <linux/ipv6.h>
  13#include <sys/socket.h>
  14#include <linux/tcp.h>
  15
  16#include "bpf_helpers.h"
  17#include "bpf_endian.h"
  18
  19struct bpf_map_def SEC("maps") results = {
  20        .type = BPF_MAP_TYPE_ARRAY,
  21        .key_size = sizeof(__u32),
  22        .value_size = sizeof(__u64),
  23        .max_entries = 1,
  24};
  25
  26static __always_inline void check_syncookie(void *ctx, void *data,
  27                                            void *data_end)
  28{
  29        struct bpf_sock_tuple tup;
  30        struct bpf_sock *sk;
  31        struct ethhdr *ethh;
  32        struct iphdr *ipv4h;
  33        struct ipv6hdr *ipv6h;
  34        struct tcphdr *tcph;
  35        int ret;
  36        __u32 key = 0;
  37        __u64 value = 1;
  38
  39        ethh = data;
  40        if (ethh + 1 > data_end)
  41                return;
  42
  43        switch (bpf_ntohs(ethh->h_proto)) {
  44        case ETH_P_IP:
  45                ipv4h = data + sizeof(struct ethhdr);
  46                if (ipv4h + 1 > data_end)
  47                        return;
  48
  49                if (ipv4h->ihl != 5)
  50                        return;
  51
  52                tcph = data + sizeof(struct ethhdr) + sizeof(struct iphdr);
  53                if (tcph + 1 > data_end)
  54                        return;
  55
  56                tup.ipv4.saddr = ipv4h->saddr;
  57                tup.ipv4.daddr = ipv4h->daddr;
  58                tup.ipv4.sport = tcph->source;
  59                tup.ipv4.dport = tcph->dest;
  60
  61                sk = bpf_skc_lookup_tcp(ctx, &tup, sizeof(tup.ipv4),
  62                                        BPF_F_CURRENT_NETNS, 0);
  63                if (!sk)
  64                        return;
  65
  66                if (sk->state != BPF_TCP_LISTEN)
  67                        goto release;
  68
  69                ret = bpf_tcp_check_syncookie(sk, ipv4h, sizeof(*ipv4h),
  70                                              tcph, sizeof(*tcph));
  71                break;
  72
  73        case ETH_P_IPV6:
  74                ipv6h = data + sizeof(struct ethhdr);
  75                if (ipv6h + 1 > data_end)
  76                        return;
  77
  78                if (ipv6h->nexthdr != IPPROTO_TCP)
  79                        return;
  80
  81                tcph = data + sizeof(struct ethhdr) + sizeof(struct ipv6hdr);
  82                if (tcph + 1 > data_end)
  83                        return;
  84
  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;
  89
  90                sk = bpf_skc_lookup_tcp(ctx, &tup, sizeof(tup.ipv6),
  91                                        BPF_F_CURRENT_NETNS, 0);
  92                if (!sk)
  93                        return;
  94
  95                if (sk->state != BPF_TCP_LISTEN)
  96                        goto release;
  97
  98                ret = bpf_tcp_check_syncookie(sk, ipv6h, sizeof(*ipv6h),
  99                                              tcph, sizeof(*tcph));
 100                break;
 101
 102        default:
 103                return;
 104        }
 105
 106        if (ret == 0)
 107                bpf_map_update_elem(&results, &key, &value, 0);
 108
 109release:
 110        bpf_sk_release(sk);
 111}
 112
 113SEC("clsact/check_syncookie")
 114int check_syncookie_clsact(struct __sk_buff *skb)
 115{
 116        check_syncookie(skb, (void *)(long)skb->data,
 117                        (void *)(long)skb->data_end);
 118        return TC_ACT_OK;
 119}
 120
 121SEC("xdp/check_syncookie")
 122int check_syncookie_xdp(struct xdp_md *ctx)
 123{
 124        check_syncookie(ctx, (void *)(long)ctx->data,
 125                        (void *)(long)ctx->data_end);
 126        return XDP_PASS;
 127}
 128
 129char _license[] SEC("license") = "GPL";
 130