Skip to content

Commit a3a3125

Browse files
Nicolas Pitrecarlescufi
authored andcommitted
net: npf: add the ability to do MAC address masked matching
Add the ability to do matching on partial MAC addresses. Signed-off-by: Nicolas Pitre <[email protected]>
1 parent faa0b2a commit a3a3125

File tree

3 files changed

+87
-6
lines changed

3 files changed

+87
-6
lines changed

include/net/net_pkt_filter.h

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ typedef bool (npf_test_fn_t)(struct npf_test *test, struct net_pkt *pkt);
4141

4242
/** @brief common filter test structure to be embedded into larger structures */
4343
struct npf_test {
44-
npf_test_fn_t *fn; /*< packet condition test function */
44+
npf_test_fn_t *fn; /**< packet condition test function */
4545
};
4646

4747
/** @brief filter rule structure */
4848
struct npf_rule {
4949
sys_snode_t node;
50-
enum net_verdict result; /*< result if all tests pass */
51-
uint32_t nb_tests; /*< number of tests in this rule */
52-
struct npf_test *tests[]; /*< pointers to @ref npf_test instances */
50+
enum net_verdict result; /**< result if all tests pass */
51+
uint32_t nb_tests; /**< number of tests for this rule */
52+
struct npf_test *tests[]; /**< pointers to @ref npf_test instances */
5353
};
5454

5555
/** @brief Default rule list termination for accepting a packet */
@@ -310,6 +310,7 @@ struct npf_test_eth_addr {
310310
struct npf_test test;
311311
unsigned int nb_addresses;
312312
struct net_eth_addr *addresses;
313+
struct net_eth_addr mask;
313314
};
314315

315316
extern npf_test_fn_t npf_eth_src_addr_match;
@@ -333,6 +334,7 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
333334
.addresses = (_addr_array), \
334335
.nb_addresses = ARRAY_SIZE(_addr_array), \
335336
.test.fn = npf_eth_src_addr_match, \
337+
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
336338
}
337339

338340
/**
@@ -349,6 +351,7 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
349351
.addresses = (_addr_array), \
350352
.nb_addresses = ARRAY_SIZE(_addr_array), \
351353
.test.fn = npf_eth_src_addr_unmatch, \
354+
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
352355
}
353356

354357
/**
@@ -365,6 +368,7 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
365368
.addresses = (_addr_array), \
366369
.nb_addresses = ARRAY_SIZE(_addr_array), \
367370
.test.fn = npf_eth_dst_addr_match, \
371+
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
368372
}
369373

370374
/**
@@ -381,6 +385,43 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
381385
.addresses = (_addr_array), \
382386
.nb_addresses = ARRAY_SIZE(_addr_array), \
383387
.test.fn = npf_eth_dst_addr_unmatch, \
388+
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
389+
}
390+
391+
/**
392+
* @brief Statically define a "source address match with mask" packet filter condition
393+
*
394+
* This tests if the packet source address matches any of the Ethernet
395+
* addresses contained in the provided set after applying specified mask.
396+
*
397+
* @param _name Name of the condition
398+
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
399+
* @param ... up to 6 mask bytes
400+
*/
401+
#define NPF_ETH_SRC_ADDR_MASK_MATCH(_name, _addr_array, ...) \
402+
struct npf_test_eth_addr _name = { \
403+
.addresses = (_addr_array), \
404+
.nb_addresses = ARRAY_SIZE(_addr_array), \
405+
.mask.addr = { __VA_ARGS__ }, \
406+
.test.fn = npf_eth_src_addr_match, \
407+
}
408+
409+
/**
410+
* @brief Statically define a "destination address match with mask" packet filter condition
411+
*
412+
* This tests if the packet destination address matches any of the Ethernet
413+
* addresses contained in the provided set after applying specified mask.
414+
*
415+
* @param _name Name of the condition
416+
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
417+
* @param ... up to 6 mask bytes
418+
*/
419+
#define NPF_ETH_DST_ADDR_MASK_MATCH(_name, _addr_array, ...) \
420+
struct npf_test_eth_addr _name = { \
421+
.addresses = (_addr_array), \
422+
.nb_addresses = ARRAY_SIZE(_addr_array), \
423+
.mask.addr = { __VA_ARGS__ }, \
424+
.test.fn = npf_eth_dst_addr_match, \
384425
}
385426

