1 // SPDX-License-Identifier: GPL-2.0 2 #include <vmlinux.h> 3 #include <bpf/bpf_helpers.h> 4 5 #define EAFNOSUPPORT 97 6 #define EPROTO 71 7 #define ENONET 64 8 #define EINVAL 22 9 #define ENOENT 2 10 11 int test_einval_bpf_tuple = 0; 12 int test_einval_reserved = 0; 13 int test_einval_netns_id = 0; 14 int test_einval_len_opts = 0; 15 int test_eproto_l4proto = 0; 16 int test_enonet_netns_id = 0; 17 int test_enoent_lookup = 0; 18 int test_eafnosupport = 0; 19 20 struct nf_conn; 21 22 struct bpf_ct_opts___local { 23 s32 netns_id; 24 s32 error; 25 u8 l4proto; 26 u8 reserved[3]; 27 } __attribute__((preserve_access_index)); 28 29 struct nf_conn *bpf_xdp_ct_lookup(struct xdp_md *, struct bpf_sock_tuple *, u32, 30 struct bpf_ct_opts___local *, u32) __ksym; 31 struct nf_conn *bpf_skb_ct_lookup(struct __sk_buff *, struct bpf_sock_tuple *, u32, 32 struct bpf_ct_opts___local *, u32) __ksym; 33 void bpf_ct_release(struct nf_conn *) __ksym; 34 35 static __always_inline void 36 nf_ct_test(struct nf_conn *(*func)(void *, struct bpf_sock_tuple *, u32, 37 struct bpf_ct_opts___local *, u32), 38 void *ctx) 39 { 40 struct bpf_ct_opts___local opts_def = { .l4proto = IPPROTO_TCP, .netns_id = -1 }; 41 struct bpf_sock_tuple bpf_tuple; 42 struct nf_conn *ct; 43 44 __builtin_memset(&bpf_tuple, 0, sizeof(bpf_tuple.ipv4)); 45 46 ct = func(ctx, NULL, 0, &opts_def, sizeof(opts_def)); 47 if (ct) 48 bpf_ct_release(ct); 49 else 50 test_einval_bpf_tuple = opts_def.error; 51 52 opts_def.reserved[0] = 1; 53 ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); 54 opts_def.reserved[0] = 0; 55 opts_def.l4proto = IPPROTO_TCP; 56 if (ct) 57 bpf_ct_release(ct); 58 else 59 test_einval_reserved = opts_def.error; 60 61 opts_def.netns_id = -2; 62 ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); 63 opts_def.netns_id = -1; 64 if (ct) 65 bpf_ct_release(ct); 66 else 67 test_einval_netns_id = opts_def.error; 68 69 ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def) - 1); 70 if (ct) 71 bpf_ct_release(ct); 72 else 73 test_einval_len_opts = opts_def.error; 74 75 opts_def.l4proto = IPPROTO_ICMP; 76 ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); 77 opts_def.l4proto = IPPROTO_TCP; 78 if (ct) 79 bpf_ct_release(ct); 80 else 81 test_eproto_l4proto = opts_def.error; 82 83 opts_def.netns_id = 0xf00f; 84 ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); 85 opts_def.netns_id = -1; 86 if (ct) 87 bpf_ct_release(ct); 88 else 89 test_enonet_netns_id = opts_def.error; 90 91 ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); 92 if (ct) 93 bpf_ct_release(ct); 94 else 95 test_enoent_lookup = opts_def.error; 96 97 ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4) - 1, &opts_def, sizeof(opts_def)); 98 if (ct) 99 bpf_ct_release(ct); 100 else 101 test_eafnosupport = opts_def.error; 102 } 103 104 SEC("xdp") 105 int nf_xdp_ct_test(struct xdp_md *ctx) 106 { 107 nf_ct_test((void *)bpf_xdp_ct_lookup, ctx); 108 return 0; 109 } 110 111 SEC("tc") 112 int nf_skb_ct_test(struct __sk_buff *ctx) 113 { 114 nf_ct_test((void *)bpf_skb_ct_lookup, ctx); 115 return 0; 116 } 117 118 char _license[] SEC("license") = "GPL"; 119