New netgraph node type, ng_bpf(8). This node type allows you to

apply bpf(4) filters to data travelling through a netgraph network.
This commit is contained in:
Archie Cobbs 1999-12-03 21:21:49 +00:00
parent 899e9c4e44
commit 92a3e5521f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=54097
12 changed files with 1061 additions and 5 deletions

143
share/man/man4/ng_bpf.4 Normal file
View File

@ -0,0 +1,143 @@
.\" Copyright (c) 1999 Whistle Communications, Inc.
.\" All rights reserved.
.\"
.\" Subject to the following obligations and disclaimer of warranty, use and
.\" redistribution of this software, in source or object code forms, with or
.\" without modifications are expressly permitted by Whistle Communications;
.\" provided, however, that:
.\" 1. Any and all reproductions of the source or object code must include the
.\" copyright notice above and the following disclaimer of warranties; and
.\" 2. No rights are granted, in any manner or form, to use Whistle
.\" Communications, Inc. trademarks, including the mark "WHISTLE
.\" COMMUNICATIONS" on advertising, endorsements, or otherwise except as
.\" such appears in the above copyright notice or in the software.
.\"
.\" THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
.\" INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
.\" WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
.\" REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
.\" SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
.\" IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
.\" RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
.\" WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
.\" PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
.\" OF SUCH DAMAGE.
.\"
.\" Author: Archie Cobbs <archie@whistle.com>
.\"
.\" $FreeBSD$
.\" $Whistle: ng_bpf.8,v 1.2 1999/12/03 01:57:12 archie Exp $
.\"
.Dd December 2, 1999
.Dt NG_BPF 8
.Os FreeBSD 4.0
.Sh NAME
.Nm ng_bpf
.Nd Berkeley packet filter netgraph node type
.Sh SYNOPSIS
.Fd #include <net/bpf.h>
.Fd #include <netgraph/ng_bpf.h>
.Sh DESCRIPTION
The
.Nm bpf
node type allows Berkeley Packet Filter (see
.Xr bpf 8 )
filters to be applied to data travelling through a Netgraph network.
Each node allows an arbitrary number of connections to arbitrarily
named hooks. With each hook is associated a
.Xf bpf 8
filter program which is applied to incoming data only, a destination hook
for matching packets, a destination hook for non-matching packets,
and various statistics counters.
.Pp
A
.Xr bpf 8
program returns an unsigned integer, which is normally interpreted as
the length of the prefix of the packet to return. In the context of this
node type, returning zero is considered a non-match, in which case the
entire packet is delivered out the non-match destination hook.
Returning a value greater than zero causes the packet to be truncated
to that length and delivered out the match destination hook.
Either or both destination hooks may be the empty string, or may
not exist, in which case the packet is dropped.
.Pp
New hooks are initially configured to drop all packets.
A new filter may be installed using the
.Dv NGM_BPF_SET_FILTER
control message.
.Sh HOOKS
This node type supports any number of hooks having arbitrary names.
.Sh CONTROL MESSAGES
This node type supports the generic control messages, plus the following:
.Bl -tag -width foo
.It Dv NGM_BPF_SET_FILTER
This command sets the filter program that will be applied to incoming
data on a hook. The following structure must be supplied as an argument:
.Bd -literal -offset 4n
struct ngm_bpf_hookprog {
char thisHook[NG_HOOKLEN+1]; /* name of hook */
char ifMatch[NG_HOOKLEN+1]; /* match dest hook */
char ifNotMatch[NG_HOOKLEN+1]; /* !match dest hook */
int32_t bpf_prog_len; /* #isns in program */
struct bpf_insn bpf_prog[0]; /* bpf program */
};
.Ed
.Pp
The hook to be updated is specified in
.Dv thisHook .
The BPF program is the sequence of instructions in the
.Dv bpf_prog
array; there must be
.Dv bpf_prog_len
of them.
Matching and non-matching incoming packets are delivered out the hooks named
.Dv ifMatch
and
.Dv ifNotMatch ,
respectively. The program must be a valid
.Xr bpf 8
program or else
.Er EINVAL
is returned.
.It Dv NGM_BPF_GET_FILTER
This command takes an ASCII string argument, the hook name, and returns the
corresponding
.Dv "struct ngm_bpf_hookprog"
as shown above.
.It Dv NGM_BPF_GET_STATS
This command takes an ASCII string argument, the hook name, and returns the
statistics associated with the hook as a
.Dv "struct ng_bpf_hookstat" .
.It Dv NGM_BPF_CLR_STATS
This command takes an ASCII string argument, the hook name, and clears the
statistics associated with the hook.
.It Dv NGM_BPF_GETCLR_STATS
This command is identical to
.Dv NGM_BPF_GET_STATS ,
except that the statistics are also atomically cleared.
.El
.Sh SHUTDOWN
This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
control message, or when all hooks have been disconnected.
.Sh BUGS
When built as a loadable kernel module, this module includes the file
.Dv "net/bpf_filter.c" .
Although loading the module should fail if
.Dv "net/bpf_filter.c"
already exists in the kernel, currently it does not, and the duplicate
copies of the file do not interfere.
However, this may change in the future.
.Sh SEE ALSO
.Xr netgraph 4 ,
.Xr bpf 4 ,
.Xr ngctl 8 .
.Sh AUTHOR
Archie Cobbs <archie@whistle.com>

