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 <npitre@baylibre.com>
This commit is contained in:
parent
faa0b2a848
commit
a3a31257df
3 changed files with 87 additions and 6 deletions
|
@ -41,15 +41,15 @@ typedef bool (npf_test_fn_t)(struct npf_test *test, struct net_pkt *pkt);
|
||||||
|
|
||||||
/** @brief common filter test structure to be embedded into larger structures */
|
/** @brief common filter test structure to be embedded into larger structures */
|
||||||
struct npf_test {
|
struct npf_test {
|
||||||
npf_test_fn_t *fn; /*< packet condition test function */
|
npf_test_fn_t *fn; /**< packet condition test function */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief filter rule structure */
|
/** @brief filter rule structure */
|
||||||
struct npf_rule {
|
struct npf_rule {
|
||||||
sys_snode_t node;
|
sys_snode_t node;
|
||||||
enum net_verdict result; /*< result if all tests pass */
|
enum net_verdict result; /**< result if all tests pass */
|
||||||
uint32_t nb_tests; /*< number of tests in this rule */
|
uint32_t nb_tests; /**< number of tests for this rule */
|
||||||
struct npf_test *tests[]; /*< pointers to @ref npf_test instances */
|
struct npf_test *tests[]; /**< pointers to @ref npf_test instances */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief Default rule list termination for accepting a packet */
|
/** @brief Default rule list termination for accepting a packet */
|
||||||
|
@ -310,6 +310,7 @@ struct npf_test_eth_addr {
|
||||||
struct npf_test test;
|
struct npf_test test;
|
||||||
unsigned int nb_addresses;
|
unsigned int nb_addresses;
|
||||||
struct net_eth_addr *addresses;
|
struct net_eth_addr *addresses;
|
||||||
|
struct net_eth_addr mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern npf_test_fn_t npf_eth_src_addr_match;
|
extern npf_test_fn_t npf_eth_src_addr_match;
|
||||||
|
@ -333,6 +334,7 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
|
||||||
.addresses = (_addr_array), \
|
.addresses = (_addr_array), \
|
||||||
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
||||||
.test.fn = npf_eth_src_addr_match, \
|
.test.fn = npf_eth_src_addr_match, \
|
||||||
|
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -349,6 +351,7 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
|
||||||
.addresses = (_addr_array), \
|
.addresses = (_addr_array), \
|
||||||
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
||||||
.test.fn = npf_eth_src_addr_unmatch, \
|
.test.fn = npf_eth_src_addr_unmatch, \
|
||||||
|
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -365,6 +368,7 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
|
||||||
.addresses = (_addr_array), \
|
.addresses = (_addr_array), \
|
||||||
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
||||||
.test.fn = npf_eth_dst_addr_match, \
|
.test.fn = npf_eth_dst_addr_match, \
|
||||||
|
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -381,6 +385,43 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
|
||||||
.addresses = (_addr_array), \
|
.addresses = (_addr_array), \
|
||||||
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
||||||
.test.fn = npf_eth_dst_addr_unmatch, \
|
.test.fn = npf_eth_dst_addr_unmatch, \
|
||||||
|
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Statically define a "source address match with mask" packet filter condition
|
||||||
|
*
|
||||||
|
* This tests if the packet source address matches any of the Ethernet
|
||||||
|
* addresses contained in the provided set after applying specified mask.
|
||||||
|
*
|
||||||
|
* @param _name Name of the condition
|
||||||
|
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
|
||||||
|
* @param ... up to 6 mask bytes
|
||||||
|
*/
|
||||||
|
#define NPF_ETH_SRC_ADDR_MASK_MATCH(_name, _addr_array, ...) \
|
||||||
|
struct npf_test_eth_addr _name = { \
|
||||||
|
.addresses = (_addr_array), \
|
||||||
|
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
||||||
|
.mask.addr = { __VA_ARGS__ }, \
|
||||||
|
.test.fn = npf_eth_src_addr_match, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Statically define a "destination address match with mask" packet filter condition
|
||||||
|
*
|
||||||
|
* This tests if the packet destination address matches any of the Ethernet
|
||||||
|
* addresses contained in the provided set after applying specified mask.
|
||||||
|
*
|
||||||
|
* @param _name Name of the condition
|
||||||
|
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
|
||||||
|
* @param ... up to 6 mask bytes
|
||||||
|
*/
|
||||||
|
#define NPF_ETH_DST_ADDR_MASK_MATCH(_name, _addr_array, ...) \
|
||||||
|
struct npf_test_eth_addr _name = { \
|
||||||
|
.addresses = (_addr_array), \
|
||||||
|
.nb_addresses = ARRAY_SIZE(_addr_array), \
|
||||||
|
.mask.addr = { __VA_ARGS__ }, \
|
||||||
|
.test.fn = npf_eth_dst_addr_match, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @cond INTERNAL_HIDDEN */
|
/** @cond INTERNAL_HIDDEN */
|
||||||
|
|
|
@ -10,15 +10,29 @@ LOG_MODULE_REGISTER(npf_ethernet, CONFIG_NET_PKT_FILTER_LOG_LEVEL);
|
||||||
#include <net/ethernet.h>
|
#include <net/ethernet.h>
|
||||||
#include <net/net_pkt_filter.h>
|
#include <net/net_pkt_filter.h>
|
||||||
|
|
||||||
|
static bool addr_mask_compare(struct net_eth_addr *addr1,
|
||||||
|
struct net_eth_addr *addr2,
|
||||||
|
struct net_eth_addr *mask)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if ((addr1->addr[i] & mask->addr[i]) !=
|
||||||
|
(addr2->addr[i] & mask->addr[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool addr_match(struct npf_test *test, struct net_eth_addr *pkt_addr)
|
static bool addr_match(struct npf_test *test, struct net_eth_addr *pkt_addr)
|
||||||
{
|
{
|
||||||
struct npf_test_eth_addr *test_eth_addr =
|
struct npf_test_eth_addr *test_eth_addr =
|
||||||
CONTAINER_OF(test, struct npf_test_eth_addr, test);
|
CONTAINER_OF(test, struct npf_test_eth_addr, test);
|
||||||
struct net_eth_addr *addr = test_eth_addr->addresses;
|
struct net_eth_addr *addr = test_eth_addr->addresses;
|
||||||
|
struct net_eth_addr *mask = &test_eth_addr->mask;
|
||||||
unsigned int nb_addr = test_eth_addr->nb_addresses;
|
unsigned int nb_addr = test_eth_addr->nb_addresses;
|
||||||
|
|
||||||
while (nb_addr) {
|
while (nb_addr) {
|
||||||
if (memcmp(addr, pkt_addr, sizeof(struct net_eth_addr)) == 0) {
|
if (addr_mask_compare(addr, pkt_addr, mask)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
addr++;
|
addr++;
|
||||||
|
|
|
@ -281,13 +281,39 @@ static void test_npf_eth_mac_address(void)
|
||||||
zassert_true(npf_remove_recv_rule(&accept_unmatched_dst_addr), "");
|
zassert_true(npf_remove_recv_rule(&accept_unmatched_dst_addr), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NPF_ETH_SRC_ADDR_MASK_MATCH(matched_src_addr_mask, mac_address_list,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0x00);
|
||||||
|
static NPF_RULE(accept_matched_src_addr_mask, NET_OK, matched_src_addr_mask);
|
||||||
|
|
||||||
|
static void test_npf_eth_mac_addr_mask(void)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt = build_test_pkt(NET_ETH_PTYPE_IP, 100, NULL);
|
||||||
|
|
||||||
|
/* test standard match rule from previous test */
|
||||||
|
npf_insert_recv_rule(&npf_default_drop);
|
||||||
|
npf_insert_recv_rule(&accept_matched_src_addr);
|
||||||
|
zassert_true(net_pkt_filter_recv_ok(pkt), "");
|
||||||
|
|
||||||
|
/* clobber one nibble of matching address from previous test */
|
||||||
|
mac_address_list[1].addr[5] = 0x00;
|
||||||
|
zassert_false(net_pkt_filter_recv_ok(pkt), "");
|
||||||
|
|
||||||
|
/* insert masked address match rule */
|
||||||
|
npf_insert_recv_rule(&accept_matched_src_addr_mask);
|
||||||
|
zassert_true(net_pkt_filter_recv_ok(pkt), "");
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
zassert_true(npf_remove_all_recv_rules(), "");
|
||||||
|
}
|
||||||
|
|
||||||
void test_main(void)
|
void test_main(void)
|
||||||
{
|
{
|
||||||
ztest_test_suite(net_pkt_filter_test,
|
ztest_test_suite(net_pkt_filter_test,
|
||||||
ztest_unit_test(test_npf_iface),
|
ztest_unit_test(test_npf_iface),
|
||||||
ztest_unit_test(test_npf_example1),
|
ztest_unit_test(test_npf_example1),
|
||||||
ztest_unit_test(test_npf_example2),
|
ztest_unit_test(test_npf_example2),
|
||||||
ztest_unit_test(test_npf_eth_mac_address));
|
ztest_unit_test(test_npf_eth_mac_address),
|
||||||
|
ztest_unit_test(test_npf_eth_mac_addr_mask));
|
||||||
|
|
||||||
ztest_run_test_suite(net_pkt_filter_test);
|
ztest_run_test_suite(net_pkt_filter_test);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue