1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <netinet/in.h>
4#include <linux/netfilter.h>
5
6#include "test_progs.h"
7#include "test_netfilter_link_attach.skel.h"
8
9struct nf_link_test {
10	__u32 pf;
11	__u32 hooknum;
12	__s32 priority;
13	__u32 flags;
14
15	bool expect_success;
16	const char * const name;
17};
18
19static const struct nf_link_test nf_hook_link_tests[] = {
20	{ .name = "allzero", },
21	{ .pf = NFPROTO_NUMPROTO, .name = "invalid-pf", },
22	{ .pf = NFPROTO_IPV4, .hooknum = 42, .name = "invalid-hooknum", },
23	{ .pf = NFPROTO_IPV4, .priority = INT_MIN, .name = "invalid-priority-min", },
24	{ .pf = NFPROTO_IPV4, .priority = INT_MAX, .name = "invalid-priority-max", },
25	{ .pf = NFPROTO_IPV4, .flags = UINT_MAX, .name = "invalid-flags", },
26
27	{ .pf = NFPROTO_INET, .priority = 1, .name = "invalid-inet-not-supported", },
28
29	{ .pf = NFPROTO_IPV4, .priority = -10000, .expect_success = true, .name = "attach ipv4", },
30	{ .pf = NFPROTO_IPV6, .priority =  10001, .expect_success = true, .name = "attach ipv6", },
31};
32
33void test_netfilter_link_attach(void)
34{
35	struct test_netfilter_link_attach *skel;
36	struct bpf_program *prog;
37	LIBBPF_OPTS(bpf_netfilter_opts, opts);
38	int i;
39
40	skel = test_netfilter_link_attach__open_and_load();
41	if (!ASSERT_OK_PTR(skel, "test_netfilter_link_attach__open_and_load"))
42		goto out;
43
44	prog = skel->progs.nf_link_attach_test;
45	if (!ASSERT_OK_PTR(prog, "attach program"))
46		goto out;
47
48	for (i = 0; i < ARRAY_SIZE(nf_hook_link_tests); i++) {
49		struct bpf_link *link;
50
51		if (!test__start_subtest(nf_hook_link_tests[i].name))
52			continue;
53
54#define X(opts, m, i)	opts.m = nf_hook_link_tests[(i)].m
55		X(opts, pf, i);
56		X(opts, hooknum, i);
57		X(opts, priority, i);
58		X(opts, flags, i);
59#undef X
60		link = bpf_program__attach_netfilter(prog, &opts);
61		if (nf_hook_link_tests[i].expect_success) {
62			struct bpf_link *link2;
63
64			if (!ASSERT_OK_PTR(link, "program attach successful"))
65				continue;
66
67			link2 = bpf_program__attach_netfilter(prog, &opts);
68			ASSERT_ERR_PTR(link2, "attach program with same pf/hook/priority");
69
70			if (!ASSERT_OK(bpf_link__destroy(link), "link destroy"))
71				break;
72
73			link2 = bpf_program__attach_netfilter(prog, &opts);
74			if (!ASSERT_OK_PTR(link2, "program reattach successful"))
75				continue;
76			if (!ASSERT_OK(bpf_link__destroy(link2), "link destroy"))
77				break;
78		} else {
79			ASSERT_ERR_PTR(link, "program load failure");
80		}
81	}
82
83out:
84	test_netfilter_link_attach__destroy(skel);
85}
86
87