View File

@ -394,9 +394,11 @@ options NETATALK #Appletalk communications protocols
# Individual node types can be enabled with the corresponding option
# listed below; however, this is not strictly necessary as netgraph
# will automatically load the corresponding KLD module if the node type
# is not already compiled into the kernel.
# is not already compiled into the kernel. Each type below has a
# corresponding man page, e.g., ng_async(8).
options NETGRAPH #netgraph(4) system
options NETGRAPH_ASYNC
options NETGRAPH_BPF
options NETGRAPH_CISCO
options NETGRAPH_ECHO
options NETGRAPH_FRAME_RELAY

View File

@ -574,6 +574,8 @@ netatm/uni/unisig_vc_state.c optional atm_uni atm_core
netgraph/ng_base.c optional netgraph
netgraph/ng_parse.c optional netgraph
netgraph/ng_async.c optional netgraph_async
netgraph/ng_bpf.c optional netgraph_bpf
net/bpf_filter.c optional netgraph_bpf
netgraph/ng_cisco.c optional netgraph_cisco
netgraph/ng_echo.c optional netgraph_echo
netgraph/ng_frame_relay.c optional netgraph_frame_relay

View File

@ -245,9 +245,10 @@ TCP_RESTRICT_RST opt_tcp_input.h
# Netgraph(4). Use option NETGRAPH to enable the base netgraph code.
# Each netgraph node type can be either be compiled into the kernel
# or loaded dynamically. To get the former, include the corresponding
# option below.
# option below. Each type has its own man page, e.g. ng_async(8).
NETGRAPH
NETGRAPH_ASYNC opt_netgraph.h
NETGRAPH_BPF opt_netgraph.h
NETGRAPH_CISCO opt_netgraph.h
NETGRAPH_ECHO opt_netgraph.h
NETGRAPH_FRAME_RELAY opt_netgraph.h

View File

@ -394,9 +394,11 @@ options NETATALK #Appletalk communications protocols
# Individual node types can be enabled with the corresponding option
# listed below; however, this is not strictly necessary as netgraph
# will automatically load the corresponding KLD module if the node type
# is not already compiled into the kernel.
# is not already compiled into the kernel. Each type below has a
# corresponding man page, e.g., ng_async(8).
options NETGRAPH #netgraph(4) system
options NETGRAPH_ASYNC
options NETGRAPH_BPF
options NETGRAPH_CISCO
options NETGRAPH_ECHO
options NETGRAPH_FRAME_RELAY

View File

@ -394,9 +394,11 @@ options NETATALK #Appletalk communications protocols
# Individual node types can be enabled with the corresponding option
# listed below; however, this is not strictly necessary as netgraph
# will automatically load the corresponding KLD module if the node type
# is not already compiled into the kernel.
# is not already compiled into the kernel. Each type below has a
# corresponding man page, e.g., ng_async(8).
options NETGRAPH #netgraph(4) system
options NETGRAPH_ASYNC
options NETGRAPH_BPF
options NETGRAPH_CISCO
options NETGRAPH_ECHO
options NETGRAPH_FRAME_RELAY

View File

@ -1,7 +1,7 @@
# $Whistle: Makefile,v 1.5 1999/01/24 06:48:37 archie Exp $
# $FreeBSD$
SUBDIR= async cisco echo frame_relay hole iface ksocket lmi netgraph \
SUBDIR= async bpf cisco echo frame_relay hole iface ksocket lmi netgraph \
ppp pppoe rfc1490 socket tee tty UI vjc
.include <bsd.subdir.mk>

