From 1edd13e295e6ccc9fabae6f5d194ea28e5360dd6 Mon Sep 17 00:00:00 2001 From: archie Date: Fri, 3 Dec 1999 21:21:49 +0000 Subject: New netgraph node type, ng_bpf(8). This node type allows you to apply bpf(4) filters to data travelling through a netgraph network. --- share/man/man4/ng_bpf.4 | 143 +++++++++++ sys/conf/NOTES | 4 +- sys/conf/files | 2 + sys/conf/options | 3 +- sys/i386/conf/LINT | 4 +- sys/i386/conf/NOTES | 4 +- sys/modules/netgraph/Makefile | 2 +- sys/modules/netgraph/bpf/Makefile | 11 + sys/modules/netgraph/bpf/ng_bpf.4 | 143 +++++++++++ sys/modules/netgraph/bpf/ng_bpf.8 | 143 +++++++++++ sys/netgraph/ng_bpf.c | 501 ++++++++++++++++++++++++++++++++++++++ sys/netgraph/ng_bpf.h | 106 ++++++++ 12 files changed, 1061 insertions(+), 5 deletions(-) create mode 100644 share/man/man4/ng_bpf.4 create mode 100644 sys/modules/netgraph/bpf/Makefile create mode 100644 sys/modules/netgraph/bpf/ng_bpf.4 create mode 100644 sys/modules/netgraph/bpf/ng_bpf.8 create mode 100644 sys/netgraph/ng_bpf.c create mode 100644 sys/netgraph/ng_bpf.h diff --git a/share/man/man4/ng_bpf.4 b/share/man/man4/ng_bpf.4 new file mode 100644 index 0000000..e9079ea --- /dev/null +++ b/share/man/man4/ng_bpf.4 @@ -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 +.\" +.\" $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 +.Fd #include +.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 diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 647f21b..70df1ae 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -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 diff --git a/sys/conf/files b/sys/conf/files index fbda398..ef04f36 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -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 diff --git a/sys/conf/options b/sys/conf/options index 130e535..da11cc0 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -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 diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 647f21b..70df1ae 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -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 diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 647f21b..70df1ae 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -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 diff --git a/sys/modules/netgraph/Makefile b/sys/modules/netgraph/Makefile index b3fe13f..ab3e9ed 100644 --- a/sys/modules/netgraph/Makefile +++ b/sys/modules/netgraph/Makefile @@ -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 diff --git a/sys/modules/netgraph/bpf/Makefile b/sys/modules/netgraph/bpf/Makefile new file mode 100644 index 0000000..6f1714c --- /dev/null +++ b/sys/modules/netgraph/bpf/Makefile @@ -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 diff --git a/sys/modules/netgraph/bpf/ng_bpf.4 b/sys/modules/netgraph/bpf/ng_bpf.4 new file mode 100644 index 0000000..e9079ea --- /dev/null +++ b/sys/modules/netgraph/bpf/ng_bpf.4 @@ -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 +.\" +.\" $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 +.Fd #include +.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 diff --git a/sys/modules/netgraph/bpf/ng_bpf.8 b/sys/modules/netgraph/bpf/ng_bpf.8 new file mode 100644 index 0000000..e9079ea --- /dev/null +++ b/sys/modules/netgraph/bpf/ng_bpf.8 @@ -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 +.\" +.\" $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 +.Fd #include +.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 diff --git a/sys/netgraph/ng_bpf.c b/sys/netgraph/ng_bpf.c new file mode 100644 index 0000000..7b0e80c --- /dev/null +++ b/sys/netgraph/ng_bpf.c @@ -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 + * + * $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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#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); +} + diff --git a/sys/netgraph/ng_bpf.h b/sys/netgraph/ng_bpf.h new file mode 100644 index 0000000..6745b88 --- /dev/null +++ b/sys/netgraph/ng_bpf.h @@ -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 + * + * $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_ */ -- cgit v1.1