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_insert_send_rule(rule)
npf_insert_recv_rule(rule)
npf_append_send_rule(rule)
npf_append_recv_rule(rule)
npf_remove_send_rule(rule)
npf_remove_recv_rule(rule)
npf_remove_all_send_rules()
npf_remove_all_recv_rules()
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 or NET_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 npf_default_ok

Default rule list termination for accepting a packet.

struct npf_rule npf_default_drop

Default rule list termination for rejecting a packet.

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

struct npf_rule
#include <net_pkt_filter.h>

filter rule structure

Public Members

enum net_verdict result

result if all tests pass

uint32_t nb_tests

number of tests for this rule

struct npf_test *tests[]

pointers to npf_test instances

struct npf_rule_list
#include <net_pkt_filter.h>

rule set for a given test location

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.

Parameters:
  • _name – Name of the condition

  • _ip_addr_array – Array of struct in_addr or struct in6_addr items to test against

  • _ip_addr_num – number of IP addresses in the array

  • _af – Addresses family type (AF_INET / AF_INET6) in the array

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.

Parameters:
  • _name – Name of the condition

  • _ip_addr_array – Array of struct in_addr or struct in6_addr items to test against

  • _ip_addr_num – number of IP addresses in the array

  • _af – Addresses family type (AF_INET / AF_INET6) in the array

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