View File

@ -0,0 +1,11 @@
# $FreeBSD$
# $Whistle: Makefile,v 1.1 1999/12/03 01:44:28 archie Exp $
KMOD= ng_bpf
SRCS= ng_bpf.c bpf_filter.c
MAN8= ng_bpf.8
KMODDEPS= netgraph
.PATH: ../../../net
.include <bsd.kmod.mk>

View File

@ -0,0 +1,143 @@
.\" Copyright (c) 1999 Whistle Communications, Inc.
.\" All rights reserved.
.\"
.\" Subject to the following obligations and disclaimer of warranty, use and
.\" redistribution of this software, in source or object code forms, with or
.\" without modifications are expressly permitted by Whistle Communications;
.\" provided, however, that:
.\" 1. Any and all reproductions of the source or object code must include the
.\" copyright notice above and the following disclaimer of warranties; and
.\" 2. No rights are granted, in any manner or form, to use Whistle
.\" Communications, Inc. trademarks, including the mark "WHISTLE
.\" COMMUNICATIONS" on advertising, endorsements, or otherwise except as
.\" such appears in the above copyright notice or in the software.
.\"
.\" THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
.\" INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
.\" WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
.\" REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
.\" SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
.\" IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
.\" RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
.\" WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
.\" PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
.\" OF SUCH DAMAGE.
.\"
.\" Author: Archie Cobbs <archie@whistle.com>
.\"
.\" $FreeBSD$
.\" $Whistle: ng_bpf.8,v 1.2 1999/12/03 01:57:12 archie Exp $
.\"
.Dd December 2, 1999
.Dt NG_BPF 8
.Os FreeBSD 4.0
.Sh NAME
.Nm ng_bpf
.Nd Berkeley packet filter netgraph node type
.Sh SYNOPSIS
.Fd #include <net/bpf.h>
.Fd #include <netgraph/ng_bpf.h>
.Sh DESCRIPTION
The
.Nm bpf
node type allows Berkeley Packet Filter (see
.Xr bpf 8 )
filters to be applied to data travelling through a Netgraph network.
Each node allows an arbitrary number of connections to arbitrarily
named hooks. With each hook is associated a
.Xf bpf 8
filter program which is applied to incoming data only, a destination hook
for matching packets, a destination hook for non-matching packets,
and various statistics counters.
.Pp
A
.Xr bpf 8
program returns an unsigned integer, which is normally interpreted as
the length of the prefix of the packet to return. In the context of this
node type, returning zero is considered a non-match, in which case the
entire packet is delivered out the non-match destination hook.
Returning a value greater than zero causes the packet to be truncated
to that length and delivered out the match destination hook.
Either or both destination hooks may be the empty string, or may
not exist, in which case the packet is dropped.
.Pp
New hooks are initially configured to drop all packets.
A new filter may be installed using the
.Dv NGM_BPF_SET_FILTER
control message.
.Sh HOOKS
This node type supports any number of hooks having arbitrary names.
.Sh CONTROL MESSAGES
This node type supports the generic control messages, plus the following:
.Bl -tag -width foo
.It Dv NGM_BPF_SET_FILTER
This command sets the filter program that will be applied to incoming
data on a hook. The following structure must be supplied as an argument:
.Bd -literal -offset 4n
struct ngm_bpf_hookprog {
char thisHook[NG_HOOKLEN+1]; /* name of hook */
char ifMatch[NG_HOOKLEN+1]; /* match dest hook */
char ifNotMatch[NG_HOOKLEN+1]; /* !match dest hook */
int32_t bpf_prog_len; /* #isns in program */
struct bpf_insn bpf_prog[0]; /* bpf program */
};
.Ed
.Pp
The hook to be updated is specified in
.Dv thisHook .
The BPF program is the sequence of instructions in the
.Dv bpf_prog
array; there must be
.Dv bpf_prog_len
of them.
Matching and non-matching incoming packets are delivered out the hooks named
.Dv ifMatch
and
.Dv ifNotMatch ,
respectively. The program must be a valid
.Xr bpf 8
program or else
.Er EINVAL
is returned.
.It Dv NGM_BPF_GET_FILTER
This command takes an ASCII string argument, the hook name, and returns the
corresponding
.Dv "struct ngm_bpf_hookprog"
as shown above.
.It Dv NGM_BPF_GET_STATS
This command takes an ASCII string argument, the hook name, and returns the
statistics associated with the hook as a
.Dv "struct ng_bpf_hookstat" .
.It Dv NGM_BPF_CLR_STATS
This command takes an ASCII string argument, the hook name, and clears the
statistics associated with the hook.
.It Dv NGM_BPF_GETCLR_STATS
This command is identical to
.Dv NGM_BPF_GET_STATS ,
except that the statistics are also atomically cleared.
.El
.Sh SHUTDOWN
This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
control message, or when all hooks have been disconnected.
.Sh BUGS
When built as a loadable kernel module, this module includes the file
.Dv "net/bpf_filter.c" .
Although loading the module should fail if
.Dv "net/bpf_filter.c"
already exists in the kernel, currently it does not, and the duplicate
copies of the file do not interfere.
However, this may change in the future.
.Sh SEE ALSO
.Xr netgraph 4 ,
.Xr bpf 4 ,
.Xr ngctl 8 .
.Sh AUTHOR
Archie Cobbs <archie@whistle.com>

