net: pkt_filter: Add enablers for shell support

Add helpers and enablers that allow "net filter" shell command to
work.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
Jukka Rissanen 2025-04-11 14:51:20 +03:00 committed by Benjamin Cabé
commit f5bac38865
3 changed files with 362 additions and 86 deletions

View file

@ -39,11 +39,46 @@ struct npf_test;
typedef bool (npf_test_fn_t)(struct npf_test *test, struct net_pkt *pkt);
enum npf_test_type {
NPF_TEST_TYPE_UNKNOWN = 0,
NPF_TEST_TYPE_IFACE_MATCH,
NPF_TEST_TYPE_IFACE_UNMATCH,
NPF_TEST_TYPE_ORIG_IFACE_MATCH,
NPF_TEST_TYPE_ORIG_IFACE_UNMATCH,
NPF_TEST_TYPE_SIZE_MIN,
NPF_TEST_TYPE_SIZE_MAX,
NPF_TEST_TYPE_SIZE_BOUNDS,
NPF_TEST_TYPE_IP_SRC_ADDR_ALLOWLIST,
NPF_TEST_TYPE_IP_SRC_ADDR_BLOCKLIST,
NPF_TEST_TYPE_ETH_SRC_ADDR_MATCH,
NPF_TEST_TYPE_ETH_SRC_ADDR_UNMATCH,
NPF_TEST_TYPE_ETH_DST_ADDR_MATCH,
NPF_TEST_TYPE_ETH_DST_ADDR_UNMATCH,
NPF_TEST_TYPE_ETH_SRC_ADDR_MASK_MATCH,
NPF_TEST_TYPE_ETH_DST_ADDR_MASK_MATCH,
NPF_TEST_TYPE_ETH_TYPE_MATCH,
NPF_TEST_TYPE_ETH_TYPE_UNMATCH,
};
#if defined(CONFIG_NET_PKT_FILTER_LOG_LEVEL_DBG) || \
defined(CONFIG_NET_SHELL_PKT_FILTER_SUPPORTED)
#define NPF_TEST_ENABLE_NAME 1
#elif defined(NPF_TEST_ENABLE_NAME)
#undef NPF_TEST_ENABLE_NAME
#endif
/** @endcond */
/** @brief common filter test structure to be embedded into larger structures */
struct npf_test {
npf_test_fn_t *fn; /**< packet condition test function */
/** @cond INTERNAL_HIDDEN */
IF_ENABLED(NPF_TEST_ENABLE_NAME,
(const char *name;)) /**< Name of the test */
IF_ENABLED(NPF_TEST_ENABLE_NAME,
(enum npf_test_type type;)) /**< Type of the test */
/** @endcond */
};
/** @brief filter rule structure */
@ -237,10 +272,13 @@ extern npf_test_fn_t npf_orig_iface_unmatch;
* @param _name Name of the condition
* @param _iface Interface to match
*/
#define NPF_IFACE_MATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_iface_match, \
#define NPF_IFACE_MATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_iface_match, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "iface", \
.test.type = NPF_TEST_TYPE_IFACE_MATCH,)) \
}
/**
@ -249,10 +287,13 @@ extern npf_test_fn_t npf_orig_iface_unmatch;
* @param _name Name of the condition
* @param _iface Interface to exclude
*/
#define NPF_IFACE_UNMATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_iface_unmatch, \
#define NPF_IFACE_UNMATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_iface_unmatch, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "!iface", \
.test.type = NPF_TEST_TYPE_IFACE_UNMATCH,)) \
}
/**
@ -261,10 +302,13 @@ extern npf_test_fn_t npf_orig_iface_unmatch;
* @param _name Name of the condition
* @param _iface Interface to match
*/
#define NPF_ORIG_IFACE_MATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_orig_iface_match, \
#define NPF_ORIG_IFACE_MATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_orig_iface_match, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "orig iface", \
.test.type = NPF_TEST_TYPE_ORIG_IFACE_MATCH,)) \
}
/**
@ -273,10 +317,13 @@ extern npf_test_fn_t npf_orig_iface_unmatch;
* @param _name Name of the condition
* @param _iface Interface to exclude
*/
#define NPF_ORIG_IFACE_UNMATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_orig_iface_unmatch, \
#define NPF_ORIG_IFACE_UNMATCH(_name, _iface) \
struct npf_test_iface _name = { \
.iface = (_iface), \
.test.fn = npf_orig_iface_unmatch, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "!orig iface", \
.test.type = NPF_TEST_TYPE_ORIG_IFACE_UNMATCH,)) \
}
/** @cond INTERNAL_HIDDEN */
@ -297,11 +344,14 @@ extern npf_test_fn_t npf_size_inbounds;
* @param _name Name of the condition
* @param _size Lower bound of the packet's data size
*/
#define NPF_SIZE_MIN(_name, _size) \
struct npf_test_size_bounds _name = { \
.min = (_size), \
.max = SIZE_MAX, \
.test.fn = npf_size_inbounds, \
#define NPF_SIZE_MIN(_name, _size) \
struct npf_test_size_bounds _name = { \
.min = (_size), \
.max = SIZE_MAX, \
.test.fn = npf_size_inbounds, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "size min", \
.test.type = NPF_TEST_TYPE_SIZE_MIN,)) \
}
/**
@ -310,11 +360,14 @@ extern npf_test_fn_t npf_size_inbounds;
* @param _name Name of the condition
* @param _size Higher bound of the packet's data size
*/
#define NPF_SIZE_MAX(_name, _size) \
struct npf_test_size_bounds _name = { \
.min = 0, \
.max = (_size), \
.test.fn = npf_size_inbounds, \
#define NPF_SIZE_MAX(_name, _size) \
struct npf_test_size_bounds _name = { \
.min = 0, \
.max = (_size), \
.test.fn = npf_size_inbounds, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "size max", \
.test.type = NPF_TEST_TYPE_SIZE_MAX,)) \
}
/**
@ -324,11 +377,14 @@ extern npf_test_fn_t npf_size_inbounds;
* @param _min_size Lower bound of the packet's data size
* @param _max_size Higher bound of the packet's data size
*/
#define NPF_SIZE_BOUNDS(_name, _min_size, _max_size) \
struct npf_test_size_bounds _name = { \
.min = (_min_size), \
.max = (_max_size), \
.test.fn = npf_size_inbounds, \
#define NPF_SIZE_BOUNDS(_name, _min_size, _max_size) \
struct npf_test_size_bounds _name = { \
.min = (_min_size), \
.max = (_max_size), \
.test.fn = npf_size_inbounds, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "size bounds", \
.test.type = NPF_TEST_TYPE_SIZE_BOUNDS,)) \
}
/** @cond INTERNAL_HIDDEN */
@ -358,11 +414,14 @@ extern npf_test_fn_t npf_ip_src_addr_unmatch;
* @param _af Addresses family type (AF_INET / AF_INET6) in the array
*/
#define NPF_IP_SRC_ADDR_ALLOWLIST(_name, _ip_addr_array, _ip_addr_num, _af) \
struct npf_test_ip _name = { \
.addr_family = _af, \
.ipaddr = (_ip_addr_array), \
.ipaddr_num = _ip_addr_num, \
.test.fn = npf_ip_src_addr_match, \
struct npf_test_ip _name = { \
.addr_family = _af, \
.ipaddr = (_ip_addr_array), \
.ipaddr_num = _ip_addr_num, \
.test.fn = npf_ip_src_addr_match, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "ip src allow", \
.test.type = NPF_TEST_TYPE_IP_SRC_ADDR_ALLOWLIST,)) \
}
/**
@ -378,11 +437,14 @@ extern npf_test_fn_t npf_ip_src_addr_unmatch;
* @param _af Addresses family type (AF_INET / AF_INET6) in the array
*/
#define NPF_IP_SRC_ADDR_BLOCKLIST(_name, _ip_addr_array, _ip_addr_num, _af) \
struct npf_test_ip _name = { \
.addr_family = _af, \
.ipaddr = (_ip_addr_array), \
.ipaddr_num = _ip_addr_num, \
.test.fn = npf_ip_src_addr_unmatch, \
struct npf_test_ip _name = { \
.addr_family = _af, \
.ipaddr = (_ip_addr_array), \
.ipaddr_num = _ip_addr_num, \
.test.fn = npf_ip_src_addr_unmatch, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "ip src block", \
.test.type = NPF_TEST_TYPE_IP_SRC_ADDR_BLOCKLIST,)) \
}
/** @} */
@ -420,12 +482,15 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
* @param _name Name of the condition
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
*/
#define NPF_ETH_SRC_ADDR_MATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_src_addr_match, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
#define NPF_ETH_SRC_ADDR_MATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_src_addr_match, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "eth src", \
.test.type = NPF_TEST_TYPE_ETH_SRC_ADDR_MATCH,)) \
}
/**
@ -437,12 +502,15 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
* @param _name Name of the condition
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
*/
#define NPF_ETH_SRC_ADDR_UNMATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_src_addr_unmatch, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
#define NPF_ETH_SRC_ADDR_UNMATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_src_addr_unmatch, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "!eth src", \
.test.type = NPF_TEST_TYPE_ETH_SRC_ADDR_UNMATCH,)) \
}
/**
@ -454,12 +522,15 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
* @param _name Name of the condition
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
*/
#define NPF_ETH_DST_ADDR_MATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_dst_addr_match, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
#define NPF_ETH_DST_ADDR_MATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_dst_addr_match, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "eth dst", \
.test.type = NPF_TEST_TYPE_ETH_DST_ADDR_MATCH,)) \
}
/**
@ -471,12 +542,15 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
* @param _name Name of the condition
* @param _addr_array Array of <tt>struct net_eth_addr</tt> items to test against
*/
#define NPF_ETH_DST_ADDR_UNMATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_dst_addr_unmatch, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
#define NPF_ETH_DST_ADDR_UNMATCH(_name, _addr_array) \
struct npf_test_eth_addr _name = { \
.addresses = (_addr_array), \
.nb_addresses = ARRAY_SIZE(_addr_array), \
.test.fn = npf_eth_dst_addr_unmatch, \
.mask.addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "!eth dst", \
.test.type = NPF_TEST_TYPE_ETH_DST_ADDR_UNMATCH,)) \
}
/**
@ -489,12 +563,15 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
* @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, \
#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, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "eth src mask", \
.test.type = NPF_TEST_TYPE_ETH_SRC_ADDR_MASK_MATCH,)) \
}
/**
@ -507,12 +584,15 @@ extern npf_test_fn_t npf_eth_dst_addr_unmatch;
* @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, \
#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, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "eth dst mask", \
.test.type = NPF_TEST_TYPE_ETH_DST_ADDR_MASK_MATCH,)) \
}
/** @cond INTERNAL_HIDDEN */
@ -533,10 +613,13 @@ extern npf_test_fn_t npf_eth_type_unmatch;
* @param _name Name of the condition
* @param _type Ethernet type to match
*/
#define NPF_ETH_TYPE_MATCH(_name, _type) \
struct npf_test_eth_type _name = { \
.type = htons(_type), \
.test.fn = npf_eth_type_match, \
#define NPF_ETH_TYPE_MATCH(_name, _type) \
struct npf_test_eth_type _name = { \
.type = htons(_type), \
.test.fn = npf_eth_type_match, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "eth type", \
.test.type = NPF_TEST_TYPE_ETH_TYPE_MATCH,)) \
}
/**
@ -545,12 +628,51 @@ extern npf_test_fn_t npf_eth_type_unmatch;
* @param _name Name of the condition
* @param _type Ethernet type to exclude
*/
#define NPF_ETH_TYPE_UNMATCH(_name, _type) \
struct npf_test_eth_type _name = { \
.type = htons(_type), \
.test.fn = npf_eth_type_unmatch, \
#define NPF_ETH_TYPE_UNMATCH(_name, _type) \
struct npf_test_eth_type _name = { \
.type = htons(_type), \
.test.fn = npf_eth_type_unmatch, \
IF_ENABLED(NPF_TEST_ENABLE_NAME, \
(.test.name = "!eth type", \
.test.type = NPF_TEST_TYPE_ETH_TYPE_UNMATCH,)) \
}
/** Type of the packet filter rule. */
enum npf_rule_type {
NPF_RULE_TYPE_UNKNOWN = 0, /**< Unknown rule type */
NPF_RULE_TYPE_SEND, /**< Rule for outgoing packets */
NPF_RULE_TYPE_RECV, /**< Rule for incoming packets */
NPF_RULE_TYPE_LOCAL_IN_RECV, /**< Rule for local incoming packets */
NPF_RULE_TYPE_IPV4_RECV, /**< Rule for IPv4 incoming packets */
NPF_RULE_TYPE_IPV6_RECV, /**< Rule for IPv6 incoming packets */
};
/**
* @typedef npf_rule_cb_t
* @brief Callback used while iterating over network packet filter rules.
*
* @param rule Pointer to current network packet filter rule
* @param type Type of the rule (rx, tx, local_in, IPv4 or IPv6)
* @param user_data A valid pointer to user data or NULL
*/
typedef void (*npf_rule_cb_t)(struct npf_rule *rule,
enum npf_rule_type type,
void *user_data);
/**
* @brief Go through all the network packet filter rules and call callback
* for each of them.
*
* @param cb User-supplied callback function to call
* @param user_data User specified data
*/
void npf_rules_foreach(npf_rule_cb_t cb, void *user_data);
/** @cond INTERNAL_HIDDEN */
const char *npf_test_get_str(struct npf_test *test, char *buf,
size_t len);
/** @endcond */
/** @} */
#ifdef __cplusplus

View file

@ -5,5 +5,6 @@ if(CONFIG_NET_PKT_FILTER)
zephyr_library()
zephyr_library_sources(base.c)
zephyr_library_sources_ifdef(CONFIG_NET_L2_ETHERNET ethernet.c)
zephyr_library_include_directories(${ZEPHYR_BASE}/subsys/net/ip)
endif()

View file

@ -87,7 +87,9 @@ static bool apply_tests(struct npf_rule *rule, struct net_pkt *pkt)
for (i = 0; i < rule->nb_tests; i++) {
test = rule->tests[i];
result = test->fn(test, pkt);
NET_DBG("test %p result %d", test, result);
NET_DBG("test %s (%p) result %d",
COND_CODE_1(NPF_TEST_ENABLE_NAME, (test->name), ("")),
test, result);
if (result == false) {
return false;
}
@ -298,3 +300,154 @@ bool npf_ip_src_addr_unmatch(struct npf_test *test, struct net_pkt *pkt)
{
return !npf_ip_src_addr_match(test, pkt);
}
static void rules_cb(struct npf_rule_list *rules, enum npf_rule_type type,
npf_rule_cb_t cb, void *user_data)
{
struct npf_rule *rule;
SYS_SLIST_FOR_EACH_CONTAINER(&rules->rule_head, rule, node) {
cb(rule, type, user_data);
}
}
void npf_rules_foreach(npf_rule_cb_t cb, void *user_data)
{
rules_cb(&npf_send_rules, NPF_RULE_TYPE_SEND, cb, user_data);
rules_cb(&npf_recv_rules, NPF_RULE_TYPE_RECV, cb, user_data);
#ifdef CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK
rules_cb(&npf_local_in_recv_rules, NPF_RULE_TYPE_LOCAL_IN_RECV, cb, user_data);
#endif /* CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK */
#ifdef CONFIG_NET_PKT_FILTER_IPV4_HOOK
rules_cb(&npf_ipv4_recv_rules, NPF_RULE_TYPE_IPV4_RECV, cb, user_data);
#endif /* CONFIG_NET_PKT_FILTER_IPV4_HOOK */
#ifdef CONFIG_NET_PKT_FILTER_IPV6_HOOK
rules_cb(&npf_ipv6_recv_rules, NPF_RULE_TYPE_IPV6_RECV, cb, user_data);
#endif /* CONFIG_NET_PKT_FILTER_IPV6_HOOK */
}
#include "net_private.h" /* for net_sprint_addr() */
const char *npf_test_get_str(struct npf_test *test, char *buf, size_t len)
{
#if defined(CONFIG_NET_SHELL_PKT_FILTER_SUPPORTED)
if (test->type == NPF_TEST_TYPE_IFACE_MATCH ||
test->type == NPF_TEST_TYPE_IFACE_UNMATCH ||
test->type == NPF_TEST_TYPE_ORIG_IFACE_MATCH ||
test->type == NPF_TEST_TYPE_ORIG_IFACE_UNMATCH) {
struct npf_test_iface *test_iface =
CONTAINER_OF(test, struct npf_test_iface, test);
snprintk(buf, len, "[%d]", net_if_get_by_iface(test_iface->iface));
} else if (test->type == NPF_TEST_TYPE_SIZE_BOUNDS ||
test->type == NPF_TEST_TYPE_SIZE_MIN ||
test->type == NPF_TEST_TYPE_SIZE_MAX) {
struct npf_test_size_bounds *bounds =
CONTAINER_OF(test, struct npf_test_size_bounds, test);
if (test->type == NPF_TEST_TYPE_SIZE_MIN ||
test->type == NPF_TEST_TYPE_SIZE_MAX) {
snprintk(buf, len, "[%zu]",
test->type == NPF_TEST_TYPE_SIZE_MIN ?
bounds->min : bounds->max);
} else {
snprintk(buf, len, "[%zu-%zu]", bounds->min, bounds->max);
}
} else if (test->type == NPF_TEST_TYPE_IP_SRC_ADDR_ALLOWLIST ||
test->type == NPF_TEST_TYPE_IP_SRC_ADDR_BLOCKLIST) {
struct npf_test_ip *test_ip =
CONTAINER_OF(test, struct npf_test_ip, test);
int pos = 1;
if (len < 2) {
goto out;
}
if (test_ip->ipaddr_num == 0) {
snprintk(buf, len, "[]");
goto out;
}
buf[0] = '[';
for (uint32_t i = 0; i < test_ip->ipaddr_num; i++) {
if (IS_ENABLED(CONFIG_NET_IPV4) &&
test_ip->addr_family == AF_INET) {
struct in_addr *addr =
&((struct in_addr *)test_ip->ipaddr)[i];
pos += snprintk(buf + pos, len - pos,
"%s%s", pos > 1 ? "," : "",
net_sprint_ipv4_addr(addr));
} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
test_ip->addr_family == AF_INET6) {
struct in6_addr *addr =
&((struct in6_addr *)test_ip->ipaddr)[i];
pos += snprintk(buf + pos, len - pos,
"%s%s", pos > 1 ? "," : "",
net_sprint_ipv6_addr(addr));
}
}
if (pos >= len) {
goto out;
}
buf[pos] = ']';
} else if (test->type == NPF_TEST_TYPE_ETH_SRC_ADDR_MATCH ||
test->type == NPF_TEST_TYPE_ETH_SRC_ADDR_UNMATCH ||
test->type == NPF_TEST_TYPE_ETH_DST_ADDR_MATCH ||
test->type == NPF_TEST_TYPE_ETH_DST_ADDR_UNMATCH ||
test->type == NPF_TEST_TYPE_ETH_SRC_ADDR_MASK_MATCH ||
test->type == NPF_TEST_TYPE_ETH_DST_ADDR_MASK_MATCH) {
struct npf_test_eth_addr *test_eth =
CONTAINER_OF(test, struct npf_test_eth_addr, test);
int pos = 1;
if (len < 2) {
goto out;
}
if (test_eth->nb_addresses == 0) {
snprintk(buf, len, "[]");
goto out;
}
buf[0] = '[';
for (uint32_t i = 0; i < test_eth->nb_addresses; i++) {
pos += snprintk(buf + pos, len - pos,
"%s%s", pos > 1 ? "," : "",
net_sprint_ll_addr(
(const uint8_t *)(&test_eth->addresses[i]),
NET_ETH_ADDR_LEN));
}
if (pos >= len) {
goto out;
}
buf[pos] = ']';
} else if (test->type == NPF_TEST_TYPE_ETH_TYPE_MATCH ||
test->type == NPF_TEST_TYPE_ETH_TYPE_UNMATCH) {
struct npf_test_eth_type *test_eth =
CONTAINER_OF(test, struct npf_test_eth_type, test);
snprintk(buf, len, "[0x%04x]", ntohs(test_eth->type));
}
out:
return test->name;
#else
return "<UNKNOWN>";
#endif
}