386427
/** @cond INTERNAL_HIDDEN */

subsys/net/pkt_filter/ethernet.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,29 @@ LOG_MODULE_REGISTER(npf_ethernet, CONFIG_NET_PKT_FILTER_LOG_LEVEL);
1010
#include <net/ethernet.h>
1111
#include <net/net_pkt_filter.h>
1212

13+
static bool addr_mask_compare(struct net_eth_addr *addr1,
14+
struct net_eth_addr *addr2,
15+
struct net_eth_addr *mask)
16+
{
17+
for (int i = 0; i < 6; i++) {
18+
if ((addr1->addr[i] & mask->addr[i]) !=
19+
(addr2->addr[i] & mask->addr[i])) {
20+
return false;
21+
}
22+
}
23+
return true;
24+
}
25+
1326
static bool addr_match(struct npf_test *test, struct net_eth_addr *pkt_addr)
1427
{
1528
struct npf_test_eth_addr *test_eth_addr =
1629
CONTAINER_OF(test, struct npf_test_eth_addr, test);
1730
struct net_eth_addr *addr = test_eth_addr->addresses;
31+
struct net_eth_addr *mask = &test_eth_addr->mask;
1832
unsigned int nb_addr = test_eth_addr->nb_addresses;
1933

2034
while (nb_addr) {
21-
if (memcmp(addr, pkt_addr, sizeof(struct net_eth_addr)) == 0) {
35+
if (addr_mask_compare(addr, pkt_addr, mask)) {
2236
return true;
2337
}
2438
addr++;

tests/net/npf/src/main.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,13 +281,39 @@ static void test_npf_eth_mac_address(void)
281281
zassert_true(npf_remove_recv_rule(&accept_unmatched_dst_addr), "");
282282
}
283283

284+
static NPF_ETH_SRC_ADDR_MASK_MATCH(matched_src_addr_mask, mac_address_list,
285+
0xff, 0xff, 0xff, 0xff, 0xff, 0x00);
286+
static NPF_RULE(accept_matched_src_addr_mask, NET_OK, matched_src_addr_mask);
287+
288+
static void test_npf_eth_mac_addr_mask(void)
289+
{
290+
struct net_pkt *pkt = build_test_pkt(NET_ETH_PTYPE_IP, 100, NULL);
291+
292+
/* test standard match rule from previous test */
293+
npf_insert_recv_rule(&npf_default_drop);
294+
npf_insert_recv_rule(&accept_matched_src_addr);
295+
zassert_true(net_pkt_filter_recv_ok(pkt), "");
296+
297+
/* clobber one nibble of matching address from previous test */
298+
mac_address_list[1].addr[5] = 0x00;
299+
zassert_false(net_pkt_filter_recv_ok(pkt), "");
300+
301+
/* insert masked address match rule */
302+
npf_insert_recv_rule(&accept_matched_src_addr_mask);
303+
zassert_true(net_pkt_filter_recv_ok(pkt), "");
304+
305+
/* cleanup */
306+
zassert_true(npf_remove_all_recv_rules(), "");
307+
}
308+
284309
void test_main(void)
285310
{
286311
ztest_test_suite(net_pkt_filter_test,
287312
ztest_unit_test(test_npf_iface),
288313
ztest_unit_test(test_npf_example1),
289314
ztest_unit_test(test_npf_example2),
290-
ztest_unit_test(test_npf_eth_mac_address));
315+
ztest_unit_test(test_npf_eth_mac_address),
316+
ztest_unit_test(test_npf_eth_mac_addr_mask));
291317

292318
ztest_run_test_suite(net_pkt_filter_test);
293319
}

0 commit comments

Comments
 (0)