View File

@ -0,0 +1,143 @@
.\" Copyright (c) 1999 Whistle Communications, Inc.
.\" All rights reserved.
.\"
.\" Subject to the following obligations and disclaimer of warranty, use and
.\" redistribution of this software, in source or object code forms, with or
.\" without modifications are expressly permitted by Whistle Communications;
.\" provided, however, that:
.\" 1. Any and all reproductions of the source or object code must include the
.\" copyright notice above and the following disclaimer of warranties; and
.\" 2. No rights are granted, in any manner or form, to use Whistle
.\" Communications, Inc. trademarks, including the mark "WHISTLE
.\" COMMUNICATIONS" on advertising, endorsements, or otherwise except as
.\" such appears in the above copyright notice or in the software.
.\"
.\" THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
.\" INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
.\" WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
.\" REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
.\" SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
.\" IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
.\" RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
.\" WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
.\" PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
.\" OF SUCH DAMAGE.
.\"
.\" Author: Archie Cobbs <archie@whistle.com>
.\"
.\" $FreeBSD$
.\" $Whistle: ng_bpf.8,v 1.2 1999/12/03 01:57:12 archie Exp $
.\"
.Dd December 2, 1999
.Dt NG_BPF 8
.Os FreeBSD 4.0
.Sh NAME
.Nm ng_bpf
.Nd Berkeley packet filter netgraph node type
.Sh SYNOPSIS
.Fd #include <net/bpf.h>
.Fd #include <netgraph/ng_bpf.h>
.Sh DESCRIPTION
The
.Nm bpf
node type allows Berkeley Packet Filter (see
.Xr bpf 8 )
filters to be applied to data travelling through a Netgraph network.
Each node allows an arbitrary number of connections to arbitrarily
named hooks. With each hook is associated a
.Xf bpf 8
filter program which is applied to incoming data only, a destination hook
for matching packets, a destination hook for non-matching packets,
and various statistics counters.
.Pp
A
.Xr bpf 8
program returns an unsigned integer, which is normally interpreted as
the length of the prefix of the packet to return. In the context of this
node type, returning zero is considered a non-match, in which case the
entire packet is delivered out the non-match destination hook.
Returning a value greater than zero causes the packet to be truncated
to that length and delivered out the match destination hook.
Either or both destination hooks may be the empty string, or may
not exist, in which case the packet is dropped.
.Pp
New hooks are initially configured to drop all packets.
A new filter may be installed using the
.Dv NGM_BPF_SET_FILTER
control message.
.Sh HOOKS
This node type supports any number of hooks having arbitrary names.
.Sh CONTROL MESSAGES
This node type supports the generic control messages, plus the following:
.Bl -tag -width foo
.It Dv NGM_BPF_SET_FILTER
This command sets the filter program that will be applied to incoming
data on a hook. The following structure must be supplied as an argument:
.Bd -literal -offset 4n
struct ngm_bpf_hookprog {
char thisHook[NG_HOOKLEN+1]; /* name of hook */
char ifMatch[NG_HOOKLEN+1]; /* match dest hook */
char ifNotMatch[NG_HOOKLEN+1]; /* !match dest hook */
int32_t bpf_prog_len; /* #isns in program */
struct bpf_insn bpf_prog[0]; /* bpf program */
};
.Ed
.Pp
The hook to be updated is specified in
.Dv thisHook .
The BPF program is the sequence of instructions in the
.Dv bpf_prog
array; there must be
.Dv bpf_prog_len
of them.
Matching and non-matching incoming packets are delivered out the hooks named
.Dv ifMatch
and
.Dv ifNotMatch ,
respectively. The program must be a valid
.Xr bpf 8
program or else
.Er EINVAL
is returned.
.It Dv NGM_BPF_GET_FILTER
This command takes an ASCII string argument, the hook name, and returns the
corresponding
.Dv "struct ngm_bpf_hookprog"
as shown above.
.It Dv NGM_BPF_GET_STATS
This command takes an ASCII string argument, the hook name, and returns the
statistics associated with the hook as a
.Dv "struct ng_bpf_hookstat" .
.It Dv NGM_BPF_CLR_STATS
This command takes an ASCII string argument, the hook name, and clears the
statistics associated with the hook.
.It Dv NGM_BPF_GETCLR_STATS
This command is identical to
.Dv NGM_BPF_GET_STATS ,
except that the statistics are also atomically cleared.
.El
.Sh SHUTDOWN
This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
control message, or when all hooks have been disconnected.
.Sh BUGS
When built as a loadable kernel module, this module includes the file
.Dv "net/bpf_filter.c" .
Although loading the module should fail if
.Dv "net/bpf_filter.c"
already exists in the kernel, currently it does not, and the duplicate
copies of the file do not interfere.
However, this may change in the future.
.Sh SEE ALSO
.Xr netgraph 4 ,
.Xr bpf 4 ,
.Xr ngctl 8 .
.Sh AUTHOR
Archie Cobbs <archie@whistle.com>

