packet filter interface
typedef int (*pfil_func_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir, struct inpcb);
pfil_head_register(struct pfil_head *head);
pfil_head_unregister(struct pfil_head *head);
struct pfil_head *
pfil_head_get(int af, u_long dlt);
pfil_add_hook(pfil_func_t, void *arg, int flags, struct pfil_head *);
pfil_remove_hook(pfil_func_t, void *arg, int flags, struct pfil_head *);
pfil_run_hooks(struct pfil_head *head, struct mbuf **mp, struct ifnet *, int dir, struct inpcb *);
pfil_rlock(struct pfil_head *, struct rm_priotracker *);
pfil_runlock(struct pfil_head *, struct rm_priotracker *);
pfil_wlock(struct pfil_head *);
pfil_wunlock(struct pfil_head *);
framework allows for a specified
function to be invoked for every incoming or outgoing packet for a particular
network I/O stream. These hooks may be used to implement a firewall or perform
Packet filtering points are registered with
(). Filtering points are
identified by a key (void *
) and a data link
) in the
structure. Packet filters use the
key and data link type to look up the filtering point with which they register
themselves. The key is unique to the filtering point. The data link type is a
DLT constant indicating what kind of
header is present on the packet at the filtering point. Each filtering point
uses common per-VNET rmlock by default. This can be changed by specifying
field in the
structure. Note that specifying
private lock can break filters sharing the same ruleset and/or state between
different data link types. Filtering points may be unregistered with the
Packet filters register/unregister themselves with a filtering point with the
() functions, respectively.
The head is looked up using the
() function, which takes the
key and data link type that the packet filter expects. Filters may provide an
argument to be passed to the filter when invoked on a packet.
When a filter is invoked, the packet appears just as if it “came off the
wire”. That is, all protocol fields are in network byte order. The
filter is called with its specified argument, the pointer to the pointer to
containing the packet, the pointer
to the network interface that the packet is traversing, and the direction
) that the packet is traveling. The
filter may change which mbuf the
argument references. The
filter returns an error (errno) if the packet processing is to stop, or 0 if
the processing is to continue. If the packet processing is to stop, it is the
responsibility of the filter to free the packet.
Every filter hook is called with
lock held. All heads uses the same lock within the same VNET instance. Packet
filter can use this lock instead of own locking model to improve performance.
to be passed as
argument. Filter can acquire and release writer lock via
() functions. See
for more details.
Currently, filtering points are implemented for the following link types:
- IPv4 packets.
- IPv6 packets.
- Link-layer packets.
() returns the
structure for the given key/dlt.
() functions return 0 if
successful. If called with flag
() is expected to always
() function might
interface first appeared in
input and output lists were originally
structures; however this was changed
in NetBSD 1.4
structures. This change was to allow
the input and output filters to be processed in reverse order, to allow the
same path to be taken, in or out of the kernel.
interface was changed in 1.4T to
accept a 3rd parameter to both
(), introducing the
capability of per-protocol filtering. This was done primarily in order to
support filtering of IPv6.
In 1.5K, the
framework was changed to
work with an arbitrary number of filtering points, as well as be less
Fine-grained locking was added in FreeBSD 5.2
lock export was added in
When a pfil_head
is being modified, no traffic
is diverted (to avoid deadlock). This means that traffic may be dropped
unconditionally for a short period of time.
() will return
to indicate this.