1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Unstable XFRM state BPF helpers. 3 * 4 * Note that it is allowed to break compatibility for these functions since the 5 * interface they are exposed through to BPF programs is explicitly unstable. 6 */ 7 8 #include <linux/bpf.h> 9 #include <linux/btf.h> 10 #include <linux/btf_ids.h> 11 #include <net/xdp.h> 12 #include <net/xfrm.h> 13 14 /* bpf_xfrm_state_opts - Options for XFRM state lookup helpers 15 * 16 * Members: 17 * @error - Out parameter, set for any errors encountered 18 * Values: 19 * -EINVAL - netns_id is less than -1 20 * -EINVAL - opts__sz isn't BPF_XFRM_STATE_OPTS_SZ 21 * -ENONET - No network namespace found for netns_id 22 * -ENOENT - No xfrm_state found 23 * @netns_id - Specify the network namespace for lookup 24 * Values: 25 * BPF_F_CURRENT_NETNS (-1) 26 * Use namespace associated with ctx 27 * [0, S32_MAX] 28 * Network Namespace ID 29 * @mark - XFRM mark to match on 30 * @daddr - Destination address to match on 31 * @spi - Security parameter index to match on 32 * @proto - IP protocol to match on (eg. IPPROTO_ESP) 33 * @family - Protocol family to match on (AF_INET/AF_INET6) 34 */ 35 struct bpf_xfrm_state_opts { 36 s32 error; 37 s32 netns_id; 38 u32 mark; 39 xfrm_address_t daddr; 40 __be32 spi; 41 u8 proto; 42 u16 family; 43 }; 44 45 enum { 46 BPF_XFRM_STATE_OPTS_SZ = sizeof(struct bpf_xfrm_state_opts), 47 }; 48 49 __bpf_kfunc_start_defs(); 50 51 /* bpf_xdp_get_xfrm_state - Get XFRM state 52 * 53 * A `struct xfrm_state *`, if found, must be released with a corresponding 54 * bpf_xdp_xfrm_state_release. 55 * 56 * Parameters: 57 * @ctx - Pointer to ctx (xdp_md) in XDP program 58 * Cannot be NULL 59 * @opts - Options for lookup (documented above) 60 * Cannot be NULL 61 * @opts__sz - Length of the bpf_xfrm_state_opts structure 62 * Must be BPF_XFRM_STATE_OPTS_SZ 63 */ 64 __bpf_kfunc struct xfrm_state * 65 bpf_xdp_get_xfrm_state(struct xdp_md *ctx, struct bpf_xfrm_state_opts *opts, u32 opts__sz) 66 { 67 struct xdp_buff *xdp = (struct xdp_buff *)ctx; 68 struct net *net = dev_net(xdp->rxq->dev); 69 struct xfrm_state *x; 70 71 if (!opts || opts__sz < sizeof(opts->error)) 72 return NULL; 73 74 if (opts__sz != BPF_XFRM_STATE_OPTS_SZ) { 75 opts->error = -EINVAL; 76 return NULL; 77 } 78 79 if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) { 80 opts->error = -EINVAL; 81 return NULL; 82 } 83 84 if (opts->netns_id >= 0) { 85 net = get_net_ns_by_id(net, opts->netns_id); 86 if (unlikely(!net)) { 87 opts->error = -ENONET; 88 return NULL; 89 } 90 } 91 92 x = xfrm_state_lookup(net, opts->mark, &opts->daddr, opts->spi, 93 opts->proto, opts->family); 94 95 if (opts->netns_id >= 0) 96 put_net(net); 97 if (!x) 98 opts->error = -ENOENT; 99 100 return x; 101 } 102 103 /* bpf_xdp_xfrm_state_release - Release acquired xfrm_state object 104 * 105 * This must be invoked for referenced PTR_TO_BTF_ID, and the verifier rejects 106 * the program if any references remain in the program in all of the explored 107 * states. 108 * 109 * Parameters: 110 * @x - Pointer to referenced xfrm_state object, obtained using 111 * bpf_xdp_get_xfrm_state. 112 */ 113 __bpf_kfunc void bpf_xdp_xfrm_state_release(struct xfrm_state *x) 114 { 115 xfrm_state_put(x); 116 } 117 118 __bpf_kfunc_end_defs(); 119 120 BTF_SET8_START(xfrm_state_kfunc_set) 121 BTF_ID_FLAGS(func, bpf_xdp_get_xfrm_state, KF_RET_NULL | KF_ACQUIRE) 122 BTF_ID_FLAGS(func, bpf_xdp_xfrm_state_release, KF_RELEASE) 123 BTF_SET8_END(xfrm_state_kfunc_set) 124 125 static const struct btf_kfunc_id_set xfrm_state_xdp_kfunc_set = { 126 .owner = THIS_MODULE, 127 .set = &xfrm_state_kfunc_set, 128 }; 129 130 int __init register_xfrm_state_bpf(void) 131 { 132 return register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, 133 &xfrm_state_xdp_kfunc_set); 134 } 135