501
sys/netgraph/ng_bpf.c Normal file
View File

@ -0,0 +1,501 @@
/*
* ng_bpf.c
*
* Copyright (c) 1999 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANBPF, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Archie Cobbs <archie@whistle.com>
*
* $FreeBSD$
* $Whistle: ng_bpf.c,v 1.3 1999/12/03 20:30:23 archie Exp $
*/
/*
* BPF NETGRAPH NODE TYPE
*
* This node type accepts any number of hook connections. With each hook
* is associated a bpf(4) filter program, and two hook names (each possibly
* the empty string). Incoming packets are compared against the filter;
* matching packets are delivered out the first named hook (or dropped if
* the empty string), and non-matching packets are delivered out the second
* named hook (or dropped if the empty string).
*
* Each hook also keeps statistics about how many packets have matched, etc.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <net/bpf.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_parse.h>
#include <netgraph/ng_bpf.h>
#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
#define ERROUT(x) do { error = (x); goto done; } while (0)
/* Per hook private info */
struct ng_bpf_hookinfo {
node_p node;
hook_p hook;
struct ng_bpf_hookprog *prog;
struct ng_bpf_hookstat stats;
};
typedef struct ng_bpf_hookinfo *hinfo_p;
/* Netgraph methods */
static ng_constructor_t ng_bpf_constructor;
static ng_rcvmsg_t ng_bpf_rcvmsg;
static ng_shutdown_t ng_bpf_rmnode;
static ng_newhook_t ng_bpf_newhook;
static ng_rcvdata_t ng_bpf_rcvdata;
static ng_disconnect_t ng_bpf_disconnect;
/* Internal helper functions */
static int ng_bpf_setprog(hook_p hook, const struct ng_bpf_hookprog *hp);
/* Parse type for one struct bfp_insn */
static const struct ng_parse_struct_info ng_bpf_insn_type_info = {
{
{ "code", &ng_parse_int16_type },
{ "jt", &ng_parse_int8_type },
{ "jf", &ng_parse_int8_type },
{ "k", &ng_parse_int32_type },
{ NULL }
}
};
static const struct ng_parse_type ng_bpf_insn_type = {
&ng_parse_struct_type,
&ng_bpf_insn_type_info
};
/* Parse type for the field 'bpf_prog' in struct ng_bpf_hookprog */
static int
ng_bpf_hookprogary_getLength(const struct ng_parse_type *type,
const u_char *start, const u_char *buf)
{
const struct ng_bpf_hookprog *hp;
hp = (const struct ng_bpf_hookprog *)
(buf - OFFSETOF(struct ng_bpf_hookprog, bpf_prog));
return hp->bpf_prog_len;
}
static const struct ng_parse_array_info ng_bpf_hookprogary_info = {
&ng_bpf_insn_type,
&ng_bpf_hookprogary_getLength,
NULL
};
static const struct ng_parse_type ng_bpf_hookprogary_type = {
&ng_parse_array_type,
&ng_bpf_hookprogary_info
};
/* Parse type for struct ng_bpf_hookprog */
static const struct ng_parse_struct_info ng_bpf_hookprog_type_info
= NG_BPF_HOOKPROG_TYPE_INFO(&ng_bpf_hookprogary_type);
static const struct ng_parse_type ng_bpf_hookprog_type = {
&ng_parse_struct_type,
&ng_bpf_hookprog_type_info
};
/* Parse type for struct ng_bpf_hookstat */
static const struct ng_parse_struct_info
ng_bpf_hookstat_type_info = NG_BPF_HOOKSTAT_TYPE_INFO;
static const struct ng_parse_type ng_bpf_hookstat_type = {
&ng_parse_struct_type,
&ng_bpf_hookstat_type_info
};
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_bpf_cmdlist[] = {
{
NGM_BPF_COOKIE,
NGM_BPF_SET_PROGRAM,
"setprogram",
&ng_bpf_hookprog_type,
NULL
},
{
NGM_BPF_COOKIE,
NGM_BPF_GET_PROGRAM,
"getprogram",
&ng_parse_hookbuf_type,
&ng_bpf_hookprog_type
},
{
NGM_BPF_COOKIE,
NGM_BPF_GET_STATS,
"getstats",
&ng_parse_hookbuf_type,
&ng_bpf_hookstat_type
},
{
NGM_BPF_COOKIE,
NGM_BPF_CLR_STATS,
"clrstats",
&ng_parse_hookbuf_type,
NULL
},
{
NGM_BPF_COOKIE,
NGM_BPF_GETCLR_STATS,
"getclrstats",
&ng_parse_hookbuf_type,
&ng_bpf_hookstat_type
},
{ 0 }
};
/* Netgraph type descriptor */
static struct ng_type typestruct = {
NG_VERSION,
NG_BPF_NODE_TYPE,
NULL,
ng_bpf_constructor,
ng_bpf_rcvmsg,
ng_bpf_rmnode,
ng_bpf_newhook,
NULL,
NULL,
ng_bpf_rcvdata,
ng_bpf_rcvdata,
ng_bpf_disconnect,
ng_bpf_cmdlist
};
NETGRAPH_INIT(bpf, &typestruct);
/* Default BPF program for a hook that matches nothing */
static const struct ng_bpf_hookprog ng_bpf_default_prog = {
{ '\0' }, /* to be filled in at hook creation time */
{ '\0' },
{ '\0' },
1,
{ BPF_STMT(BPF_RET+BPF_K, 0) }
};
/*
* Node constructor
*
* We don't keep any per-node private data
*/
static int
ng_bpf_constructor(node_p *nodep)
{
int error = 0;
if ((error = ng_make_node_common(&typestruct, nodep)))
return (error);
(*nodep)->private = NULL;
return (0);
}
/*
* Add a hook
*/
static int
ng_bpf_newhook(node_p node, hook_p hook, const char *name)
{
hinfo_p hip;
int error;
/* Create hook private structure */
MALLOC(hip, hinfo_p, sizeof(*hip), M_NETGRAPH, M_WAITOK);
if (hip == NULL)
return (ENOMEM);
bzero(hip, sizeof(*hip));
hip->hook = hook;
hook->private = hip;
hip->node = node;
/* Attach the default BPF program */
if ((error = ng_bpf_setprog(hook, &ng_bpf_default_prog)) != 0) {
FREE(hip, M_NETGRAPH);
hook->private = NULL;
return (error);
}
/* Set hook name */
strncpy(hip->prog->thisHook, name, sizeof(hip->prog->thisHook) - 1);
hip->prog->thisHook[sizeof(hip->prog->thisHook) - 1] = '\0';
return (0);
}
/*
* Receive a control message
*/
static int
ng_bpf_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
struct ng_mesg **rptr)
{
struct ng_mesg *resp = NULL;
int error = 0;
switch (msg->header.typecookie) {
case NGM_BPF_COOKIE:
switch (msg->header.cmd) {
case NGM_BPF_SET_PROGRAM:
{
struct ng_bpf_hookprog *const
hp = (struct ng_bpf_hookprog *)msg->data;
hook_p hook;
/* Sanity check */
if (msg->header.arglen < sizeof(*hp)
|| msg->header.arglen != NG_BPF_HOOKPROG_SIZE(hp))
ERROUT(EINVAL);
/* Find hook */
if ((hook = ng_findhook(node, hp->thisHook)) == NULL)
ERROUT(ENOENT);
/* Set new program */
if ((error = ng_bpf_setprog(hook, hp)) != 0)
ERROUT(error);
break;
}
case NGM_BPF_GET_PROGRAM:
{
hook_p hook;
hinfo_p hip;
/* Sanity check */
if (msg->header.arglen == 0)
ERROUT(EINVAL);
msg->data[msg->header.arglen - 1] = '\0';
/* Find hook */
if ((hook = ng_findhook(node, msg->data)) == NULL)
ERROUT(ENOENT);
hip = hook->private;
/* Build response */
NG_MKRESPONSE(resp, msg,
NG_BPF_HOOKPROG_SIZE(hip->prog), M_NOWAIT);
if (resp == NULL)
ERROUT(ENOMEM);
bcopy(hip->prog, resp->data,
NG_BPF_HOOKPROG_SIZE(hip->prog));
break;
}
case NGM_BPF_GET_STATS:
case NGM_BPF_CLR_STATS:
case NGM_BPF_GETCLR_STATS:
{
struct ng_bpf_hookstat *stats;
hook_p hook;
/* Sanity check */
if (msg->header.arglen == 0)
ERROUT(EINVAL);
msg->data[msg->header.arglen - 1] = '\0';
/* Find hook */
if ((hook = ng_findhook(node, msg->data)) == NULL)
ERROUT(ENOENT);
stats = &((hinfo_p)hook->private)->stats;
/* Build response (if desired) */
if (msg->header.cmd != NGM_BPF_CLR_STATS) {
NG_MKRESPONSE(resp,
msg, sizeof(*stats), M_NOWAIT);
if (resp == NULL)
ERROUT(ENOMEM);
bcopy(stats, resp->data, sizeof(*stats));
}
/* Clear stats (if desired) */
if (msg->header.cmd != NGM_BPF_GET_STATS)
bzero(stats, sizeof(*stats));
break;
}
default:
error = EINVAL;
break;
}
break;
default:
error = EINVAL;
break;
}
if (rptr)
*rptr = resp;
else if (resp)
FREE(resp, M_NETGRAPH);
done:
FREE(msg, M_NETGRAPH);
return (error);
}
/*
* Receive data on a hook
*
* Apply the filter, and then drop or forward packet as appropriate.
*/
static int
ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
{
const hinfo_p hip = hook->private;
int totlen = m->m_pkthdr.len;
int needfree = 0, error = 0;
u_char *data, buf[256];
hinfo_p dhip;
hook_p dest;
u_int len;
/* Update stats on incoming hook */
hip->stats.recvFrames++;
hip->stats.recvOctets += totlen;
/* Need to put packet in contiguous memory for bpf */
if (m->m_next != NULL) {
if (totlen > sizeof(buf)) {
MALLOC(data, u_char *, totlen, M_NETGRAPH, M_NOWAIT);
if (data == NULL) {
NG_FREE_DATA(m, meta);
return (ENOMEM);
}
needfree = 1;
} else
data = buf;
m_copydata(m, 0, totlen, (caddr_t)data);
} else
data = mtod(m, u_char *);
/* Run packet through filter */
len = bpf_filter(hip->prog->bpf_prog, data, totlen, totlen);
if (needfree)
FREE(data, M_NETGRAPH);
/* See if we got a match and find destination hook */
if (len > 0) {
/* Update stats */
hip->stats.recvMatchFrames++;
hip->stats.recvMatchOctets += totlen;
/* Truncate packet length if required by the filter */
if (len < totlen) {
m_adj(m, -(totlen - len));
totlen -= len;
}
dest = ng_findhook(hip->node, hip->prog->ifMatch);
} else
dest = ng_findhook(hip->node, hip->prog->ifNotMatch);
if (dest == NULL) {
NG_FREE_DATA(m, meta);
return (0);
}
/* Deliver frame out destination hook */
dhip = (hinfo_p)dest->private;
dhip->stats.xmitOctets += totlen;
dhip->stats.xmitFrames++;
NG_SEND_DATA(error, dest, m, meta);
return (error);
}
/*
* Shutdown processing
*/
static int
ng_bpf_rmnode(node_p node)
{
node->flags |= NG_INVALID;
ng_cutlinks(node);
ng_unname(node);
ng_unref(node);
return (0);
}
/*
* Hook disconnection
*/
static int
ng_bpf_disconnect(hook_p hook)
{
const hinfo_p hip = hook->private;
KASSERT(hip != NULL, ("%s: null info", __FUNCTION__));
FREE(hip->prog, M_NETGRAPH);
bzero(hip, sizeof(*hip));
FREE(hip, M_NETGRAPH);
hook->private = NULL; /* for good measure */
if (hook->node->numhooks == 0)
ng_rmnode(hook->node);
return (0);
}
/************************************************************************
HELPER STUFF
************************************************************************/
/*
* Set the BPF program associated with a hook
*/
static int
ng_bpf_setprog(hook_p hook, const struct ng_bpf_hookprog *hp0)
{
const hinfo_p hip = hook->private;
struct ng_bpf_hookprog *hp;
int size;
/* Check program for validity */
if (!bpf_validate(hp0->bpf_prog, hp0->bpf_prog_len))
return (EINVAL);
/* Make a copy of the program */
size = NG_BPF_HOOKPROG_SIZE(hp0);
MALLOC(hp, struct ng_bpf_hookprog *, size, M_NETGRAPH, M_WAITOK);
if (hp == NULL)
return (ENOMEM);
bcopy(hp0, hp, size);
/* Free previous program, if any, and assign new one */
if (hip->prog != NULL)
FREE(hip->prog, M_NETGRAPH);
hip->prog = hp;
return (0);
}

