0592a4c83d
Add DIOCGETSTATESNV, an nvlist-based alternative to DIOCGETSTATES. MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D30243
1223 lines
29 KiB
Groff
1223 lines
29 KiB
Groff
.\" $OpenBSD: pf.4,v 1.62 2008/09/10 14:57:37 jmc Exp $
|
|
.\"
|
|
.\" Copyright (C) 2001, Kjell Wooding. 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. Neither the name of the project nor the names of its contributors
|
|
.\" may be used to endorse or promote products derived from this software
|
|
.\" without specific prior written permission.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 PROJECT OR CONTRIBUTORS 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 May 7, 2021
|
|
.Dt PF 4
|
|
.Os
|
|
.Sh NAME
|
|
.Nm pf
|
|
.Nd packet filter
|
|
.Sh SYNOPSIS
|
|
.Cd "device pf"
|
|
.Cd "options PF_DEFAULT_TO_DROP"
|
|
.Sh DESCRIPTION
|
|
Packet filtering takes place in the kernel.
|
|
A pseudo-device,
|
|
.Pa /dev/pf ,
|
|
allows userland processes to control the
|
|
behavior of the packet filter through an
|
|
.Xr ioctl 2
|
|
interface.
|
|
There are commands to enable and disable the filter, load rulesets,
|
|
add and remove individual rules or state table entries,
|
|
and retrieve statistics.
|
|
The most commonly used functions are covered by
|
|
.Xr pfctl 8 .
|
|
.Pp
|
|
Manipulations like loading a ruleset that involve more than a single
|
|
.Xr ioctl 2
|
|
call require a so-called
|
|
.Em ticket ,
|
|
which prevents the occurrence of
|
|
multiple concurrent manipulations.
|
|
.Pp
|
|
Fields of
|
|
.Xr ioctl 2
|
|
parameter structures that refer to packet data (like
|
|
addresses and ports) are generally expected in network byte-order.
|
|
.Pp
|
|
Rules and address tables are contained in so-called
|
|
.Em anchors .
|
|
When servicing an
|
|
.Xr ioctl 2
|
|
request, if the anchor field of the argument structure is empty,
|
|
the kernel will use the default anchor (i.e., the main ruleset)
|
|
in operations.
|
|
Anchors are specified by name and may be nested, with components
|
|
separated by
|
|
.Sq /
|
|
characters, similar to how file system hierarchies are laid out.
|
|
The final component of the anchor path is the anchor under which
|
|
operations will be performed.
|
|
.Sh SYSCTL VARIABLES AND LOADER TUNABLES
|
|
The following
|
|
.Xr loader 8
|
|
tunables are available.
|
|
.Bl -tag -width indent
|
|
.It Va net.pf.states_hashsize
|
|
Size of hash tables that store states.
|
|
Should be power of 2.
|
|
Default value is 131072.
|
|
.It Va net.pf.source_nodes_hashsize
|
|
Size of hash table that store source nodes.
|
|
Should be power of 2.
|
|
Default value is 32768.
|
|
.El
|
|
.Pp
|
|
Read only
|
|
.Xr sysctl 8
|
|
variables with matching names are provided to obtain current values
|
|
at runtime.
|
|
.Sh KERNEL OPTIONS
|
|
The following options in the kernel configuration file are related to
|
|
.Nm
|
|
operation:
|
|
.Pp
|
|
.Bl -tag -width ".Dv PF_DEFAULT_TO_DROP" -compact
|
|
.It Dv PF_DEFAULT_TO_DROP
|
|
Change default policy to drop by default
|
|
.El
|
|
.Sh IOCTL INTERFACE
|
|
.Nm
|
|
supports the following
|
|
.Xr ioctl 2
|
|
commands, available through
|
|
.Aq Pa net/pfvar.h :
|
|
.Bl -tag -width xxxxxx
|
|
.It Dv DIOCSTART
|
|
Start the packet filter.
|
|
.It Dv DIOCSTOP
|
|
Stop the packet filter.
|
|
.It Dv DIOCSTARTALTQ
|
|
Start the ALTQ bandwidth control system (see
|
|
.Xr altq 9 ) .
|
|
.It Dv DIOCSTOPALTQ
|
|
Stop the ALTQ bandwidth control system.
|
|
.It Dv DIOCBEGINADDRS Fa "struct pfioc_pooladdr *pp"
|
|
.Bd -literal
|
|
struct pfioc_pooladdr {
|
|
u_int32_t action;
|
|
u_int32_t ticket;
|
|
u_int32_t nr;
|
|
u_int32_t r_num;
|
|
u_int8_t r_action;
|
|
u_int8_t r_last;
|
|
u_int8_t af;
|
|
char anchor[MAXPATHLEN];
|
|
struct pf_pooladdr addr;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
Clear the buffer address pool and get a
|
|
.Va ticket
|
|
for subsequent
|
|
.Dv DIOCADDADDR ,
|
|
.Dv DIOCADDRULE ,
|
|
and
|
|
.Dv DIOCCHANGERULE
|
|
calls.
|
|
.It Dv DIOCADDADDR Fa "struct pfioc_pooladdr *pp"
|
|
.Pp
|
|
Add the pool address
|
|
.Va addr
|
|
to the buffer address pool to be used in the following
|
|
.Dv DIOCADDRULE
|
|
or
|
|
.Dv DIOCCHANGERULE
|
|
call.
|
|
All other members of the structure are ignored.
|
|
.It Dv DIOCADDRULE Fa "struct pfioc_rule *pr"
|
|
.Bd -literal
|
|
struct pfioc_rule {
|
|
u_int32_t action;
|
|
u_int32_t ticket;
|
|
u_int32_t pool_ticket;
|
|
u_int32_t nr;
|
|
char anchor[MAXPATHLEN];
|
|
char anchor_call[MAXPATHLEN];
|
|
struct pf_rule rule;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
Add
|
|
.Va rule
|
|
at the end of the inactive ruleset.
|
|
This call requires a
|
|
.Va ticket
|
|
obtained through a preceding
|
|
.Dv DIOCXBEGIN
|
|
call and a
|
|
.Va pool_ticket
|
|
obtained through a
|
|
.Dv DIOCBEGINADDRS
|
|
call.
|
|
.Dv DIOCADDADDR
|
|
must also be called if any pool addresses are required.
|
|
The optional
|
|
.Va anchor
|
|
name indicates the anchor in which to append the rule.
|
|
.Va nr
|
|
and
|
|
.Va action
|
|
are ignored.
|
|
.It Dv DIOCADDALTQ Fa "struct pfioc_altq *pa"
|
|
Add an ALTQ discipline or queue.
|
|
.Bd -literal
|
|
struct pfioc_altq {
|
|
u_int32_t action;
|
|
u_int32_t ticket;
|
|
u_int32_t nr;
|
|
struct pf_altq altq;
|
|
};
|
|
.Ed
|
|
.It Dv DIOCGETRULES Fa "struct pfioc_rule *pr"
|
|
Get a
|
|
.Va ticket
|
|
for subsequent
|
|
.Dv DIOCGETRULE
|
|
calls and the number
|
|
.Va nr
|
|
of rules in the active ruleset.
|
|
.It Dv DIOCGETRULE Fa "struct pfioc_rule *pr"
|
|
Get a
|
|
.Va rule
|
|
by its number
|
|
.Va nr
|
|
using the
|
|
.Va ticket
|
|
obtained through a preceding
|
|
.Dv DIOCGETRULES
|
|
call.
|
|
If
|
|
.Va action
|
|
is set to
|
|
.Dv PF_GET_CLR_CNTR ,
|
|
the per-rule statistics on the requested rule are cleared.
|
|
.It Dv DIOCGETADDRS Fa "struct pfioc_pooladdr *pp"
|
|
Get a
|
|
.Va ticket
|
|
for subsequent
|
|
.Dv DIOCGETADDR
|
|
calls and the number
|
|
.Va nr
|
|
of pool addresses in the rule specified with
|
|
.Va r_action ,
|
|
.Va r_num ,
|
|
and
|
|
.Va anchor .
|
|
.It Dv DIOCGETADDR Fa "struct pfioc_pooladdr *pp"
|
|
Get the pool address
|
|
.Va addr
|
|
by its number
|
|
.Va nr
|
|
from the rule specified with
|
|
.Va r_action ,
|
|
.Va r_num ,
|
|
and
|
|
.Va anchor
|
|
using the
|
|
.Va ticket
|
|
obtained through a preceding
|
|
.Dv DIOCGETADDRS
|
|
call.
|
|
.It Dv DIOCGETALTQS Fa "struct pfioc_altq *pa"
|
|
Get a
|
|
.Va ticket
|
|
for subsequent
|
|
.Dv DIOCGETALTQ
|
|
calls and the number
|
|
.Va nr
|
|
of queues in the active list.
|
|
.It Dv DIOCGETALTQ Fa "struct pfioc_altq *pa"
|
|
Get the queueing discipline
|
|
.Va altq
|
|
by its number
|
|
.Va nr
|
|
using the
|
|
.Va ticket
|
|
obtained through a preceding
|
|
.Dv DIOCGETALTQS
|
|
call.
|
|
.It Dv DIOCGETQSTATS Fa "struct pfioc_qstats *pq"
|
|
Get the statistics on a queue.
|
|
.Bd -literal
|
|
struct pfioc_qstats {
|
|
u_int32_t ticket;
|
|
u_int32_t nr;
|
|
void *buf;
|
|
int nbytes;
|
|
u_int8_t scheduler;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
This call fills in a pointer to the buffer of statistics
|
|
.Va buf ,
|
|
of length
|
|
.Va nbytes ,
|
|
for the queue specified by
|
|
.Va nr .
|
|
.It Dv DIOCGETRULESETS Fa "struct pfioc_ruleset *pr"
|
|
.Bd -literal
|
|
struct pfioc_ruleset {
|
|
u_int32_t nr;
|
|
char path[MAXPATHLEN];
|
|
char name[PF_ANCHOR_NAME_SIZE];
|
|
};
|
|
.Ed
|
|
.Pp
|
|
Get the number
|
|
.Va nr
|
|
of rulesets (i.e., anchors) directly attached to the anchor named by
|
|
.Va path
|
|
for use in subsequent
|
|
.Dv DIOCGETRULESET
|
|
calls.
|
|
Nested anchors, since they are not directly attached to the given
|
|
anchor, will not be included.
|
|
This ioctl returns
|
|
.Er EINVAL
|
|
if the given anchor does not exist.
|
|
.It Dv DIOCGETRULESET Fa "struct pfioc_ruleset *pr"
|
|
Get a ruleset (i.e., an anchor)
|
|
.Va name
|
|
by its number
|
|
.Va nr
|
|
from the given anchor
|
|
.Va path ,
|
|
the maximum number of which can be obtained from a preceding
|
|
.Dv DIOCGETRULESETS
|
|
call.
|
|
This ioctl returns
|
|
.Er EINVAL
|
|
if the given anchor does not exist or
|
|
.Er EBUSY
|
|
if another process is concurrently updating a ruleset.
|
|
.It Dv DIOCADDSTATE Fa "struct pfioc_state *ps"
|
|
Add a state entry.
|
|
.Bd -literal
|
|
struct pfioc_state {
|
|
struct pfsync_state state;
|
|
};
|
|
.Ed
|
|
.It Dv DIOCGETSTATENV Fa "struct pfioc_nv *nv"
|
|
Extract the entry identified by the
|
|
.Va id
|
|
and
|
|
.Va creatorid
|
|
fields of the
|
|
.Va state
|
|
nvlist from the state table.
|
|
.It Dv DIOCKILLSTATES Fa "struct pfioc_state_kill *psk"
|
|
Remove matching entries from the state table.
|
|
This ioctl returns the number of killed states in
|
|
.Va psk_killed .
|
|
.Bd -literal
|
|
struct pfioc_state_kill {
|
|
struct pf_state_cmp psk_pfcmp;
|
|
sa_family_t psk_af;
|
|
int psk_proto;
|
|
struct pf_rule_addr psk_src;
|
|
struct pf_rule_addr psk_dst;
|
|
char psk_ifname[IFNAMSIZ];
|
|
char psk_label[PF_RULE_LABEL_SIZE];
|
|
u_int psk_killed;
|
|
};
|
|
.Ed
|
|
.It Dv DIOCCLRSTATES Fa "struct pfioc_state_kill *psk"
|
|
Clear all states.
|
|
It works like
|
|
.Dv DIOCKILLSTATES ,
|
|
but ignores the
|
|
.Va psk_af ,
|
|
.Va psk_proto ,
|
|
.Va psk_src ,
|
|
and
|
|
.Va psk_dst
|
|
fields of the
|
|
.Vt pfioc_state_kill
|
|
structure.
|
|
.It Dv DIOCSETSTATUSIF Fa "struct pfioc_if *pi"
|
|
Specify the interface for which statistics are accumulated.
|
|
.Bd -literal
|
|
struct pfioc_if {
|
|
char ifname[IFNAMSIZ];
|
|
};
|
|
.Ed
|
|
.It Dv DIOCGETSTATUS Fa "struct pf_status *s"
|
|
Get the internal packet filter statistics.
|
|
.Bd -literal
|
|
struct pf_status {
|
|
u_int64_t counters[PFRES_MAX];
|
|
u_int64_t lcounters[LCNT_MAX];
|
|
u_int64_t fcounters[FCNT_MAX];
|
|
u_int64_t scounters[SCNT_MAX];
|
|
u_int64_t pcounters[2][2][3];
|
|
u_int64_t bcounters[2][2];
|
|
u_int32_t running;
|
|
u_int32_t states;
|
|
u_int32_t src_nodes;
|
|
u_int32_t since;
|
|
u_int32_t debug;
|
|
u_int32_t hostid;
|
|
char ifname[IFNAMSIZ];
|
|
u_int8_t pf_chksum[MD5_DIGEST_LENGTH];
|
|
};
|
|
.Ed
|
|
.It Dv DIOCCLRSTATUS
|
|
Clear the internal packet filter statistics.
|
|
.It Dv DIOCNATLOOK Fa "struct pfioc_natlook *pnl"
|
|
Look up a state table entry by source and destination addresses and ports.
|
|
.Bd -literal
|
|
struct pfioc_natlook {
|
|
struct pf_addr saddr;
|
|
struct pf_addr daddr;
|
|
struct pf_addr rsaddr;
|
|
struct pf_addr rdaddr;
|
|
u_int16_t sport;
|
|
u_int16_t dport;
|
|
u_int16_t rsport;
|
|
u_int16_t rdport;
|
|
sa_family_t af;
|
|
u_int8_t proto;
|
|
u_int8_t direction;
|
|
};
|
|
.Ed
|
|
.It Dv DIOCSETDEBUG Fa "u_int32_t *level"
|
|
Set the debug level.
|
|
.Bd -literal
|
|
enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC,
|
|
PF_DEBUG_NOISY };
|
|
.Ed
|
|
.It Dv DIOCGETSTATESNV Fa "struct pfioc_nv *nv"
|
|
Get state table entries.
|
|
.Bd -literal
|
|
nvlist pf_state_key {
|
|
nvlist pf_addr addr[2];
|
|
number port[2];
|
|
number af;
|
|
number proto;
|
|
};
|
|
|
|
nvlist pf_state_scrub {
|
|
bool timestamp;
|
|
number ttl;
|
|
number ts_mod;
|
|
};
|
|
|
|
nvlist pf_state_peer {
|
|
nvlist pf_state_scrub scrub;
|
|
number seqlo;
|
|
number seqhi;
|
|
number seqdiff;
|
|
number max_win;
|
|
number mss;
|
|
number state;
|
|
number wscale;
|
|
};
|
|
|
|
nvlist pf_state {
|
|
number id;
|
|
string ifname;
|
|
nvlist pf_state_key stack_key;
|
|
nvlist pf_state_key wire_key;
|
|
nvlist pf_state_peer src;
|
|
nvlist pf_state_peer dst;
|
|
nvlist pf_addr rt_addr;
|
|
number rule;
|
|
number anchor;
|
|
number nat_rule;
|
|
number expire;
|
|
number packets[2];
|
|
number bytes[2];
|
|
number creatorid;
|
|
number direction;
|
|
number log;
|
|
number state_flags;
|
|
number timeout;
|
|
number sync_flags;
|
|
};
|
|
|
|
nvlist pf_states {
|
|
number count;
|
|
nvlist pf_state states[];
|
|
};
|
|
.Ed
|
|
.Pp
|
|
If
|
|
.Va pfioc_nv.size
|
|
is insufficiently large, as many states as possible that can fit into this
|
|
size will be copied into the supplied buffer.
|
|
.It Dv DIOCCHANGERULE Fa "struct pfioc_rule *pcr"
|
|
Add or remove the
|
|
.Va rule
|
|
in the ruleset specified by
|
|
.Va rule.action .
|
|
.Pp
|
|
The type of operation to be performed is indicated by
|
|
.Va action ,
|
|
which can be any of the following:
|
|
.Bd -literal
|
|
enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL,
|
|
PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER,
|
|
PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET };
|
|
.Ed
|
|
.Pp
|
|
.Va ticket
|
|
must be set to the value obtained with
|
|
.Dv PF_CHANGE_GET_TICKET
|
|
for all actions except
|
|
.Dv PF_CHANGE_GET_TICKET .
|
|
.Va pool_ticket
|
|
must be set to the value obtained with the
|
|
.Dv DIOCBEGINADDRS
|
|
call for all actions except
|
|
.Dv PF_CHANGE_REMOVE
|
|
and
|
|
.Dv PF_CHANGE_GET_TICKET .
|
|
.Va anchor
|
|
indicates to which anchor the operation applies.
|
|
.Va nr
|
|
indicates the rule number against which
|
|
.Dv PF_CHANGE_ADD_BEFORE ,
|
|
.Dv PF_CHANGE_ADD_AFTER ,
|
|
or
|
|
.Dv PF_CHANGE_REMOVE
|
|
actions are applied.
|
|
.\" It Dv DIOCCHANGEALTQ Fa "struct pfioc_altq *pcr"
|
|
.It Dv DIOCCHANGEADDR Fa "struct pfioc_pooladdr *pca"
|
|
Add or remove the pool address
|
|
.Va addr
|
|
from the rule specified by
|
|
.Va r_action ,
|
|
.Va r_num ,
|
|
and
|
|
.Va anchor .
|
|
.It Dv DIOCSETTIMEOUT Fa "struct pfioc_tm *pt"
|
|
.Bd -literal
|
|
struct pfioc_tm {
|
|
int timeout;
|
|
int seconds;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
Set the state timeout of
|
|
.Va timeout
|
|
to
|
|
.Va seconds .
|
|
The old value will be placed into
|
|
.Va seconds .
|
|
For possible values of
|
|
.Va timeout ,
|
|
consult the
|
|
.Dv PFTM_*
|
|
values in
|
|
.Aq Pa net/pfvar.h .
|
|
.It Dv DIOCGETTIMEOUT Fa "struct pfioc_tm *pt"
|
|
Get the state timeout of
|
|
.Va timeout .
|
|
The value will be placed into the
|
|
.Va seconds
|
|
field.
|
|
.It Dv DIOCCLRRULECTRS
|
|
Clear per-rule statistics.
|
|
.It Dv DIOCSETLIMIT Fa "struct pfioc_limit *pl"
|
|
Set the hard limits on the memory pools used by the packet filter.
|
|
.Bd -literal
|
|
struct pfioc_limit {
|
|
int index;
|
|
unsigned limit;
|
|
};
|
|
|
|
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS,
|
|
PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX };
|
|
.Ed
|
|
.It Dv DIOCGETLIMIT Fa "struct pfioc_limit *pl"
|
|
Get the hard
|
|
.Va limit
|
|
for the memory pool indicated by
|
|
.Va index .
|
|
.It Dv DIOCRCLRTABLES Fa "struct pfioc_table *io"
|
|
Clear all tables.
|
|
All the ioctls that manipulate radix tables
|
|
use the same structure described below.
|
|
For
|
|
.Dv DIOCRCLRTABLES ,
|
|
.Va pfrio_ndel
|
|
contains on exit the number of tables deleted.
|
|
.Bd -literal
|
|
struct pfioc_table {
|
|
struct pfr_table pfrio_table;
|
|
void *pfrio_buffer;
|
|
int pfrio_esize;
|
|
int pfrio_size;
|
|
int pfrio_size2;
|
|
int pfrio_nadd;
|
|
int pfrio_ndel;
|
|
int pfrio_nchange;
|
|
int pfrio_flags;
|
|
u_int32_t pfrio_ticket;
|
|
};
|
|
#define pfrio_exists pfrio_nadd
|
|
#define pfrio_nzero pfrio_nadd
|
|
#define pfrio_nmatch pfrio_nadd
|
|
#define pfrio_naddr pfrio_size2
|
|
#define pfrio_setflag pfrio_size2
|
|
#define pfrio_clrflag pfrio_nadd
|
|
.Ed
|
|
.It Dv DIOCRADDTABLES Fa "struct pfioc_table *io"
|
|
Create one or more tables.
|
|
On entry,
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_table
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_table .
|
|
On exit,
|
|
.Va pfrio_nadd
|
|
contains the number of tables effectively created.
|
|
.Bd -literal
|
|
struct pfr_table {
|
|
char pfrt_anchor[MAXPATHLEN];
|
|
char pfrt_name[PF_TABLE_NAME_SIZE];
|
|
u_int32_t pfrt_flags;
|
|
u_int8_t pfrt_fback;
|
|
};
|
|
.Ed
|
|
.It Dv DIOCRDELTABLES Fa "struct pfioc_table *io"
|
|
Delete one or more tables.
|
|
On entry,
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_table
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_table .
|
|
On exit,
|
|
.Va pfrio_ndel
|
|
contains the number of tables effectively deleted.
|
|
.It Dv DIOCRGETTABLES Fa "struct pfioc_table *io"
|
|
Get the list of all tables.
|
|
On entry,
|
|
.Va pfrio_buffer[pfrio_size]
|
|
contains a valid writeable buffer for
|
|
.Vt pfr_table
|
|
structures.
|
|
On exit,
|
|
.Va pfrio_size
|
|
contains the number of tables written into the buffer.
|
|
If the buffer is too small, the kernel does not store anything but just
|
|
returns the required buffer size, without error.
|
|
.It Dv DIOCRGETTSTATS Fa "struct pfioc_table *io"
|
|
This call is like
|
|
.Dv DIOCRGETTABLES
|
|
but is used to get an array of
|
|
.Vt pfr_tstats
|
|
structures.
|
|
.Bd -literal
|
|
struct pfr_tstats {
|
|
struct pfr_table pfrts_t;
|
|
u_int64_t pfrts_packets
|
|
[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
|
|
u_int64_t pfrts_bytes
|
|
[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
|
|
u_int64_t pfrts_match;
|
|
u_int64_t pfrts_nomatch;
|
|
long pfrts_tzero;
|
|
int pfrts_cnt;
|
|
int pfrts_refcnt[PFR_REFCNT_MAX];
|
|
};
|
|
#define pfrts_name pfrts_t.pfrt_name
|
|
#define pfrts_flags pfrts_t.pfrt_flags
|
|
.Ed
|
|
.It Dv DIOCRCLRTSTATS Fa "struct pfioc_table *io"
|
|
Clear the statistics of one or more tables.
|
|
On entry,
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_table
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_table .
|
|
On exit,
|
|
.Va pfrio_nzero
|
|
contains the number of tables effectively cleared.
|
|
.It Dv DIOCRCLRADDRS Fa "struct pfioc_table *io"
|
|
Clear all addresses in a table.
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table to clear.
|
|
On exit,
|
|
.Va pfrio_ndel
|
|
contains the number of addresses removed.
|
|
.It Dv DIOCRADDADDRS Fa "struct pfioc_table *io"
|
|
Add one or more addresses to a table.
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table ID and
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_addr
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements to add to the table.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_addr .
|
|
On exit,
|
|
.Va pfrio_nadd
|
|
contains the number of addresses effectively added.
|
|
.Bd -literal
|
|
struct pfr_addr {
|
|
union {
|
|
struct in_addr _pfra_ip4addr;
|
|
struct in6_addr _pfra_ip6addr;
|
|
} pfra_u;
|
|
u_int8_t pfra_af;
|
|
u_int8_t pfra_net;
|
|
u_int8_t pfra_not;
|
|
u_int8_t pfra_fback;
|
|
};
|
|
#define pfra_ip4addr pfra_u._pfra_ip4addr
|
|
#define pfra_ip6addr pfra_u._pfra_ip6addr
|
|
.Ed
|
|
.It Dv DIOCRDELADDRS Fa "struct pfioc_table *io"
|
|
Delete one or more addresses from a table.
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table ID and
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_addr
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements to delete from the table.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_addr .
|
|
On exit,
|
|
.Va pfrio_ndel
|
|
contains the number of addresses effectively deleted.
|
|
.It Dv DIOCRSETADDRS Fa "struct pfioc_table *io"
|
|
Replace the content of a table by a new address list.
|
|
This is the most complicated command, which uses all the structure members.
|
|
.Pp
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table ID and
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_addr
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements which become the new contents of the table.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_addr .
|
|
Additionally, if
|
|
.Va pfrio_size2
|
|
is non-zero,
|
|
.Va pfrio_buffer[pfrio_size..pfrio_size2]
|
|
must be a writeable buffer, into which the kernel can copy the
|
|
addresses that have been deleted during the replace operation.
|
|
On exit,
|
|
.Va pfrio_ndel ,
|
|
.Va pfrio_nadd ,
|
|
and
|
|
.Va pfrio_nchange
|
|
contain the number of addresses deleted, added, and changed by the
|
|
kernel.
|
|
If
|
|
.Va pfrio_size2
|
|
was set on entry,
|
|
.Va pfrio_size2
|
|
will point to the size of the buffer used, exactly like
|
|
.Dv DIOCRGETADDRS .
|
|
.It Dv DIOCRGETADDRS Fa "struct pfioc_table *io"
|
|
Get all the addresses of a table.
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table ID and
|
|
.Va pfrio_buffer[pfrio_size]
|
|
contains a valid writeable buffer for
|
|
.Vt pfr_addr
|
|
structures.
|
|
On exit,
|
|
.Va pfrio_size
|
|
contains the number of addresses written into the buffer.
|
|
If the buffer was too small, the kernel does not store anything but just
|
|
returns the required buffer size, without returning an error.
|
|
.It Dv DIOCRGETASTATS Fa "struct pfioc_table *io"
|
|
This call is like
|
|
.Dv DIOCRGETADDRS
|
|
but is used to get an array of
|
|
.Vt pfr_astats
|
|
structures.
|
|
.Bd -literal
|
|
struct pfr_astats {
|
|
struct pfr_addr pfras_a;
|
|
u_int64_t pfras_packets
|
|
[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
|
|
u_int64_t pfras_bytes
|
|
[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
|
|
long pfras_tzero;
|
|
};
|
|
.Ed
|
|
.It Dv DIOCRCLRASTATS Fa "struct pfioc_table *io"
|
|
Clear the statistics of one or more addresses.
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table ID and
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_addr
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements to be cleared from the table.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_addr .
|
|
On exit,
|
|
.Va pfrio_nzero
|
|
contains the number of addresses effectively cleared.
|
|
.It Dv DIOCRTSTADDRS Fa "struct pfioc_table *io"
|
|
Test if the given addresses match a table.
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table ID and
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_addr
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements, each of which will be tested for a match in the table.
|
|
.Vt pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_addr .
|
|
On exit, the kernel updates the
|
|
.Vt pfr_addr
|
|
array by setting the
|
|
.Va pfra_fback
|
|
member appropriately.
|
|
.It Dv DIOCRSETTFLAGS Fa "struct pfioc_table *io"
|
|
Change the
|
|
.Dv PFR_TFLAG_CONST
|
|
or
|
|
.Dv PFR_TFLAG_PERSIST
|
|
flags of a table.
|
|
On entry,
|
|
.Va pfrio_buffer
|
|
must point to an array of
|
|
.Vt struct pfr_table
|
|
containing at least
|
|
.Vt pfrio_size
|
|
elements.
|
|
.Va pfrio_esize
|
|
must be the size of
|
|
.Vt struct pfr_table .
|
|
.Va pfrio_setflag
|
|
must contain the flags to add, while
|
|
.Va pfrio_clrflag
|
|
must contain the flags to remove.
|
|
On exit,
|
|
.Va pfrio_nchange
|
|
and
|
|
.Va pfrio_ndel
|
|
contain the number of tables altered or deleted by the kernel.
|
|
Yes, tables can be deleted if one removes the
|
|
.Dv PFR_TFLAG_PERSIST
|
|
flag of an unreferenced table.
|
|
.It Dv DIOCRINADEFINE Fa "struct pfioc_table *io"
|
|
Defines a table in the inactive set.
|
|
On entry,
|
|
.Va pfrio_table
|
|
contains the table ID and
|
|
.Va pfrio_buffer[pfrio_size]
|
|
contains an array of
|
|
.Vt pfr_addr
|
|
structures to put in the table.
|
|
A valid ticket must also be supplied to
|
|
.Va pfrio_ticket .
|
|
On exit,
|
|
.Va pfrio_nadd
|
|
contains 0 if the table was already defined in the inactive list
|
|
or 1 if a new table has been created.
|
|
.Va pfrio_naddr
|
|
contains the number of addresses effectively put in the table.
|
|
.It Dv DIOCXBEGIN Fa "struct pfioc_trans *io"
|
|
.Bd -literal
|
|
struct pfioc_trans {
|
|
int size; /* number of elements */
|
|
int esize; /* size of each element in bytes */
|
|
struct pfioc_trans_e {
|
|
int rs_num;
|
|
char anchor[MAXPATHLEN];
|
|
u_int32_t ticket;
|
|
} *array;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
Clear all the inactive rulesets specified in the
|
|
.Vt pfioc_trans_e
|
|
array.
|
|
For each ruleset, a ticket is returned for subsequent "add rule" ioctls,
|
|
as well as for the
|
|
.Dv DIOCXCOMMIT
|
|
and
|
|
.Dv DIOCXROLLBACK
|
|
calls.
|
|
.Pp
|
|
Ruleset types, identified by
|
|
.Va rs_num ,
|
|
include the following:
|
|
.Pp
|
|
.Bl -tag -width PF_RULESET_FILTER -offset ind -compact
|
|
.It Dv PF_RULESET_SCRUB
|
|
Scrub (packet normalization) rules.
|
|
.It Dv PF_RULESET_FILTER
|
|
Filter rules.
|
|
.It Dv PF_RULESET_NAT
|
|
NAT (Network Address Translation) rules.
|
|
.It Dv PF_RULESET_BINAT
|
|
Bidirectional NAT rules.
|
|
.It Dv PF_RULESET_RDR
|
|
Redirect rules.
|
|
.It Dv PF_RULESET_ALTQ
|
|
ALTQ disciplines.
|
|
.It Dv PF_RULESET_TABLE
|
|
Address tables.
|
|
.El
|
|
.It Dv DIOCXCOMMIT Fa "struct pfioc_trans *io"
|
|
Atomically switch a vector of inactive rulesets to the active rulesets.
|
|
This call is implemented as a standard two-phase commit, which will either
|
|
fail for all rulesets or completely succeed.
|
|
All tickets need to be valid.
|
|
This ioctl returns
|
|
.Er EBUSY
|
|
if another process is concurrently updating some of the same rulesets.
|
|
.It Dv DIOCXROLLBACK Fa "struct pfioc_trans *io"
|
|
Clean up the kernel by undoing all changes that have taken place on the
|
|
inactive rulesets since the last
|
|
.Dv DIOCXBEGIN .
|
|
.Dv DIOCXROLLBACK
|
|
will silently ignore rulesets for which the ticket is invalid.
|
|
.It Dv DIOCSETHOSTID Fa "u_int32_t *hostid"
|
|
Set the host ID, which is used by
|
|
.Xr pfsync 4
|
|
to identify which host created state table entries.
|
|
.It Dv DIOCOSFPFLUSH
|
|
Flush the passive OS fingerprint table.
|
|
.It Dv DIOCOSFPADD Fa "struct pf_osfp_ioctl *io"
|
|
.Bd -literal
|
|
struct pf_osfp_ioctl {
|
|
struct pf_osfp_entry {
|
|
SLIST_ENTRY(pf_osfp_entry) fp_entry;
|
|
pf_osfp_t fp_os;
|
|
char fp_class_nm[PF_OSFP_LEN];
|
|
char fp_version_nm[PF_OSFP_LEN];
|
|
char fp_subtype_nm[PF_OSFP_LEN];
|
|
} fp_os;
|
|
pf_tcpopts_t fp_tcpopts;
|
|
u_int16_t fp_wsize;
|
|
u_int16_t fp_psize;
|
|
u_int16_t fp_mss;
|
|
u_int16_t fp_flags;
|
|
u_int8_t fp_optcnt;
|
|
u_int8_t fp_wscale;
|
|
u_int8_t fp_ttl;
|
|
int fp_getnum;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
Add a passive OS fingerprint to the table.
|
|
Set
|
|
.Va fp_os.fp_os
|
|
to the packed fingerprint,
|
|
.Va fp_os.fp_class_nm
|
|
to the name of the class (Linux, Windows, etc),
|
|
.Va fp_os.fp_version_nm
|
|
to the name of the version (NT, 95, 98), and
|
|
.Va fp_os.fp_subtype_nm
|
|
to the name of the subtype or patchlevel.
|
|
The members
|
|
.Va fp_mss ,
|
|
.Va fp_wsize ,
|
|
.Va fp_psize ,
|
|
.Va fp_ttl ,
|
|
.Va fp_optcnt ,
|
|
and
|
|
.Va fp_wscale
|
|
are set to the TCP MSS, the TCP window size, the IP length, the IP TTL,
|
|
the number of TCP options, and the TCP window scaling constant of the
|
|
TCP SYN packet, respectively.
|
|
.Pp
|
|
The
|
|
.Va fp_flags
|
|
member is filled according to the
|
|
.Aq Pa net/pfvar.h
|
|
include file
|
|
.Dv PF_OSFP_*
|
|
defines.
|
|
The
|
|
.Va fp_tcpopts
|
|
member contains packed TCP options.
|
|
Each option uses
|
|
.Dv PF_OSFP_TCPOPT_BITS
|
|
bits in the packed value.
|
|
Options include any of
|
|
.Dv PF_OSFP_TCPOPT_NOP ,
|
|
.Dv PF_OSFP_TCPOPT_SACK ,
|
|
.Dv PF_OSFP_TCPOPT_WSCALE ,
|
|
.Dv PF_OSFP_TCPOPT_MSS ,
|
|
or
|
|
.Dv PF_OSFP_TCPOPT_TS .
|
|
.Pp
|
|
The
|
|
.Va fp_getnum
|
|
member is not used with this ioctl.
|
|
.Pp
|
|
The structure's slack space must be zeroed for correct operation;
|
|
.Xr memset 3
|
|
the whole structure to zero before filling and sending to the kernel.
|
|
.It Dv DIOCOSFPGET Fa "struct pf_osfp_ioctl *io"
|
|
Get the passive OS fingerprint number
|
|
.Va fp_getnum
|
|
from the kernel's fingerprint list.
|
|
The rest of the structure members will come back filled.
|
|
Get the whole list by repeatedly incrementing the
|
|
.Va fp_getnum
|
|
number until the ioctl returns
|
|
.Er EBUSY .
|
|
.It Dv DIOCGETSRCNODES Fa "struct pfioc_src_nodes *psn"
|
|
.Bd -literal
|
|
struct pfioc_src_nodes {
|
|
int psn_len;
|
|
union {
|
|
caddr_t psu_buf;
|
|
struct pf_src_node *psu_src_nodes;
|
|
} psn_u;
|
|
#define psn_buf psn_u.psu_buf
|
|
#define psn_src_nodes psn_u.psu_src_nodes
|
|
};
|
|
.Ed
|
|
.Pp
|
|
Get the list of source nodes kept by sticky addresses and source
|
|
tracking.
|
|
The ioctl must be called once with
|
|
.Va psn_len
|
|
set to 0.
|
|
If the ioctl returns without error,
|
|
.Va psn_len
|
|
will be set to the size of the buffer required to hold all the
|
|
.Va pf_src_node
|
|
structures held in the table.
|
|
A buffer of this size should then be allocated, and a pointer to this buffer
|
|
placed in
|
|
.Va psn_buf .
|
|
The ioctl must then be called again to fill this buffer with the actual
|
|
source node data.
|
|
After that call,
|
|
.Va psn_len
|
|
will be set to the length of the buffer actually used.
|
|
.It Dv DIOCCLRSRCNODES
|
|
Clear the tree of source tracking nodes.
|
|
.It Dv DIOCIGETIFACES Fa "struct pfioc_iface *io"
|
|
Get the list of interfaces and interface drivers known to
|
|
.Nm .
|
|
All the ioctls that manipulate interfaces
|
|
use the same structure described below:
|
|
.Bd -literal
|
|
struct pfioc_iface {
|
|
char pfiio_name[IFNAMSIZ];
|
|
void *pfiio_buffer;
|
|
int pfiio_esize;
|
|
int pfiio_size;
|
|
int pfiio_nzero;
|
|
int pfiio_flags;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
If not empty,
|
|
.Va pfiio_name
|
|
can be used to restrict the search to a specific interface or driver.
|
|
.Va pfiio_buffer[pfiio_size]
|
|
is the user-supplied buffer for returning the data.
|
|
On entry,
|
|
.Va pfiio_size
|
|
contains the number of
|
|
.Vt pfi_kif
|
|
entries that can fit into the buffer.
|
|
The kernel will replace this value by the real number of entries it wants
|
|
to return.
|
|
.Va pfiio_esize
|
|
should be set to
|
|
.Li sizeof(struct pfi_kif) .
|
|
.Pp
|
|
The data is returned in the
|
|
.Vt pfi_kif
|
|
structure described below:
|
|
.Bd -literal
|
|
struct pfi_kif {
|
|
RB_ENTRY(pfi_kif) pfik_tree;
|
|
char pfik_name[IFNAMSIZ];
|
|
u_int64_t pfik_packets[2][2][2];
|
|
u_int64_t pfik_bytes[2][2][2];
|
|
u_int32_t pfik_tzero;
|
|
int pfik_flags;
|
|
struct pf_state_tree_lan_ext pfik_lan_ext;
|
|
struct pf_state_tree_ext_gwy pfik_ext_gwy;
|
|
TAILQ_ENTRY(pfi_kif) pfik_w_states;
|
|
void *pfik_ah_cookie;
|
|
struct ifnet *pfik_ifp;
|
|
struct ifg_group *pfik_group;
|
|
int pfik_states;
|
|
int pfik_rules;
|
|
TAILQ_HEAD(, pfi_dynaddr) pfik_dynaddrs;
|
|
};
|
|
.Ed
|
|
.It Dv DIOCSETIFFLAG Fa "struct pfioc_iface *io"
|
|
Set the user settable flags (described above) of the
|
|
.Nm
|
|
internal interface description.
|
|
The filtering process is the same as for
|
|
.Dv DIOCIGETIFACES .
|
|
.Bd -literal
|
|
#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */
|
|
.Ed
|
|
.It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io"
|
|
Works as
|
|
.Dv DIOCSETIFFLAG
|
|
above but clears the flags.
|
|
.It Dv DIOCKILLSRCNODES Fa "struct pfioc_iface *io"
|
|
Explicitly remove source tracking nodes.
|
|
.El
|
|
.Sh FILES
|
|
.Bl -tag -width /dev/pf -compact
|
|
.It Pa /dev/pf
|
|
packet filtering device.
|
|
.El
|
|
.Sh EXAMPLES
|
|
The following example demonstrates how to use the
|
|
.Dv DIOCNATLOOK
|
|
command to find the internal host/port of a NATed connection:
|
|
.Bd -literal
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/fcntl.h>
|
|
#include <net/if.h>
|
|
#include <netinet/in.h>
|
|
#include <net/pfvar.h>
|
|
#include <err.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
u_int32_t
|
|
read_address(const char *s)
|
|
{
|
|
int a, b, c, d;
|
|
|
|
sscanf(s, "%i.%i.%i.%i", &a, &b, &c, &d);
|
|
return htonl(a << 24 | b << 16 | c << 8 | d);
|
|
}
|
|
|
|
void
|
|
print_address(u_int32_t a)
|
|
{
|
|
a = ntohl(a);
|
|
printf("%d.%d.%d.%d", a >> 24 & 255, a >> 16 & 255,
|
|
a >> 8 & 255, a & 255);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
struct pfioc_natlook nl;
|
|
int dev;
|
|
|
|
if (argc != 5) {
|
|
printf("%s <gwy addr> <gwy port> <ext addr> <ext port>\\n",
|
|
argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
dev = open("/dev/pf", O_RDWR);
|
|
if (dev == -1)
|
|
err(1, "open(\\"/dev/pf\\") failed");
|
|
|
|
memset(&nl, 0, sizeof(struct pfioc_natlook));
|
|
nl.saddr.v4.s_addr = read_address(argv[1]);
|
|
nl.sport = htons(atoi(argv[2]));
|
|
nl.daddr.v4.s_addr = read_address(argv[3]);
|
|
nl.dport = htons(atoi(argv[4]));
|
|
nl.af = AF_INET;
|
|
nl.proto = IPPROTO_TCP;
|
|
nl.direction = PF_IN;
|
|
|
|
if (ioctl(dev, DIOCNATLOOK, &nl))
|
|
err(1, "DIOCNATLOOK");
|
|
|
|
printf("internal host ");
|
|
print_address(nl.rsaddr.v4.s_addr);
|
|
printf(":%u\\n", ntohs(nl.rsport));
|
|
return 0;
|
|
}
|
|
.Ed
|
|
.Sh SEE ALSO
|
|
.Xr ioctl 2 ,
|
|
.Xr altq 4 ,
|
|
.Xr if_bridge 4 ,
|
|
.Xr pflog 4 ,
|
|
.Xr pfsync 4 ,
|
|
.Xr pfctl 8 ,
|
|
.Xr altq 9
|
|
.Sh HISTORY
|
|
The
|
|
.Nm
|
|
packet filtering mechanism first appeared in
|
|
.Ox 3.0
|
|
and then
|
|
.Fx 5.2 .
|
|
.Pp
|
|
This implementation is derived from
|
|
.Ox 4.5 .
|
|
It has been heavily modified to be capable of running in multithreaded
|
|
.Fx
|
|
kernel and scale its performance on multiple CPUs.
|