Network Packet Filtering
Overview
The Network Packet Filtering facility provides the infrastructure to construct custom rules for accepting and/or denying packet transmission and reception. This can be used to create a basic firewall, control network traffic, etc.
The CONFIG_NET_PKT_FILTER
must be set in order to enable the
relevant APIs.
Both the transmission and reception paths may have a list of filter rules. Each rule is made of a set of conditions and a packet outcome. Every packet is subjected to the conditions attached to a rule. When all the conditions for a given rule are true then the packet outcome is immediately determined as specified by the current rule and no more rules are considered. If one condition is false then the next rule in the list is considered.
Packet outcome is either NET_OK
to accept the packet or NET_DROP
to
drop it.
A rule is represented by a npf_rule
object. It can be inserted to,
appended to or removed from a rule list contained in a
npf_rule_list
object using npf_insert_rule()
,
npf_append_rule()
, and npf_remove_rule()
.
Currently, two such rule lists exist: npf_send_rules
for outgoing packets,
and npf_recv_rules
for incoming packets.
If a filter rule list is empty then NET_OK
is assumed. If a non-empty
rule list runs to the end then NET_DROP
is assumed. However it is
recommended to always terminate a non-empty rule list with an explicit
default termination rule, either npf_default_ok
or npf_default_drop
.
Rule conditions are represented by a npf_test
. This structure
can be embedded into a larger structure when a specific condition requires
extra test data. It is up to the test function for such conditions to
retrieve the outer structure from the provided npf_test
structure pointer.
Convenience macros are provided in include/zephyr/net/net_pkt_filter.h
to statically define condition instances for various conditions, and
NPF_RULE()
to create a rule instance to tie them.
Examples
Here’s an example usage:
static NPF_SIZE_MAX(maxsize_200, 200);
static NPF_ETH_TYPE_MATCH(ip_packet, NET_ETH_PTYPE_IP);
static NPF_RULE(small_ip_pkt, NET_OK, ip_packet, maxsize_200);
void install_my_filter(void)
{
npf_insert_recv_rule(&npf_default_drop);
npf_insert_recv_rule(&small_ip_pkt);
}
The above would accept IP packets that are 200 bytes or smaller, and drop all other packets.
Another (less efficient) way to achieve the same result could be:
static NPF_SIZE_MIN(minsize_201, 201);
static NPF_ETH_TYPE_UNMATCH(not_ip_packet, NET_ETH_PTYPE_IP);
static NPF_RULE(reject_big_pkts, NET_DROP, minsize_201);
static NPF_RULE(reject_non_ip, NET_DROP, not_ip_packet);
void install_my_filter(void) {
npf_append_recv_rule(&reject_big_pkts);
npf_append_recv_rule(&reject_non_ip);
npf_append_recv_rule(&npf_default_ok);
}
API Reference
- group net_pkt_filter
Network Packet Filter API.
Defines
-
NPF_RULE(_name, _result, ...)
Statically define one packet filter rule.
This creates a rule from a variable amount of filter conditions. This rule can then be inserted or appended to the rule list for a given network packet path.
Example:
static NPF_SIZE_MAX(maxsize_200, 200); static NPF_ETH_TYPE_MATCH(ip_packet, NET_ETH_PTYPE_IP); static NPF_RULE(small_ip_pkt, NET_OK, ip_packet, maxsize_200); void install_my_filter(void) { npf_insert_recv_rule(&npf_default_drop); npf_insert_recv_rule(&small_ip_pkt); }
The above would accept IP packets that are 200 bytes or smaller, and drop all other packets.
Another (less efficient) way to create the same result could be:
static NPF_SIZE_MIN(minsize_201, 201); static NPF_ETH_TYPE_UNMATCH(not_ip_packet, NET_ETH_PTYPE_IP); static NPF_RULE(reject_big_pkts, NET_DROP, minsize_201); static NPF_RULE(reject_non_ip, NET_DROP, not_ip_packet); void install_my_filter(void) { npf_append_recv_rule(&reject_big_pkts); npf_append_recv_rule(&reject_non_ip); npf_append_recv_rule(&npf_default_ok); }
The first rule in the list for which all conditions are true determines the fate of the packet. If one condition is false then the next rule in the list is evaluated.
- Parameters:
_name – Name for this rule.
_result – Fate of the packet if all conditions are true, either
NET_OK
orNET_DROP
.... – List of conditions for this rule.
Functions
-
void npf_insert_rule(struct npf_rule_list *rules, struct npf_rule *rule)
Insert a rule at the front of given rule list.
- Parameters:
rules – the affected rule list
rule – the rule to be inserted
-
void npf_append_rule(struct npf_rule_list *rules, struct npf_rule *rule)
Append a rule at the end of given rule list.
- Parameters:
rules – the affected rule list
rule – the rule to be appended
-
bool npf_remove_rule(struct npf_rule_list *rules, struct npf_rule *rule)
Remove a rule from the given rule list.
- Parameters:
rules – the affected rule list
rule – the rule to be removed
- Return values:
true – if given rule was found in the rule list and removed
-
bool npf_remove_all_rules(struct npf_rule_list *rules)
Remove all rules from the given rule list.
- Parameters:
rules – the affected rule list
- Return values:
true – if at least one rule was removed from the rule list
Variables
-
struct npf_rule_list npf_send_rules
rule list applied to outgoing packets
-
struct npf_rule_list npf_recv_rules
rule list applied to incoming packets
-
struct npf_rule_list npf_local_in_recv_rules
rule list applied for local incoming packets
-
struct npf_rule_list npf_ipv4_recv_rules
rule list applied for IPv4 incoming packets
-
struct npf_rule_list npf_ipv6_recv_rules
rule list applied for IPv6 incoming packets
-
struct npf_test
- #include <net_pkt_filter.h>
common filter test structure to be embedded into larger structures
Public Members
-
npf_test_fn_t *fn
packet condition test function
-
npf_test_fn_t *fn
-
struct npf_rule
- #include <net_pkt_filter.h>
filter rule structure
Public Members
-
sys_snode_t node
Slist rule list node.
-
enum net_verdict result
result if all tests pass
-
uint32_t nb_tests
number of tests for this rule
-
sys_snode_t node
-
struct npf_rule_list
- #include <net_pkt_filter.h>
rule set for a given test location
Public Members
-
sys_slist_t rule_head
List head.
-
struct k_spinlock lock
Lock protecting the list access.
-
sys_slist_t rule_head
-
NPF_RULE(_name, _result, ...)
- group npf_basic_cond
Defines
-
NPF_IFACE_MATCH(_name, _iface)
Statically define an “interface match” packet filter condition.
- Parameters:
_name – Name of the condition
_iface – Interface to match
-
NPF_IFACE_UNMATCH(_name, _iface)
Statically define an “interface unmatch” packet filter condition.
- Parameters:
_name – Name of the condition
_iface – Interface to exclude
-
NPF_ORIG_IFACE_MATCH(_name, _iface)
Statically define an “orig interface match” packet filter condition.
- Parameters:
_name – Name of the condition
_iface – Interface to match
-
NPF_ORIG_IFACE_UNMATCH(_name, _iface)
Statically define an “orig interface unmatch” packet filter condition.
- Parameters:
_name – Name of the condition
_iface – Interface to exclude
-
NPF_SIZE_MIN(_name, _size)
Statically define a “data minimum size” packet filter condition.
- Parameters:
_name – Name of the condition
_size – Lower bound of the packet’s data size
-
NPF_SIZE_MAX(_name, _size)
Statically define a “data maximum size” packet filter condition.
- Parameters:
_name – Name of the condition
_size – Higher bound of the packet’s data size
-
NPF_SIZE_BOUNDS(_name, _min_size, _max_size)
Statically define a “data bounded size” packet filter condition.
- Parameters:
_name – Name of the condition
_min_size – Lower bound of the packet’s data size
_max_size – Higher bound of the packet’s data size
-
NPF_IP_SRC_ADDR_ALLOWLIST(_name, _ip_addr_array, _ip_addr_num, _af)
Statically define a “ip address allowlist” packet filter condition.
This tests if the packet source ip address matches any of the ip addresses contained in the provided set.
-
NPF_IP_SRC_ADDR_BLOCKLIST(_name, _ip_addr_array, _ip_addr_num, _af)
Statically define a “ip address blocklist” packet filter condition.
This tests if the packet source ip address matches any of the ip addresses contained in the provided set.
-
NPF_IFACE_MATCH(_name, _iface)
- group npf_eth_cond
Defines
-
NPF_ETH_SRC_ADDR_MATCH(_name, _addr_array)
Statically define a “source address match” packet filter condition.
This tests if the packet source address matches any of the Ethernet addresses contained in the provided set.
- Parameters:
_name – Name of the condition
_addr_array – Array of
struct net_eth_addr
items to test against
-
NPF_ETH_SRC_ADDR_UNMATCH(_name, _addr_array)
Statically define a “source address unmatch” packet filter condition.
This tests if the packet source address matches none of the Ethernet addresses contained in the provided set.
- Parameters:
_name – Name of the condition
_addr_array – Array of
struct net_eth_addr
items to test against
-
NPF_ETH_DST_ADDR_MATCH(_name, _addr_array)
Statically define a “destination address match” packet filter condition.
This tests if the packet destination address matches any of the Ethernet addresses contained in the provided set.
- Parameters:
_name – Name of the condition
_addr_array – Array of
struct net_eth_addr
items to test against
-
NPF_ETH_DST_ADDR_UNMATCH(_name, _addr_array)
Statically define a “destination address unmatch” packet filter condition.
This tests if the packet destination address matches none of the Ethernet addresses contained in the provided set.
- Parameters:
_name – Name of the condition
_addr_array – Array of
struct net_eth_addr
items to test against
-
NPF_ETH_SRC_ADDR_MASK_MATCH(_name, _addr_array, ...)
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.
- Parameters:
_name – Name of the condition
_addr_array – Array of
struct net_eth_addr
items to test against... – up to 6 mask bytes
-
NPF_ETH_DST_ADDR_MASK_MATCH(_name, _addr_array, ...)
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.
- Parameters:
_name – Name of the condition
_addr_array – Array of
struct net_eth_addr
items to test against... – up to 6 mask bytes
-
NPF_ETH_TYPE_MATCH(_name, _type)
Statically define an “Ethernet type match” packet filter condition.
- Parameters:
_name – Name of the condition
_type – Ethernet type to match
-
NPF_ETH_TYPE_UNMATCH(_name, _type)
Statically define an “Ethernet type unmatch” packet filter condition.
- Parameters:
_name – Name of the condition
_type – Ethernet type to exclude
-
NPF_ETH_SRC_ADDR_MATCH(_name, _addr_array)