npf_l2rule_test.c revision 1.3 1 1.1 joe /*
2 1.1 joe * NPF layer 2 ruleset tests.
3 1.1 joe *
4 1.1 joe * Public Domain.
5 1.1 joe */
6 1.1 joe
7 1.1 joe #ifdef _KERNEL
8 1.1 joe #include <sys/types.h>
9 1.1 joe #endif
10 1.1 joe
11 1.1 joe #include "npf_impl.h"
12 1.1 joe #include "npf_test.h"
13 1.1 joe
14 1.1 joe #define RESULT_PASS 0
15 1.1 joe #define RESULT_BLOCK ENETUNREACH
16 1.1 joe
17 1.1 joe static const struct test_case {
18 1.2 christos const char *src;
19 1.2 christos const char *dst;
20 1.2 christos uint16_t etype;
21 1.2 christos const char *ifname;
22 1.2 christos int di;
23 1.2 christos int ret;
24 1.1 joe } test_cases[] = {
25 1.1 joe {
26 1.1 joe /* pass ether in final from $mac1 to $mac2 type $E_IPv6 */
27 1.1 joe .src = "00:00:5E:00:53:00", .dst = "00:00:5E:00:53:01",
28 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_IPV6,
29 1.1 joe .di = PFIL_IN, .ret = RESULT_PASS
30 1.1 joe },
31 1.1 joe {
32 1.1 joe /* block ether in final from $mac2 */
33 1.1 joe .src = "00:00:5E:00:53:01", .dst = "00:00:5E:00:53:02",
34 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_IP,
35 1.1 joe .di = PFIL_IN, .ret = RESULT_BLOCK
36 1.1 joe },
37 1.1 joe
38 1.1 joe /* pass ether out final to $mac3 $Apple talk */
39 1.1 joe {
40 1.1 joe .src = "00:00:5E:00:53:00", .dst = "00:00:5E:00:53:02",
41 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_ATALK,
42 1.1 joe .di = PFIL_OUT, .ret = RESULT_PASS
43 1.1 joe },
44 1.1 joe {
45 1.1 joe /* goto default: block all (since direction is not matching ) */
46 1.1 joe .src = "00:00:5E:00:53:00", .dst = "00:00:5E:00:53:02",
47 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_IP,
48 1.1 joe .di = PFIL_IN, .ret = RESULT_BLOCK
49 1.1 joe },
50 1.3 joe {
51 1.3 joe /* pass from nested options : 03 */
52 1.3 joe .src = "00:00:5E:00:53:03", .dst = "00:00:5E:00:53:5A",
53 1.3 joe .ifname = IFNAME_INT, .etype = ETHERTYPE_IP,
54 1.3 joe .di = PFIL_IN, .ret = RESULT_PASS
55 1.3 joe },
56 1.3 joe {
57 1.3 joe /* pass from nested options : 04 */
58 1.3 joe .src = "00:00:5E:00:53:04", .dst = "00:00:5E:00:53:5A",
59 1.3 joe .ifname = IFNAME_INT, .etype = ETHERTYPE_IP,
60 1.3 joe .di = PFIL_IN, .ret = RESULT_PASS
61 1.3 joe },
62 1.3 joe {
63 1.3 joe /* pass from nested options : 04 */
64 1.3 joe .src = "00:00:5E:00:53:05", .dst = "00:00:5E:00:53:5A",
65 1.3 joe .ifname = IFNAME_INT, .etype = ETHERTYPE_IP,
66 1.3 joe .di = PFIL_IN, .ret = RESULT_PASS
67 1.3 joe },
68 1.1 joe };
69 1.1 joe
70 1.1 joe static int
71 1.1 joe run_raw_testcase(unsigned i)
72 1.1 joe {
73 1.1 joe const struct test_case *t = &test_cases[i];
74 1.1 joe npf_t *npf = npf_getkernctx();
75 1.1 joe npf_cache_t *npc;
76 1.1 joe struct mbuf *m;
77 1.1 joe npf_rule_t *rl;
78 1.1 joe int slock, error;
79 1.1 joe
80 1.2 christos m = mbuf_get_frame(t->src, t->dst, htons(t->etype));
81 1.1 joe npc = get_cached_pkt(m, t->ifname, NPF_RULE_LAYER_2);
82 1.1 joe
83 1.1 joe slock = npf_config_read_enter(npf);
84 1.1 joe rl = npf_ruleset_inspect(npc, npf_config_ruleset(npf), t->di, NPF_RULE_LAYER_2);
85 1.1 joe if (rl) {
86 1.1 joe npf_match_info_t mi;
87 1.1 joe error = npf_rule_conclude(rl, &mi);
88 1.1 joe } else {
89 1.1 joe error = ENOENT;
90 1.1 joe }
91 1.1 joe npf_config_read_exit(npf, slock);
92 1.1 joe
93 1.1 joe put_cached_pkt(npc);
94 1.1 joe return error;
95 1.1 joe }
96 1.1 joe
97 1.1 joe /* for dynamic testing */
98 1.1 joe static int
99 1.1 joe run_handler_testcase(unsigned i)
100 1.1 joe {
101 1.1 joe const struct test_case *t = &test_cases[i];
102 1.1 joe ifnet_t *ifp = npf_test_getif(t->ifname);
103 1.1 joe npf_t *npf = npf_getkernctx();
104 1.1 joe struct mbuf *m;
105 1.1 joe int error;
106 1.1 joe
107 1.2 christos m = mbuf_get_frame(t->src, t->dst, htons(t->etype));
108 1.1 joe error = npfk_layer2_handler(npf, &m, ifp, t->di);
109 1.1 joe if (m) {
110 1.1 joe m_freem(m);
111 1.1 joe }
112 1.1 joe return error;
113 1.1 joe }
114 1.1 joe
115 1.1 joe static npf_rule_t *
116 1.1 joe npf_blockall_rule(void)
117 1.1 joe {
118 1.1 joe npf_t *npf = npf_getkernctx();
119 1.1 joe nvlist_t *rule = nvlist_create(0);
120 1.1 joe npf_rule_t *rl;
121 1.1 joe
122 1.1 joe nvlist_add_number(rule, "attr",
123 1.1 joe NPF_RULE_IN | NPF_RULE_OUT | NPF_RULE_DYNAMIC | NPF_RULE_LAYER_2);
124 1.1 joe rl = npf_rule_alloc(npf, rule);
125 1.1 joe nvlist_destroy(rule);
126 1.1 joe return rl;
127 1.1 joe }
128 1.1 joe
129 1.1 joe static bool
130 1.1 joe test_static(bool verbose)
131 1.1 joe {
132 1.1 joe for (unsigned i = 0; i < __arraycount(test_cases); i++) {
133 1.1 joe const struct test_case *t = &test_cases[i];
134 1.1 joe int error;
135 1.1 joe
136 1.1 joe if (npf_test_getif(t->ifname) == NULL) {
137 1.1 joe printf("Interface %s is not configured.\n", t->ifname);
138 1.1 joe return false;
139 1.1 joe }
140 1.1 joe
141 1.1 joe error = run_handler_testcase(i);
142 1.1 joe
143 1.1 joe if (verbose) {
144 1.1 joe printf("rule test %d:\texpected %d\n"
145 1.1 joe "\t\t-> returned %d\n",
146 1.1 joe i + 1, t->ret, error);
147 1.1 joe }
148 1.1 joe CHECK_TRUE(error == t->ret);
149 1.1 joe }
150 1.1 joe return true;
151 1.1 joe }
152 1.1 joe
153 1.1 joe static bool
154 1.1 joe test_dynamic(void)
155 1.1 joe {
156 1.1 joe npf_t *npf = npf_getkernctx();
157 1.1 joe npf_ruleset_t *rlset;
158 1.1 joe npf_rule_t *rl;
159 1.1 joe uint64_t id;
160 1.1 joe int error;
161 1.1 joe
162 1.1 joe /*
163 1.1 joe * Test dynamic NPF rules.
164 1.1 joe */
165 1.1 joe
166 1.1 joe error = run_raw_testcase(0);
167 1.1 joe CHECK_TRUE(error == RESULT_PASS);
168 1.1 joe
169 1.1 joe npf_config_enter(npf);
170 1.1 joe rlset = npf_config_ruleset(npf);
171 1.1 joe
172 1.1 joe rl = npf_blockall_rule();
173 1.1 joe error = npf_ruleset_add(rlset, "l2-ruleset", rl);
174 1.1 joe CHECK_TRUE(error == 0);
175 1.1 joe
176 1.1 joe error = run_raw_testcase(0);
177 1.1 joe CHECK_TRUE(error == RESULT_BLOCK);
178 1.1 joe
179 1.1 joe id = npf_rule_getid(rl);
180 1.1 joe error = npf_ruleset_remove(rlset, "l2-ruleset", id);
181 1.1 joe CHECK_TRUE(error == 0);
182 1.1 joe
183 1.1 joe npf_config_exit(npf);
184 1.1 joe
185 1.1 joe error = run_raw_testcase(0);
186 1.1 joe CHECK_TRUE(error == RESULT_PASS);
187 1.1 joe
188 1.1 joe return true;
189 1.1 joe }
190 1.1 joe
191 1.1 joe bool
192 1.1 joe npf_layer2_rule_test(bool verbose)
193 1.1 joe {
194 1.1 joe bool ok;
195 1.1 joe
196 1.1 joe ok = test_static(verbose);
197 1.1 joe CHECK_TRUE(ok);
198 1.1 joe
199 1.1 joe ok = test_dynamic();
200 1.1 joe CHECK_TRUE(ok);
201 1.1 joe
202 1.1 joe return true;
203 1.1 joe }
204