106
sys/netgraph/ng_bpf.h Normal file
View File

@ -0,0 +1,106 @@
/*
* ng_bpf.h
*
* Copyright (c) 1996-1999 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANBPF, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* Author: Archie Cobbs <archie@whistle.com>
*
* $FreeBSD$
* $Whistle: ng_bpf.h,v 1.3 1999/12/03 20:30:23 archie Exp $
*/
#ifndef _NETGRAPH_BPF_H_
#define _NETGRAPH_BPF_H_
/* Node type name and magic cookie */
#define NG_BPF_NODE_TYPE "bpf"
#define NGM_BPF_COOKIE 944100792
/* Program structure for one hook */
struct ng_bpf_hookprog {
char thisHook[NG_HOOKLEN+1]; /* name of hook */
char ifMatch[NG_HOOKLEN+1]; /* match dest hook */
char ifNotMatch[NG_HOOKLEN+1]; /* !match dest hook */
int32_t bpf_prog_len; /* #isns in program */
struct bpf_insn bpf_prog[0]; /* bpf program */
};
#define NG_BPF_HOOKPROG_SIZE(hp) \
(sizeof(*(hp)) + (hp)->bpf_prog_len * sizeof((hp)->bpf_prog[0]))
/* Keep this in sync with the above structure definition */
#define NG_BPF_HOOKPROG_TYPE_INFO(bptype) { \
{ \
{ "thisHook", &ng_parse_hookbuf_type }, \
{ "ifMatch", &ng_parse_hookbuf_type }, \
{ "ifNotMatch", &ng_parse_hookbuf_type }, \
{ "bpf_prog_len", &ng_parse_int32_type }, \
{ "bpf_prog", (bptype) }, \
{ NULL }, \
} \
}
/* Statistics structure for one hook */
struct ng_bpf_hookstat {
u_int64_t recvFrames;
u_int64_t recvOctets;
u_int64_t recvMatchFrames;
u_int64_t recvMatchOctets;
u_int64_t xmitFrames;
u_int64_t xmitOctets;
};
/* Keep this in sync with the above structure definition */
#define NG_BPF_HOOKSTAT_TYPE_INFO { \
{ \
{ "recvFrames", &ng_parse_int64_type }, \
{ "recvOctets", &ng_parse_int64_type }, \
{ "recvMatchFrames", &ng_parse_int64_type }, \
{ "recvMatchOctets", &ng_parse_int64_type }, \
{ "xmitFrames", &ng_parse_int64_type }, \
{ "xmitOctets", &ng_parse_int64_type }, \
{ NULL }, \
} \
}
/* Netgraph commands */
enum {
NGM_BPF_SET_PROGRAM = 1, /* supply a struct ng_bpf_hookprog */
NGM_BPF_GET_PROGRAM, /* returns a struct ng_bpf_hookprog */
NGM_BPF_GET_STATS, /* supply name as char[NG_HOOKLEN+1] */
NGM_BPF_CLR_STATS, /* supply name as char[NG_HOOKLEN+1] */
NGM_BPF_GETCLR_STATS, /* supply name as char[NG_HOOKLEN+1] */
};
#endif /* _NETGRAPH_BPF_H_ */