effaab8861
Forwarded packets passed through PFIL_OUT, which made it difficult for firewalls to figure out if they were forwarding or producing packets. This in turn is an issue for pf for IPv6 fragment handling: it needs to call ip6_output() or ip6_forward() to handle the fragments. Figuring out which was difficult (and until now, incorrect). Having pfil distinguish the two removes an ugly piece of code from pf. Introduce a new variant of the netpfil callbacks with a flags variable, which has PFIL_FWD set for forwarded packets. This allows pf to reliably work out if a packet is forwarded. Reviewed by: ae, kevans Differential Revision: https://reviews.freebsd.org/D13715
268 lines
7.3 KiB
Groff
268 lines
7.3 KiB
Groff
.\" $NetBSD: pfil.9,v 1.22 2003/07/01 13:04:06 wiz Exp $
|
|
.\"
|
|
.\" Copyright (c) 1996 Matthew R. Green
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\" 3. The name of the author may not be used to endorse or promote products
|
|
.\" derived from this software without specific prior written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
.\" SUCH DAMAGE.
|
|
.\"
|
|
.\" $FreeBSD$
|
|
.\"
|
|
.Dd March 10, 2018
|
|
.Dt PFIL 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm pfil ,
|
|
.Nm pfil_head_register ,
|
|
.Nm pfil_head_unregister ,
|
|
.Nm pfil_head_get ,
|
|
.Nm pfil_add_hook ,
|
|
.Nm pfil_add_hook_flags ,
|
|
.Nm pfil_remove_hook ,
|
|
.Nm pfil_remove_hook_flags ,
|
|
.Nm pfil_run_hooks ,
|
|
.Nm pfil_rlock ,
|
|
.Nm pfil_runlock ,
|
|
.Nm pfil_wlock ,
|
|
.Nm pfil_wunlock
|
|
.Nd packet filter interface
|
|
.Sh SYNOPSIS
|
|
.In sys/param.h
|
|
.In sys/mbuf.h
|
|
.In net/if.h
|
|
.In net/pfil.h
|
|
.Bd -literal
|
|
typedef int (*pfil_func_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir, struct inpcb);
|
|
.Bd -literal
|
|
typedef int (*pfil_func_flags_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir, int flags, struct inpcb);
|
|
.Ft int
|
|
.Fn pfil_head_register "struct pfil_head *head"
|
|
.Ft int
|
|
.Fn pfil_head_unregister "struct pfil_head *head"
|
|
.Ft "struct pfil_head *"
|
|
.Fn pfil_head_get "int af" "u_long dlt"
|
|
.Ft int
|
|
.Fn pfil_add_hook "pfil_func_t" "void *arg" "struct pfil_head *"
|
|
.Ft int
|
|
.Fn pfil_add_hook_flags "pfil_func_flags_t" "void *arg" "int flags" "struct pfil_head *"
|
|
.Ft int
|
|
.Fn pfil_remove_hook "pfil_func_t" "void *arg" "struct pfil_head *"
|
|
.Ft int
|
|
.Fn pfil_remove_hook_flags "pfil_func_flags_t" "void *arg" "int flags" "struct pfil_head *"
|
|
.Ft int
|
|
.Fn pfil_run_hooks "struct pfil_head *head" "struct mbuf **mp" "struct ifnet *" "int dir" "int flags" "struct inpcb *"
|
|
.Ft void
|
|
.Fn pfil_rlock "struct pfil_head *" "struct rm_priotracker *"
|
|
.Ft void
|
|
.Fn pfil_runlock "struct pfil_head *" "struct rm_priotracker *"
|
|
.Ft void
|
|
.Fn pfil_wlock "struct pfil_head *"
|
|
.Ft void
|
|
.Fn pfil_wunlock "struct pfil_head *"
|
|
.Ed
|
|
.Sh DESCRIPTION
|
|
The
|
|
.Nm
|
|
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.
|
|
.Pp
|
|
Packet filtering points are registered with
|
|
.Fn pfil_head_register .
|
|
Filtering points are identified by a key
|
|
.Pq Vt "void *"
|
|
and a data link type
|
|
.Pq Vt int
|
|
in the
|
|
.Vt 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
|
|
.Xr 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
|
|
.Vt PFIL_FLAG_PRIVATE_LOCK
|
|
as
|
|
.Vt "flags"
|
|
field in the
|
|
.Vt 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
|
|
.Fn pfil_head_unregister
|
|
function.
|
|
.Pp
|
|
Packet filters register/unregister themselves with a filtering point
|
|
with the
|
|
.Fn pfil_add_hook
|
|
and
|
|
.Fn pfil_remove_hook
|
|
functions, respectively.
|
|
.I
|
|
The head is looked up using the
|
|
.Fn 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.
|
|
.Pp
|
|
When a filter is invoked, the packet appears just as if it
|
|
.Dq 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
|
|
.Vt mbuf
|
|
containing the packet, the pointer to the network
|
|
interface that the packet is traversing, and the direction
|
|
.Dv ( PFIL_IN
|
|
or
|
|
.Dv PFIL_OUT )
|
|
that the packet is traveling.
|
|
The
|
|
.Vt flags
|
|
argument will indicate if an outgoing packet is simply being forwarded with the
|
|
value PFIL_FWD.
|
|
The filter may change which mbuf the
|
|
.Vt "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.
|
|
.Pp
|
|
Every filter hook is called with
|
|
.Nm
|
|
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
|
|
.Nm
|
|
uses
|
|
.Xr rmlock 9
|
|
.Fn pfil_rlock
|
|
and
|
|
.Fn pfil_runlock
|
|
require
|
|
.Va struct rm_priotracker
|
|
to be passed as argument.
|
|
Filter can acquire and release writer lock via
|
|
.Fn pfil_wlock
|
|
and
|
|
.Fn pfil_wunlock
|
|
functions.
|
|
See
|
|
.Xr rmlock 9
|
|
for more details.
|
|
.Sh FILTERING POINTS
|
|
Currently, filtering points are implemented for the following link types:
|
|
.Pp
|
|
.Bl -tag -width "AF_INET6" -offset XXX -compact
|
|
.It AF_INET
|
|
IPv4 packets.
|
|
.It AF_INET6
|
|
IPv6 packets.
|
|
.It AF_LINK
|
|
Link-layer packets.
|
|
.El
|
|
.Sh RETURN VALUES
|
|
If successful,
|
|
.Fn pfil_head_get
|
|
returns the
|
|
.Vt pfil_head
|
|
structure for the given key/dlt.
|
|
The
|
|
.Fn pfil_add_hook
|
|
and
|
|
.Fn pfil_remove_hook
|
|
functions
|
|
return 0 if successful.
|
|
If called with flag
|
|
.Dv PFIL_WAITOK ,
|
|
.Fn pfil_remove_hook
|
|
is expected to always succeed.
|
|
.Pp
|
|
The
|
|
.Fn pfil_head_unregister
|
|
function
|
|
might sleep!
|
|
.Sh SEE ALSO
|
|
.Xr bpf 4 ,
|
|
.Xr if_bridge 4 ,
|
|
.Xr rmlock 9
|
|
.Sh HISTORY
|
|
The
|
|
.Nm
|
|
interface first appeared in
|
|
.Nx 1.3 .
|
|
The
|
|
.Nm
|
|
input and output lists were originally implemented as
|
|
.In sys/queue.h
|
|
.Dv LIST
|
|
structures;
|
|
however this was changed in
|
|
.Nx 1.4
|
|
to
|
|
.Dv 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.
|
|
.Pp
|
|
The
|
|
.Nm
|
|
interface was changed in 1.4T to accept a 3rd parameter to both
|
|
.Fn pfil_add_hook
|
|
and
|
|
.Fn pfil_remove_hook ,
|
|
introducing the capability of per-protocol filtering.
|
|
This was done primarily in order to support filtering of IPv6.
|
|
.Pp
|
|
In 1.5K, the
|
|
.Nm
|
|
framework was changed to work with an arbitrary number of filtering points,
|
|
as well as be less IP-centric.
|
|
.Pp
|
|
Fine-grained locking was added in
|
|
.Fx 5.2 .
|
|
.Nm
|
|
lock export was added in
|
|
.Fx 10.0 .
|
|
.Sh BUGS
|
|
When a
|
|
.Vt 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.
|
|
.Fn pfil_run_hooks
|
|
will return
|
|
.Er ENOBUFS
|
|
to indicate this.
|