PFIL(9) | Kernel Developer's Manual | PFIL(9) |
pfil
,
pfil_head_register
,
pfil_head_unregister
,
pfil_head_get
,
pfil_add_hook
,
pfil_add_hook_flags
,
pfil_remove_hook
,
pfil_remove_hook_flags
,
pfil_run_hooks
, pfil_rlock
,
pfil_runlock
, pfil_wlock
,
pfil_wunlock
— packet filter
interface
#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);
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);
int
pfil_add_hook
(pfil_func_t,
void *arg,
struct pfil_head *);
int
pfil_add_hook_flags
(pfil_func_flags_t,
void *arg,
int flags,
struct pfil_head *);
int
pfil_remove_hook
(pfil_func_t,
void *arg,
struct pfil_head *);
int
pfil_remove_hook_flags
(pfil_func_flags_t,
void *arg,
int flags,
struct pfil_head *);
int
pfil_run_hooks
(struct
pfil_head *head, struct
mbuf **mp, struct ifnet
*, int dir,
int flags,
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 *);
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
flags argument will indicate if an outgoing packet is
simply being forwarded with the value PFIL_FWD. 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.
Currently, filtering points are implemented for the following link types:
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!
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.
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.
March 10, 2018 | Debian |