Line data Source code
1 1 : /** @file
2 : * @brief Network packet filtering public header file
3 : *
4 : * The network packet filtering provides a mechanism for deciding the fate
5 : * of an incoming or outgoing packet based on a set of basic rules.
6 : */
7 :
8 : /*
9 : * Copyright (c) 2021 BayLibre SAS
10 : *
11 : * SPDX-License-Identifier: Apache-2.0
12 : */
13 :
14 : #ifndef ZEPHYR_INCLUDE_NET_PKT_FILTER_H_
15 : #define ZEPHYR_INCLUDE_NET_PKT_FILTER_H_
16 :
17 : #include <limits.h>
18 : #include <stdbool.h>
19 : #include <zephyr/sys/slist.h>
20 : #include <zephyr/net/net_core.h>
21 : #include <zephyr/net/ethernet.h>
22 :
23 : #ifdef __cplusplus
24 : extern "C" {
25 : #endif
26 :
27 : /**
28 : * @brief Network Packet Filter API
29 : * @defgroup net_pkt_filter Network Packet Filter API
30 : * @since 3.0
31 : * @version 0.8.0
32 : * @ingroup networking
33 : * @{
34 : */
35 :
36 : /** @cond INTERNAL_HIDDEN */
37 :
38 : struct npf_test;
39 :
40 : typedef bool (npf_test_fn_t)(struct npf_test *test, struct net_pkt *pkt);
41 :
42 : enum npf_test_type {
43 : NPF_TEST_TYPE_UNKNOWN = 0,
44 : NPF_TEST_TYPE_IFACE_MATCH,
45 : NPF_TEST_TYPE_IFACE_UNMATCH,
46 : NPF_TEST_TYPE_ORIG_IFACE_MATCH,
47 : NPF_TEST_TYPE_ORIG_IFACE_UNMATCH,
48 : NPF_TEST_TYPE_SIZE_MIN,
49 : NPF_TEST_TYPE_SIZE_MAX,
50 : NPF_TEST_TYPE_SIZE_BOUNDS,
51 : NPF_TEST_TYPE_IP_SRC_ADDR_ALLOWLIST,
52 : NPF_TEST_TYPE_IP_SRC_ADDR_BLOCKLIST,
53 : NPF_TEST_TYPE_ETH_SRC_ADDR_MATCH,
54 : NPF_TEST_TYPE_ETH_SRC_ADDR_UNMATCH,
55 : NPF_TEST_TYPE_ETH_DST_ADDR_MATCH,
56 : NPF_TEST_TYPE_ETH_DST_ADDR_UNMATCH,
57 : NPF_TEST_TYPE_ETH_SRC_ADDR_MASK_MATCH,
58 : NPF_TEST_TYPE_ETH_DST_ADDR_MASK_MATCH,
59 : NPF_TEST_TYPE_ETH_TYPE_MATCH,
60 : NPF_TEST_TYPE_ETH_TYPE_UNMATCH,
61 : NPF_TEST_TYPE_ETH_VLAN_TYPE_MATCH,
62 : NPF_TEST_TYPE_ETH_VLAN_TYPE_UNMATCH,
63 : };
64 :
65 : #if defined(CONFIG_NET_PKT_FILTER_LOG_LEVEL_DBG) || \
66 : defined(CONFIG_NET_SHELL_PKT_FILTER_SUPPORTED)
67 : #define NPF_TEST_ENABLE_NAME 1
68 : #elif defined(NPF_TEST_ENABLE_NAME)
69 : #undef NPF_TEST_ENABLE_NAME
70 : #endif
71 :
72 : /** @endcond */
73 :
74 : /** @brief common filter test structure to be embedded into larger structures */
75 1 : struct npf_test {
76 1 : npf_test_fn_t *fn; /**< packet condition test function */
77 :
78 : /** @cond INTERNAL_HIDDEN */
79 : IF_ENABLED(NPF_TEST_ENABLE_NAME,
80 : (const char *name;)) /**< Name of the test */
81 : IF_ENABLED(NPF_TEST_ENABLE_NAME,
82 : (enum npf_test_type type;)) /**< Type of the test */
83 : /** @endcond */
84 : };
85 :
86 : /** @brief filter rule structure */
87 1 : struct npf_rule {
88 1 : sys_snode_t node; /**< Slist rule list node */
89 1 : enum net_verdict result; /**< result if all tests pass */
90 1 : uint32_t nb_tests; /**< number of tests for this rule */
91 1 : struct npf_test *tests[]; /**< pointers to @ref npf_test instances */
92 : };
93 :
94 : /** @brief Default rule list termination for accepting a packet */
95 1 : extern struct npf_rule npf_default_ok;
96 : /** @brief Default rule list termination for rejecting a packet */
97 1 : extern struct npf_rule npf_default_drop;
98 :
99 : /** @brief rule set for a given test location */
100 1 : struct npf_rule_list {
101 1 : sys_slist_t rule_head; /**< List head */
102 1 : struct k_spinlock lock; /**< Lock protecting the list access */
103 : };
104 :
105 : /** @brief rule list applied to outgoing packets */
106 1 : extern struct npf_rule_list npf_send_rules;
107 : /** @brief rule list applied to incoming packets */
108 1 : extern struct npf_rule_list npf_recv_rules;
109 : /** @brief rule list applied for local incoming packets */
110 1 : extern struct npf_rule_list npf_local_in_recv_rules;
111 : /** @brief rule list applied for IPv4 incoming packets */
112 1 : extern struct npf_rule_list npf_ipv4_recv_rules;
113 : /** @brief rule list applied for IPv6 incoming packets */
114 1 : extern struct npf_rule_list npf_ipv6_recv_rules;
115 :
116 : /**
117 : * @brief Insert a rule at the front of given rule list
118 : *
119 : * @param rules the affected rule list
120 : * @param rule the rule to be inserted
121 : */
122 1 : void npf_insert_rule(struct npf_rule_list *rules, struct npf_rule *rule);
123 :
124 : /**
125 : * @brief Append a rule at the end of given rule list
126 : *
127 : * @param rules the affected rule list
128 : * @param rule the rule to be appended
129 : */
130 1 : void npf_append_rule(struct npf_rule_list *rules, struct npf_rule *rule);
131 :
132 : /**
133 : * @brief Remove a rule from the given rule list
134 : *
135 : * @param rules the affected rule list
136 : * @param rule the rule to be removed
137 : * @retval true if given rule was found in the rule list and removed
138 : */
139 1 : bool npf_remove_rule(struct npf_rule_list *rules, struct npf_rule *rule);
140 :
141 : /**
142 : * @brief Remove all rules from the given rule list
143 : *
144 : * @param rules the affected rule list
145 : * @retval true if at least one rule was removed from the rule list
146 : */
147 1 : bool npf_remove_all_rules(struct npf_rule_list *rules);
148 :
149 : /** @cond INTERNAL_HIDDEN */
150 :
151 : /* convenience shortcuts */
152 : #define npf_insert_send_rule(rule) npf_insert_rule(&npf_send_rules, rule)
153 : #define npf_insert_recv_rule(rule) npf_insert_rule(&npf_recv_rules, rule)
154 : #define npf_append_send_rule(rule) npf_append_rule(&npf_send_rules, rule)
155 : #define npf_append_recv_rule(rule) npf_append_rule(&npf_recv_rules, rule)
156 : #define npf_remove_send_rule(rule) npf_remove_rule(&npf_send_rules, rule)
157 : #define npf_remove_recv_rule(rule) npf_remove_rule(&npf_recv_rules, rule)
158 : #define npf_remove_all_send_rules() npf_remove_all_rules(&npf_send_rules)
159 : #define npf_remove_all_recv_rules() npf_remove_all_rules(&npf_recv_rules)
160 :
161 : #ifdef CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK
162 : #define npf_insert_local_in_recv_rule(rule) npf_insert_rule(&npf_local_in_recv_rules, rule)
163 : #define npf_append_local_in_recv_rule(rule) npf_append_rule(&npf_local_in_recv_rules, rule)
164 : #define npf_remove_local_in_recv_rule(rule) npf_remove_rule(&npf_local_in_recv_rules, rule)
165 : #define npf_remove_all_local_in_recv_rules() npf_remove_all_rules(&npf_local_in_recv_rules)
166 : #endif /* CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK */
167 :
168 : #ifdef CONFIG_NET_PKT_FILTER_IPV4_HOOK
169 : #define npf_insert_ipv4_recv_rule(rule) npf_insert_rule(&npf_ipv4_recv_rules, rule)
170 : #define npf_append_ipv4_recv_rule(rule) npf_append_rule(&npf_ipv4_recv_rules, rule)
171 : #define npf_remove_ipv4_recv_rule(rule) npf_remove_rule(&npf_ipv4_recv_rules, rule)
172 : #define npf_remove_all_ipv4_recv_rules() npf_remove_all_rules(&npf_ipv4_recv_rules)
173 : #endif /* CONFIG_NET_PKT_FILTER_IPV4_HOOK */
174 :
175 : #ifdef CONFIG_NET_PKT_FILTER_IPV6_HOOK
176 : #define npf_insert_ipv6_recv_rule(rule) npf_insert_rule(&npf_ipv6_recv_rules, rule)
177 : #define npf_append_ipv6_recv_rule(rule) npf_append_rule(&npf_ipv6_recv_rules, rule)
178 : #define npf_remove_ipv6_recv_rule(rule) npf_remove_rule(&npf_ipv6_recv_rules, rule)
179 : #define npf_remove_all_ipv6_recv_rules() npf_remove_all_rules(&npf_ipv6_recv_rules)
180 : #endif /* CONFIG_NET_PKT_FILTER_IPV6_HOOK */
181 :
182 : /** @endcond */
183 :
184 : /**
185 : * @brief Statically define one packet filter rule
186 : *
187 : * This creates a rule from a variable amount of filter conditions.
188 : * This rule can then be inserted or appended to the rule list for a given
189 : * network packet path.
190 : *
191 : * Example:
192 : *
193 : * @code{.c}
194 : *
195 : * static NPF_SIZE_MAX(maxsize_200, 200);
196 : * static NPF_ETH_TYPE_MATCH(ip_packet, NET_ETH_PTYPE_IP);
197 : *
198 : * static NPF_RULE(small_ip_pkt, NET_OK, ip_packet, maxsize_200);
199 : *
200 : * void install_my_filter(void)
201 : * {
202 : * npf_insert_recv_rule(&npf_default_drop);
203 : * npf_insert_recv_rule(&small_ip_pkt);
204 : * }
205 : *
206 : * @endcode
207 : *
208 : * The above would accept IP packets that are 200 bytes or smaller, and drop
209 : * all other packets.
210 : *
211 : * Another (less efficient) way to create the same result could be:
212 : *
213 : * @code{.c}
214 : *
215 : * static NPF_SIZE_MIN(minsize_201, 201);
216 : * static NPF_ETH_TYPE_UNMATCH(not_ip_packet, NET_ETH_PTYPE_IP);
217 : *
218 : * static NPF_RULE(reject_big_pkts, NET_DROP, minsize_201);
219 : * static NPF_RULE(reject_non_ip, NET_DROP, not_ip_packet);
220 : *
221 : * void install_my_filter(void) {
222 : * npf_append_recv_rule(&reject_big_pkts);
223 : * npf_append_recv_rule(&reject_non_ip);
224 : * npf_append_recv_rule(&npf_default_ok);
225 : * }
226 : *
227 : * @endcode
228 : *
229 : * The first rule in the list for which all conditions are true determines
230 : * the fate of the packet. If one condition is false then the next rule in
231 : * the list is evaluated.
232 : *
233 : * @param _name Name for this rule.
234 : * @param _result Fate of the packet if all conditions are true, either
235 : * <tt>NET_OK</tt> or <tt>NET_DROP</tt>.
236 : * @param ... List of conditions for this rule.
237 : */
238 1 : #define NPF_RULE(_name, _result, ...) \
239 : struct npf_rule _name = { \
240 : .result = (_result), \
241 : .nb_tests = NUM_VA_ARGS_LESS_1(__VA_ARGS__) + 1, \
242 : .tests = { FOR_EACH(Z_NPF_TEST_ADDR, (,), __VA_ARGS__) }, \
243 : }
244 :
245 : #define Z_NPF_TEST_ADDR(arg) &arg.test
246 :
247 : /** @} */
248 :
249 : /**
250 : * @defgroup npf_basic_cond Basic Filter Conditions
251 : * @since 3.0
252 : * @version 0.8.0
253 : * @ingroup net_pkt_filter
254 : * @{
255 : */
256 :
257 : /** @cond INTERNAL_HIDDEN */
258 :
259 : struct npf_test_iface {
260 : struct npf_test test;
261 : struct net_if *iface;
262 : };
263 :
264 : extern npf_test_fn_t npf_iface_match;
265 : extern npf_test_fn_t npf_iface_unmatch;
266 : extern npf_test_fn_t npf_orig_iface_match;
267 : extern npf_test_fn_t npf_orig_iface_unmatch;
268 :
269 : /** @endcond */
270 :
271 : /**
272 : * @brief Statically define an "interface match" packet filter condition
273 : *
274 : * @param _name Name of the condition
275 : * @param _iface Interface to match
276 : */
277 1 : #define NPF_IFACE_MATCH(_name, _iface) \
278 : struct npf_test_iface _name = { \
279 : .iface = (_iface), \
280 : .test.fn = npf_iface_match, \
281 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
282 : (.test.name = "iface", \
283 : .test.type = NPF_TEST_TYPE_IFACE_MATCH,)) \
284 : }
285 :
286 : /**
287 : * @brief Statically define an "interface unmatch" packet filter condition
288 : *
289 : * @param _name Name of the condition
290 : * @param _iface Interface to exclude
291 : */
292 1 : #define NPF_IFACE_UNMATCH(_name, _iface) \
293 : struct npf_test_iface _name = { \
294 : .iface = (_iface), \
295 : .test.fn = npf_iface_unmatch, \
296 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
297 : (.test.name = "!iface", \
298 : .test.type = NPF_TEST_TYPE_IFACE_UNMATCH,)) \
299 : }
300 :
301 : /**
302 : * @brief Statically define an "orig interface match" packet filter condition
303 : *
304 : * @param _name Name of the condition
305 : * @param _iface Interface to match
306 : */
307 1 : #define NPF_ORIG_IFACE_MATCH(_name, _iface) \
308 : struct npf_test_iface _name = { \
309 : .iface = (_iface), \
310 : .test.fn = npf_orig_iface_match, \
311 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
312 : (.test.name = "orig iface", \
313 : .test.type = NPF_TEST_TYPE_ORIG_IFACE_MATCH,)) \
314 : }
315 :
316 : /**
317 : * @brief Statically define an "orig interface unmatch" packet filter condition
318 : *
319 : * @param _name Name of the condition
320 : * @param _iface Interface to exclude
321 : */
322 1 : #define NPF_ORIG_IFACE_UNMATCH(_name, _iface) \
323 : struct npf_test_iface _name = { \
324 : .iface = (_iface), \
325 : .test.fn = npf_orig_iface_unmatch, \
326 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
327 : (.test.name = "!orig iface", \
328 : .test.type = NPF_TEST_TYPE_ORIG_IFACE_UNMATCH,)) \
329 : }
330 :
331 : /** @cond INTERNAL_HIDDEN */
332 :
333 : struct npf_test_size_bounds {
334 : struct npf_test test;
335 : size_t min;
336 : size_t max;
337 : };
338 :
339 : extern npf_test_fn_t npf_size_inbounds;
340 :
341 : /** @endcond */
342 :
343 : /**
344 : * @brief Statically define a "data minimum size" packet filter condition
345 : *
346 : * @param _name Name of the condition
347 : * @param _size Lower bound of the packet's data size
348 : */
349 1 : #define NPF_SIZE_MIN(_name, _size) \
350 : struct npf_test_size_bounds _name = { \
351 : .min = (_size), \
352 : .max = SIZE_MAX, \
353 : .test.fn = npf_size_inbounds, \
354 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
355 : (.test.name = "size min", \
356 : .test.type = NPF_TEST_TYPE_SIZE_MIN,)) \
357 : }
358 :
359 : /**
360 : * @brief Statically define a "data maximum size" packet filter condition
361 : *
362 : * @param _name Name of the condition
363 : * @param _size Higher bound of the packet's data size
364 : */
365 1 : #define NPF_SIZE_MAX(_name, _size) \
366 : struct npf_test_size_bounds _name = { \
367 : .min = 0, \
368 : .max = (_size), \
369 : .test.fn = npf_size_inbounds, \
370 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
371 : (.test.name = "size max", \
372 : .test.type = NPF_TEST_TYPE_SIZE_MAX,)) \
373 : }
374 :
375 : /**
376 : * @brief Statically define a "data bounded size" packet filter condition
377 : *
378 : * @param _name Name of the condition
379 : * @param _min_size Lower bound of the packet's data size
380 : * @param _max_size Higher bound of the packet's data size
381 : */
382 1 : #define NPF_SIZE_BOUNDS(_name, _min_size, _max_size) \
383 : struct npf_test_size_bounds _name = { \
384 : .min = (_min_size), \
385 : .max = (_max_size), \
386 : .test.fn = npf_size_inbounds, \
387 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
388 : (.test.name = "size bounds", \
389 : .test.type = NPF_TEST_TYPE_SIZE_BOUNDS,)) \
390 : }
391 :
392 : /** @cond INTERNAL_HIDDEN */
393 :
394 : struct npf_test_ip {
395 : struct npf_test test;
396 : uint8_t addr_family;
397 : void *ipaddr;
398 : uint32_t ipaddr_num;
399 : };
400 :
401 : extern npf_test_fn_t npf_ip_src_addr_match;
402 : extern npf_test_fn_t npf_ip_src_addr_unmatch;
403 :
404 : /** @endcond */
405 :
406 : /**
407 : * @brief Statically define a "ip address allowlist" packet filter condition
408 : *
409 : * This tests if the packet source ip address matches any of the ip
410 : * addresses contained in the provided set.
411 : *
412 : * @param _name Name of the condition
413 : * @param _ip_addr_array Array of <tt>struct in_addr</tt> or <tt>struct in6_addr</tt> items to test
414 : *against
415 : * @param _ip_addr_num number of IP addresses in the array
416 : * @param _af Addresses family type (AF_INET / AF_INET6) in the array
417 : */
418 1 : #define NPF_IP_SRC_ADDR_ALLOWLIST(_name, _ip_addr_array, _ip_addr_num, _af) \
419 : struct npf_test_ip _name = { \
420 : .addr_family = _af, \
421 : .ipaddr = (_ip_addr_array), \
422 : .ipaddr_num = _ip_addr_num, \
423 : .test.fn = npf_ip_src_addr_match, \
424 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
425 : (.test.name = "ip src allow", \
426 : .test.type = NPF_TEST_TYPE_IP_SRC_ADDR_ALLOWLIST,)) \
427 : }
428 :
429 : /**
430 : * @brief Statically define a "ip address blocklist" packet filter condition
431 : *
432 : * This tests if the packet source ip address matches any of the ip
433 : * addresses contained in the provided set.
434 : *
435 : * @param _name Name of the condition
436 : * @param _ip_addr_array Array of <tt>struct in_addr</tt> or <tt>struct in6_addr</tt> items to test
437 : *against
438 : * @param _ip_addr_num number of IP addresses in the array
439 : * @param _af Addresses family type (AF_INET / AF_INET6) in the array
440 : */
441 1 : #define NPF_IP_SRC_ADDR_BLOCKLIST(_name, _ip_addr_array, _ip_addr_num, _af) \
442 : struct npf_test_ip _name = { \
443 : .addr_family = _af, \
444 : .ipaddr = (_ip_addr_array), \
445 : .ipaddr_num = _ip_addr_num, \
446 : .test.fn = npf_ip_src_addr_unmatch, \
447 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
448 : (.test.name = "ip src block", \
449 : .test.type = NPF_TEST_TYPE_IP_SRC_ADDR_BLOCKLIST,)) \
450 : }
451 :
452 : /** @} */
453 :
454 : /**
455 : * @defgroup npf_eth_cond Ethernet Filter Conditions
456 : * @ingroup net_pkt_filter
457 : * @since 3.0
458 : * @version 0.8.0
459 : * @{
460 : */
461 :
462 : /** @cond INTERNAL_HIDDEN */
463 :
464 : struct npf_test_eth_addr {
465 : struct npf_test test;
466 : unsigned int nb_addresses;
467 : struct net_eth_addr *addresses;
468 : struct net_eth_addr mask;
469 : };
470 :
471 : extern npf_test_fn_t npf_eth_src_addr_match;
472 : extern npf_test_fn_t npf_eth_src_addr_unmatch;
473 : extern npf_test_fn_t npf_eth_dst_addr_match;
474 : extern npf_test_fn_t npf_eth_dst_addr_unmatch;
475 :
476 : /** @endcond */
477 :
478 : /**
479 : * @brief Statically define a "source address match" packet filter condition
480 : *
481 : * This tests if the packet source address matches any of the Ethernet
482 : * addresses contained in the provided set.
483 : *
484 : * @param _name Name of the condition
485 : * @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
486 : */
487 1 : #define NPF_ETH_SRC_ADDR_MATCH(_name, _addr_array) \
488 : struct npf_test_eth_addr _name = { \
489 : .addresses = (_addr_array), \
490 : .nb_addresses = ARRAY_SIZE(_addr_array), \
491 : .test.fn = npf_eth_src_addr_match, \
492 : .mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
493 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
494 : (.test.name = "eth src", \
495 : .test.type = NPF_TEST_TYPE_ETH_SRC_ADDR_MATCH,)) \
496 : }
497 :
498 : /**
499 : * @brief Statically define a "source address unmatch" packet filter condition
500 : *
501 : * This tests if the packet source address matches none of the Ethernet
502 : * addresses contained in the provided set.
503 : *
504 : * @param _name Name of the condition
505 : * @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
506 : */
507 1 : #define NPF_ETH_SRC_ADDR_UNMATCH(_name, _addr_array) \
508 : struct npf_test_eth_addr _name = { \
509 : .addresses = (_addr_array), \
510 : .nb_addresses = ARRAY_SIZE(_addr_array), \
511 : .test.fn = npf_eth_src_addr_unmatch, \
512 : .mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
513 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
514 : (.test.name = "!eth src", \
515 : .test.type = NPF_TEST_TYPE_ETH_SRC_ADDR_UNMATCH,)) \
516 : }
517 :
518 : /**
519 : * @brief Statically define a "destination address match" packet filter condition
520 : *
521 : * This tests if the packet destination address matches any of the Ethernet
522 : * addresses contained in the provided set.
523 : *
524 : * @param _name Name of the condition
525 : * @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
526 : */
527 1 : #define NPF_ETH_DST_ADDR_MATCH(_name, _addr_array) \
528 : struct npf_test_eth_addr _name = { \
529 : .addresses = (_addr_array), \
530 : .nb_addresses = ARRAY_SIZE(_addr_array), \
531 : .test.fn = npf_eth_dst_addr_match, \
532 : .mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
533 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
534 : (.test.name = "eth dst", \
535 : .test.type = NPF_TEST_TYPE_ETH_DST_ADDR_MATCH,)) \
536 : }
537 :
538 : /**
539 : * @brief Statically define a "destination address unmatch" packet filter condition
540 : *
541 : * This tests if the packet destination address matches none of the Ethernet
542 : * addresses contained in the provided set.
543 : *
544 : * @param _name Name of the condition
545 : * @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
546 : */
547 1 : #define NPF_ETH_DST_ADDR_UNMATCH(_name, _addr_array) \
548 : struct npf_test_eth_addr _name = { \
549 : .addresses = (_addr_array), \
550 : .nb_addresses = ARRAY_SIZE(_addr_array), \
551 : .test.fn = npf_eth_dst_addr_unmatch, \
552 : .mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
553 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
554 : (.test.name = "!eth dst", \
555 : .test.type = NPF_TEST_TYPE_ETH_DST_ADDR_UNMATCH,)) \
556 : }
557 :
558 : /**
559 : * @brief Statically define a "source address match with mask" packet filter condition
560 : *
561 : * This tests if the packet source address matches any of the Ethernet
562 : * addresses contained in the provided set after applying specified mask.
563 : *
564 : * @param _name Name of the condition
565 : * @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
566 : * @param ... up to 6 mask bytes
567 : */
568 1 : #define NPF_ETH_SRC_ADDR_MASK_MATCH(_name, _addr_array, ...) \
569 : struct npf_test_eth_addr _name = { \
570 : .addresses = (_addr_array), \
571 : .nb_addresses = ARRAY_SIZE(_addr_array), \
572 : .mask.addr = { __VA_ARGS__ }, \
573 : .test.fn = npf_eth_src_addr_match, \
574 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
575 : (.test.name = "eth src mask", \
576 : .test.type = NPF_TEST_TYPE_ETH_SRC_ADDR_MASK_MATCH,)) \
577 : }
578 :
579 : /**
580 : * @brief Statically define a "destination address match with mask" packet filter condition
581 : *
582 : * This tests if the packet destination address matches any of the Ethernet
583 : * addresses contained in the provided set after applying specified mask.
584 : *
585 : * @param _name Name of the condition
586 : * @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
587 : * @param ... up to 6 mask bytes
588 : */
589 1 : #define NPF_ETH_DST_ADDR_MASK_MATCH(_name, _addr_array, ...) \
590 : struct npf_test_eth_addr _name = { \
591 : .addresses = (_addr_array), \
592 : .nb_addresses = ARRAY_SIZE(_addr_array), \
593 : .mask.addr = { __VA_ARGS__ }, \
594 : .test.fn = npf_eth_dst_addr_match, \
595 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
596 : (.test.name = "eth dst mask", \
597 : .test.type = NPF_TEST_TYPE_ETH_DST_ADDR_MASK_MATCH,)) \
598 : }
599 :
600 : /** @cond INTERNAL_HIDDEN */
601 :
602 : struct npf_test_eth_type {
603 : struct npf_test test;
604 : uint16_t type; /* type in network order */
605 : };
606 :
607 : extern npf_test_fn_t npf_eth_type_match;
608 : extern npf_test_fn_t npf_eth_type_unmatch;
609 : extern npf_test_fn_t npf_eth_vlan_type_match;
610 : extern npf_test_fn_t npf_eth_vlan_type_unmatch;
611 :
612 : /** @endcond */
613 :
614 : /**
615 : * @brief Statically define an "Ethernet type match" packet filter condition
616 : *
617 : * @param _name Name of the condition
618 : * @param _type Ethernet type to match
619 : */
620 1 : #define NPF_ETH_TYPE_MATCH(_name, _type) \
621 : struct npf_test_eth_type _name = { \
622 : .type = htons(_type), \
623 : .test.fn = npf_eth_type_match, \
624 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
625 : (.test.name = "eth type", \
626 : .test.type = NPF_TEST_TYPE_ETH_TYPE_MATCH,)) \
627 : }
628 :
629 : /**
630 : * @brief Statically define an "Ethernet type unmatch" packet filter condition
631 : *
632 : * @param _name Name of the condition
633 : * @param _type Ethernet type to exclude
634 : */
635 1 : #define NPF_ETH_TYPE_UNMATCH(_name, _type) \
636 : struct npf_test_eth_type _name = { \
637 : .type = htons(_type), \
638 : .test.fn = npf_eth_type_unmatch, \
639 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
640 : (.test.name = "!eth type", \
641 : .test.type = NPF_TEST_TYPE_ETH_TYPE_UNMATCH,)) \
642 : }
643 :
644 : /**
645 : * @brief Statically define an "Ethernet VLAN header type match" packet
646 : * filter condition.
647 : *
648 : * @param _name Name of the condition
649 : * @param _type Ethernet VLAN header type to match
650 : */
651 1 : #define NPF_ETH_VLAN_TYPE_MATCH(_name, _type) \
652 : struct npf_test_eth_type _name = { \
653 : .type = htons(_type), \
654 : .test.fn = npf_eth_vlan_type_match, \
655 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
656 : (.test.name = "eth vlan type", \
657 : .test.type = NPF_TEST_TYPE_ETH_VLAN_TYPE_MATCH,)) \
658 : }
659 :
660 : /**
661 : * @brief Statically define an "Ethernet VLAN header type unmatch" packet
662 : * filter condition.
663 : *
664 : * @param _name Name of the condition
665 : * @param _type Ethernet VLAN header type to exclude
666 : */
667 1 : #define NPF_ETH_VLAN_TYPE_UNMATCH(_name, _type) \
668 : struct npf_test_eth_type _name = { \
669 : .type = htons(_type), \
670 : .test.fn = npf_eth_vlan_type_unmatch, \
671 : IF_ENABLED(NPF_TEST_ENABLE_NAME, \
672 : (.test.name = "!eth vlan type", \
673 : .test.type = NPF_TEST_TYPE_ETH_VLAN_TYPE_UNMATCH,)) \
674 : }
675 :
676 : /** Type of the packet filter rule. */
677 1 : enum npf_rule_type {
678 : NPF_RULE_TYPE_UNKNOWN = 0, /**< Unknown rule type */
679 : NPF_RULE_TYPE_SEND, /**< Rule for outgoing packets */
680 : NPF_RULE_TYPE_RECV, /**< Rule for incoming packets */
681 : NPF_RULE_TYPE_LOCAL_IN_RECV, /**< Rule for local incoming packets */
682 : NPF_RULE_TYPE_IPV4_RECV, /**< Rule for IPv4 incoming packets */
683 : NPF_RULE_TYPE_IPV6_RECV, /**< Rule for IPv6 incoming packets */
684 : };
685 :
686 : /**
687 : * @typedef npf_rule_cb_t
688 : * @brief Callback used while iterating over network packet filter rules.
689 : *
690 : * @param rule Pointer to current network packet filter rule
691 : * @param type Type of the rule (rx, tx, local_in, IPv4 or IPv6)
692 : * @param user_data A valid pointer to user data or NULL
693 : */
694 1 : typedef void (*npf_rule_cb_t)(struct npf_rule *rule,
695 : enum npf_rule_type type,
696 : void *user_data);
697 :
698 : /**
699 : * @brief Go through all the network packet filter rules and call callback
700 : * for each of them.
701 : *
702 : * @param cb User-supplied callback function to call
703 : * @param user_data User specified data
704 : */
705 1 : void npf_rules_foreach(npf_rule_cb_t cb, void *user_data);
706 :
707 : /** @cond INTERNAL_HIDDEN */
708 : const char *npf_test_get_str(struct npf_test *test, char *buf,
709 : size_t len);
710 : /** @endcond */
711 :
712 : /** @} */
713 :
714 : #ifdef __cplusplus
715 : }
716 : #endif
717 :
718 : #endif /* ZEPHYR_INCLUDE_NET_PKT_FILTER_H_ */
|