NAME¶
pfil
,
pfil_head_register
,
pfil_head_unregister
,
pfil_head_get
,
pfil_add_hook
,
pfil_remove_hook
,
pfil_run_hooks
,
pfil_rlock
,
pfil_runlock
,
pfil_wlock
,
pfil_wunlock
—
packet filter interface
SYNOPSIS¶
#include
<sys/param.h>
#include
<sys/mbuf.h>
#include
<net/if.h>
#include
<net/pfil.h>
typedef int (*pfil_func_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir, struct inpcb);
int
pfil_head_register
(struct pfil_head *head);
int
pfil_head_unregister
(struct pfil_head *head);
struct pfil_head *
pfil_head_get
(int af, u_long dlt);
void
pfil_add_hook
(pfil_func_t, void *arg, int flags, struct pfil_head *);
void
pfil_remove_hook
(pfil_func_t, void *arg, int flags, struct pfil_head *);
int
pfil_run_hooks
(struct pfil_head *head, struct mbuf **mp, struct ifnet *, int dir, struct inpcb *);
void
pfil_rlock
(struct pfil_head *, struct rm_priotracker *);
void
pfil_runlock
(struct pfil_head *, struct rm_priotracker *);
void
pfil_wlock
(struct pfil_head *);
void
pfil_wunlock
(struct pfil_head *);
DESCRIPTION¶
The
pfil
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 transformations.
Packet filtering points are registered with
pfil_head_register
(). Filtering points are
identified by a key (
void *) and a data link
type (
int) in the
pfil_head 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
bpf(4) 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
PFIL_FLAG_PRIVATE_LOCK as
flags field in the
pfil_head 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
pfil_head_unregister
() function.
Packet filters register/unregister themselves with a filtering point with the
pfil_add_hook
() and
pfil_remove_hook
() functions, respectively.
The head is looked up using the
pfil_head_get
() 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
the
mbuf containing the packet, the pointer
to the network interface that the packet is traversing, and the direction
(
PFIL_IN
or
PFIL_OUT
) that the packet is traveling. The
filter may change which mbuf the
mbuf ** 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
pfil
read
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.
Since
pfil
uses
rmlock(9)
pfil_rlock
() and
pfil_runlock
() require
struct rm_priotracker to be passed as
argument. Filter can acquire and release writer lock via
pfil_wlock
() and
pfil_wunlock
() functions. See
rmlock(9) for more details.
FILTERING POINTS¶
Currently, filtering points are implemented for the following link types:
- AF_INET
- IPv4 packets.
- AF_INET6
- IPv6 packets.
- AF_LINK
- Link-layer packets.
RETURN VALUES¶
If successful,
pfil_head_get
() returns the
pfil_head structure for the given key/dlt.
The
pfil_add_hook
() and
pfil_remove_hook
() functions return 0 if
successful. If called with flag
PFIL_WAITOK
,
pfil_remove_hook
() is expected to always
succeed.
The
pfil_head_unregister
() function might
sleep!
SEE ALSO¶
bpf(4),
if_bridge(4),
rmlock(9)
HISTORY¶
The
pfil
interface first appeared in
NetBSD 1.3. The
pfil
input and output lists were originally
implemented as
<sys/queue.h>
LIST
structures; however this was changed
in
NetBSD 1.4 to
TAILQ
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.
The
pfil
interface was changed in 1.4T to
accept a 3rd parameter to both
pfil_add_hook
() and
pfil_remove_hook
(), introducing the
capability of per-protocol filtering. This was done primarily in order to
support filtering of IPv6.
In 1.5K, the
pfil
framework was changed to
work with an arbitrary number of filtering points, as well as be less
IP-centric.
Fine-grained locking was added in
FreeBSD 5.2.
pfil
lock export was added in
FreeBSD 10.0.
BUGS¶
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.
pfil_run_hooks
() will return
ENOBUFS
to indicate this.