brintos

brintos / linux-shallow public Read only

0
0
Text · 9.9 KiB · f7b330d Raw
347 lines · c
1// SPDX-License-Identifier: GPL-2.02#define BPF_NO_KFUNC_PROTOTYPES3#include <vmlinux.h>4#include <bpf/bpf_helpers.h>5#include <bpf/bpf_endian.h>6 7#define EAFNOSUPPORT 978#define EPROTO 719#define ENONET 6410#define EINVAL 2211#define ENOENT 212 13#define NF_CT_ZONE_DIR_ORIG (1 << IP_CT_DIR_ORIGINAL)14#define NF_CT_ZONE_DIR_REPL (1 << IP_CT_DIR_REPLY)15 16extern unsigned long CONFIG_HZ __kconfig;17 18int test_einval_bpf_tuple = 0;19int test_einval_reserved = 0;20int test_einval_reserved_new = 0;21int test_einval_netns_id = 0;22int test_einval_len_opts = 0;23int test_eproto_l4proto = 0;24int test_enonet_netns_id = 0;25int test_enoent_lookup = 0;26int test_eafnosupport = 0;27int test_alloc_entry = -EINVAL;28int test_insert_entry = -EAFNOSUPPORT;29int test_succ_lookup = -ENOENT;30int test_ct_zone_id_alloc_entry = -EINVAL;31int test_ct_zone_id_insert_entry = -EAFNOSUPPORT;32int test_ct_zone_id_succ_lookup = -ENOENT;33int test_ct_zone_dir_enoent_lookup = 0;34int test_ct_zone_id_enoent_lookup = 0;35u32 test_delta_timeout = 0;36u32 test_status = 0;37u32 test_insert_lookup_mark = 0;38int test_snat_addr = -EINVAL;39int test_dnat_addr = -EINVAL;40__be32 saddr = 0;41__be16 sport = 0;42__be32 daddr = 0;43__be16 dport = 0;44int test_exist_lookup = -ENOENT;45u32 test_exist_lookup_mark = 0;46 47enum nf_nat_manip_type___local {48	NF_NAT_MANIP_SRC___local,49	NF_NAT_MANIP_DST___local50};51 52struct nf_conn;53 54struct bpf_ct_opts___local {55	s32 netns_id;56	s32 error;57	u8 l4proto;58	u8 dir;59	u8 reserved[2];60};61 62struct bpf_ct_opts___new {63	s32 netns_id;64	s32 error;65	u8 l4proto;66	u8 dir;67	u16 ct_zone_id;68	u8 ct_zone_dir;69	u8 reserved[3];70} __attribute__((preserve_access_index));71 72struct nf_conn *bpf_xdp_ct_alloc(struct xdp_md *, struct bpf_sock_tuple *, u32,73				 struct bpf_ct_opts___local *, u32) __ksym;74struct nf_conn *bpf_xdp_ct_lookup(struct xdp_md *, struct bpf_sock_tuple *, u32,75				  struct bpf_ct_opts___local *, u32) __ksym;76struct nf_conn *bpf_skb_ct_alloc(struct __sk_buff *, struct bpf_sock_tuple *, u32,77				 struct bpf_ct_opts___local *, u32) __ksym;78struct nf_conn *bpf_skb_ct_lookup(struct __sk_buff *, struct bpf_sock_tuple *, u32,79				  struct bpf_ct_opts___local *, u32) __ksym;80struct nf_conn *bpf_ct_insert_entry(struct nf_conn *) __ksym;81void bpf_ct_release(struct nf_conn *) __ksym;82void bpf_ct_set_timeout(struct nf_conn *, u32) __ksym;83int bpf_ct_change_timeout(struct nf_conn *, u32) __ksym;84int bpf_ct_set_status(struct nf_conn *, u32) __ksym;85int bpf_ct_change_status(struct nf_conn *, u32) __ksym;86int bpf_ct_set_nat_info(struct nf_conn *, union nf_inet_addr *,87			int port, enum nf_nat_manip_type___local) __ksym;88 89static __always_inline void90nf_ct_test(struct nf_conn *(*lookup_fn)(void *, struct bpf_sock_tuple *, u32,91					struct bpf_ct_opts___local *, u32),92	   struct nf_conn *(*alloc_fn)(void *, struct bpf_sock_tuple *, u32,93				       struct bpf_ct_opts___local *, u32),94	   void *ctx)95{96	struct bpf_ct_opts___local opts_def = { .l4proto = IPPROTO_TCP, .netns_id = -1 };97	struct bpf_sock_tuple bpf_tuple;98	struct nf_conn *ct;99 100	__builtin_memset(&bpf_tuple, 0, sizeof(bpf_tuple.ipv4));101 102	ct = lookup_fn(ctx, NULL, 0, &opts_def, sizeof(opts_def));103	if (ct)104		bpf_ct_release(ct);105	else106		test_einval_bpf_tuple = opts_def.error;107 108	opts_def.reserved[0] = 1;109	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,110		       sizeof(opts_def));111	opts_def.reserved[0] = 0;112	opts_def.l4proto = IPPROTO_TCP;113	if (ct)114		bpf_ct_release(ct);115	else116		test_einval_reserved = opts_def.error;117 118	opts_def.netns_id = -2;119	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,120		       sizeof(opts_def));121	opts_def.netns_id = -1;122	if (ct)123		bpf_ct_release(ct);124	else125		test_einval_netns_id = opts_def.error;126 127	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,128		       sizeof(opts_def) - 1);129	if (ct)130		bpf_ct_release(ct);131	else132		test_einval_len_opts = opts_def.error;133 134	opts_def.l4proto = IPPROTO_ICMP;135	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,136		       sizeof(opts_def));137	opts_def.l4proto = IPPROTO_TCP;138	if (ct)139		bpf_ct_release(ct);140	else141		test_eproto_l4proto = opts_def.error;142 143	opts_def.netns_id = 0xf00f;144	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,145		       sizeof(opts_def));146	opts_def.netns_id = -1;147	if (ct)148		bpf_ct_release(ct);149	else150		test_enonet_netns_id = opts_def.error;151 152	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,153		       sizeof(opts_def));154	if (ct)155		bpf_ct_release(ct);156	else157		test_enoent_lookup = opts_def.error;158 159	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4) - 1, &opts_def,160		       sizeof(opts_def));161	if (ct)162		bpf_ct_release(ct);163	else164		test_eafnosupport = opts_def.error;165 166	bpf_tuple.ipv4.saddr = bpf_get_prandom_u32(); /* src IP */167	bpf_tuple.ipv4.daddr = bpf_get_prandom_u32(); /* dst IP */168	bpf_tuple.ipv4.sport = bpf_get_prandom_u32(); /* src port */169	bpf_tuple.ipv4.dport = bpf_get_prandom_u32(); /* dst port */170 171	ct = alloc_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,172		      sizeof(opts_def));173	if (ct) {174		__u16 sport = bpf_get_prandom_u32();175		__u16 dport = bpf_get_prandom_u32();176		union nf_inet_addr saddr = {};177		union nf_inet_addr daddr = {};178		struct nf_conn *ct_ins;179 180		bpf_ct_set_timeout(ct, 10000);181		ct->mark = 77;182 183		/* snat */184		saddr.ip = bpf_get_prandom_u32();185		bpf_ct_set_nat_info(ct, &saddr, sport, NF_NAT_MANIP_SRC___local);186		/* dnat */187		daddr.ip = bpf_get_prandom_u32();188		bpf_ct_set_nat_info(ct, &daddr, dport, NF_NAT_MANIP_DST___local);189 190		ct_ins = bpf_ct_insert_entry(ct);191		if (ct_ins) {192			struct nf_conn *ct_lk;193 194			ct_lk = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4),195					  &opts_def, sizeof(opts_def));196			if (ct_lk) {197				struct nf_conntrack_tuple *tuple;198 199				/* check snat and dnat addresses */200				tuple = &ct_lk->tuplehash[IP_CT_DIR_REPLY].tuple;201				if (tuple->dst.u3.ip == saddr.ip &&202				    tuple->dst.u.all == bpf_htons(sport))203					test_snat_addr = 0;204				if (tuple->src.u3.ip == daddr.ip &&205				    tuple->src.u.all == bpf_htons(dport))206					test_dnat_addr = 0;207 208				/* update ct entry timeout */209				bpf_ct_change_timeout(ct_lk, 10000);210				test_delta_timeout = ct_lk->timeout - bpf_jiffies64();211				test_delta_timeout /= CONFIG_HZ;212				test_insert_lookup_mark = ct_lk->mark;213				bpf_ct_change_status(ct_lk,214						     IPS_CONFIRMED | IPS_SEEN_REPLY);215				test_status = ct_lk->status;216 217				bpf_ct_release(ct_lk);218				test_succ_lookup = 0;219			}220			bpf_ct_release(ct_ins);221			test_insert_entry = 0;222		}223		test_alloc_entry = 0;224	}225 226	bpf_tuple.ipv4.saddr = saddr;227	bpf_tuple.ipv4.daddr = daddr;228	bpf_tuple.ipv4.sport = sport;229	bpf_tuple.ipv4.dport = dport;230	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,231		       sizeof(opts_def));232	if (ct) {233		test_exist_lookup = 0;234		if (ct->mark == 42) {235			ct->mark++;236			test_exist_lookup_mark = ct->mark;237		}238		bpf_ct_release(ct);239	} else {240		test_exist_lookup = opts_def.error;241	}242}243 244static __always_inline void245nf_ct_opts_new_test(struct nf_conn *(*lookup_fn)(void *, struct bpf_sock_tuple *, u32,246						 struct bpf_ct_opts___new *, u32),247		    struct nf_conn *(*alloc_fn)(void *, struct bpf_sock_tuple *, u32,248						struct bpf_ct_opts___new *, u32),249		    void *ctx)250{251	struct bpf_ct_opts___new opts_def = { .l4proto = IPPROTO_TCP, .netns_id = -1 };252	struct bpf_sock_tuple bpf_tuple;253	struct nf_conn *ct;254 255	__builtin_memset(&bpf_tuple, 0, sizeof(bpf_tuple.ipv4));256 257	opts_def.reserved[0] = 1;258	ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,259		       sizeof(opts_def));260	opts_def.reserved[0] = 0;261	if (ct)262		bpf_ct_release(ct);263	else264		test_einval_reserved_new = opts_def.error;265 266	bpf_tuple.ipv4.saddr = bpf_get_prandom_u32(); /* src IP */267	bpf_tuple.ipv4.daddr = bpf_get_prandom_u32(); /* dst IP */268	bpf_tuple.ipv4.sport = bpf_get_prandom_u32(); /* src port */269	bpf_tuple.ipv4.dport = bpf_get_prandom_u32(); /* dst port */270 271	/* use non-default ct zone */272	opts_def.ct_zone_id = 10;273	opts_def.ct_zone_dir = NF_CT_ZONE_DIR_ORIG;274	ct = alloc_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,275		      sizeof(opts_def));276	if (ct) {277		__u16 sport = bpf_get_prandom_u32();278		__u16 dport = bpf_get_prandom_u32();279		union nf_inet_addr saddr = {};280		union nf_inet_addr daddr = {};281		struct nf_conn *ct_ins;282 283		bpf_ct_set_timeout(ct, 10000);284 285		/* snat */286		saddr.ip = bpf_get_prandom_u32();287		bpf_ct_set_nat_info(ct, &saddr, sport, NF_NAT_MANIP_SRC___local);288		/* dnat */289		daddr.ip = bpf_get_prandom_u32();290		bpf_ct_set_nat_info(ct, &daddr, dport, NF_NAT_MANIP_DST___local);291 292		ct_ins = bpf_ct_insert_entry(ct);293		if (ct_ins) {294			struct nf_conn *ct_lk;295 296			/* entry should exist in same ct zone we inserted it */297			ct_lk = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4),298					  &opts_def, sizeof(opts_def));299			if (ct_lk) {300				bpf_ct_release(ct_lk);301				test_ct_zone_id_succ_lookup = 0;302			}303 304			/* entry should not exist with wrong direction */305			opts_def.ct_zone_dir = NF_CT_ZONE_DIR_REPL;306			ct_lk = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4),307					  &opts_def, sizeof(opts_def));308			opts_def.ct_zone_dir = NF_CT_ZONE_DIR_ORIG;309			if (ct_lk)310				bpf_ct_release(ct_lk);311			else312				test_ct_zone_dir_enoent_lookup = opts_def.error;313 314			/* entry should not exist in default ct zone */315			opts_def.ct_zone_id = 0;316			ct_lk = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4),317					  &opts_def, sizeof(opts_def));318			if (ct_lk)319				bpf_ct_release(ct_lk);320			else321				test_ct_zone_id_enoent_lookup = opts_def.error;322 323			bpf_ct_release(ct_ins);324			test_ct_zone_id_insert_entry = 0;325		}326		test_ct_zone_id_alloc_entry = 0;327	}328}329 330SEC("xdp")331int nf_xdp_ct_test(struct xdp_md *ctx)332{333	nf_ct_test((void *)bpf_xdp_ct_lookup, (void *)bpf_xdp_ct_alloc, ctx);334	nf_ct_opts_new_test((void *)bpf_xdp_ct_lookup, (void *)bpf_xdp_ct_alloc, ctx);335	return 0;336}337 338SEC("tc")339int nf_skb_ct_test(struct __sk_buff *ctx)340{341	nf_ct_test((void *)bpf_skb_ct_lookup, (void *)bpf_skb_ct_alloc, ctx);342	nf_ct_opts_new_test((void *)bpf_skb_ct_lookup, (void *)bpf_skb_ct_alloc, ctx);343	return 0;344}345 346char _license[] SEC("license") = "GPL";347