Subject: Zembu Packet Classifier -- would like to put it in the mainline
To: None <>
From: Jason R Thorpe <>
List: tech-net
Date: 12/28/2000 19:55:26
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


I have implemented a new packet filter and classification engine
called ZPC -- Zembu Packet Classifier.  It was implemented because
of some limitations in IP Filter which weren't going to be easy to
work around in IP Filter.

The ZPC uses the BPF virtual machine as the core of the filter engine.
This has several advantages:

	(1) Can use libpcap to compile rules using a tcpdump(8)-like

	(2) Rules are parsed in userspace, thus making the kernel portion
	    of the filter engine completely protocol agnostic.  This also
	    means that filtering can be done easily at any point, allowing
	    the userspace rule compiler to adjust the rules for differing
	    protocol header offsets (due to e.g. link-layer headers being
	    present or not) -- libpcap already does this.  This makes it
	    very easy to do e.g. transparent filtering at a bridge, or to
	    filter out Appletalk packets on a certain network interface.
	    Also, to extend the filter's capabilities, all you have to
	    do is extend a userspace library (libpcap).

	(3) The filter engine is very small.

	(4) Provides a good starting point for synthesis of rules
	    into native object code for very fast rule processing.
	    This is a project that I've already started working on.

The (not yet fully implemetned) ZPC packet logging facility uses a
format that can be read with tcpdump(8) (the reason it's not fully
implemented yet is because I need to extend the pcap save file format
just a bit, and need to get in touch with the folks about

The ZPC also has a way to load arbitrary packet processing methods
into a filtering point and to apply them to a packet using filter
rules.  This can be used to implement "return ICMP error" or "return
TCP RST" types of packet blocking (see ipf.conf(5), look for
"return-rst", or to implement NAT.  The method feature is similar
in concept to the "call" mentioned in IP Filter's documentation,
although IP Filter does not appear to completely implement the

Some of these methods (such as the "return ..." and NAT) will be
written and contributed like the rest of ZPC (tho, NAT isn't the
highest on my list, but it will be done eventually).

Zembu Labs would like to contribute this to the NetBSD project.
Obviously there will be certain parts that we will keep to ourselves
(some of the more interesting "methods"), but the core and above
mentioned methods we'd like to have in the NetBSD mainline.  We also
plan on contributing the synthesis engine for the BPF virtual machine
when it's working on a processor type or two.

It's still a work-in-progress, but it is working and in use.  I also
know of a few NetBSD users (including "NetBSD in product" folks) who
are interested in using it.  Some day, other packet classifiers in
the kernel (like the IPsec policy lookup engine, or the classifier
in ALTQ) could be changed to use this classification engine (which
is more generic than the others).

Attached is a formatted copy of the zpcctl(8) manual page that
describes the configuration of the ZPC.

If there's consensus here that this would be a nice thing to have
in the tree, then I'll go ahead and commit it to -current (something
I'd like to do fairly soon).

        -- Jason R. Thorpe <>

Content-Type: text/plain; charset=us-ascii
Content-Description: zpcctl(8)
Content-Disposition: attachment; filename=foo
Content-Transfer-Encoding: quoted-printable

ZPCCTL(8)               NetBSD System Manager's Manual               ZPCCTL=

     z=08zp=08pc=08cc=08ct=08tl=08l - configuration utility for the Zembu P=
acket Classifier

     z=08zp=08pc=08cc=08ct=08tl=08l [-=08-a=08a _=08f_=08a_=08m_=08i_=08l_=
=08y] [-=08-i=08i _=08i_=08f_=08n_=08e_=08t] create
     z=08zp=08pc=08cc=08ct=08tl=08l [-=08-a=08a _=08f_=08a_=08m_=08i_=08l_=
=08y] [-=08-i=08i _=08i_=08f_=08n_=08e_=08t] destroy
     z=08zp=08pc=08cc=08ct=08tl=08l [-=08-a=08a _=08f_=08a_=08m_=08i_=08l_=
=08y] [-=08-i=08i _=08i_=08f_=08n_=08e_=08t] enable
     z=08zp=08pc=08cc=08ct=08tl=08l [-=08-a=08a _=08f_=08a_=08m_=08i_=08l_=
=08y] [-=08-i=08i _=08i_=08f_=08n_=08e_=08t] disable
     z=08zp=08pc=08cc=08ct=08tl=08l [-=08-a=08a _=08f_=08a_=08m_=08i_=08l_=
=08y] [-=08-i=08i _=08i_=08f_=08n_=08e_=08t] flush
     z=08zp=08pc=08cc=08ct=08tl=08l [-=08-a=08a _=08f_=08a_=08m_=08i_=08l_=
=08y] [-=08-i=08i _=08i_=08f_=08n_=08e_=08t] load [-=08-d=08d] [-=08-D=08D]=
 [-=08-f=08f _=08c_=08o_=08n_=08f_=08i_=08g] [-=08-O=08O] [-=08-r=08r]

     z=08zp=08pc=08cc=08ct=08tl=08l is used to configure the Zembu Packet C=
lassifier, a general pur-
     pose packet classification and filter engine.

     Classification and filter points are specified using the mutually excl=
     sive -=08-a=08a and -=08-i=08i options:

     -=08-a=08a _=08f_=08a_=08m_=08i_=08l_=08y
             Specify the filtering point corresponding to the address family
             _=08f_=08a_=08m_=08i_=08l_=08y.  Valid address families are ``=
inet'' and ``inet6''.

     -=08-i=08i _=08i_=08f_=08n_=08e_=08t
             Specify the filtering point corresponding to the network inter-
             face _=08i_=08f_=08n_=08e_=08t.  The network interface specifi=
ed must be present on
             the system.

     If a filtering point is not specified, the default address family
     ``inet'' is selected.

     The following commands are available:

     create   Create the specified filter instance.

     destroy  Destroy the specified filter instance.

     enable   Enable the specified filter instance.

     disable  Disable the specified filter instance.

     flush    Flush the rules from the specified filter instance.

     load     Load rules into the specified filter instance.  The options to
              this command are:

              -=08-d=08d      Dump the rules to the standard output after p=
                      them.  This is useful if you suspect a bug in the rule

              -=08-D=08D      Like the -=08-d=08d flag, but also dumps the =
virtual machine
                      bytecode that is generated by the packet-matching com-

              -=08-f=08f _=08c_=08o_=08n_=08f_=08i_=08g
                      Load the rules from the file _=08c_=08o_=08n_=08f_=08=
i_=08g.  An argument of
                      ``-'' causes rules to be loaded from the standard inp=
                      If a file is not specified, the rules will be taken f=
                      the file _=08/_=08e_=08t_=08c_=08/_=08z_=08p_=08c_=08=
__=08K_=08E_=08Y_=08._=08c_=08o_=08n_=08f, where _=08K_=08E_=08Y is the nam=
e of the
                      address family or network interface associated with t=
                      filtering point.

              -=08-O=08O      Do not run the packet-matching code optimizer=
.  This is
                      useful only if you suspect a bug in the optimizer.

              -=08-r=08r      By default, z=08zp=08pc=08cc=08ct=08tl=08l ap=
pends the rules to the current set
                      of rules already associated with the filtering point.
                      This option causes the new rules to replace the curre=

R=08RU=08UL=08LE=08E S=08SY=08YN=08NT=08TA=08AX=08X
     The rule syntax is based on the packet matching syntax used by the
     tcpdump(8) command.  In general, a rule has the following syntax:

     ACTION [MODIFIERS] [DIRECTION] [on _=08i_=08f_=08n_=08e_=08t] [match _=

     The following actions are defined:

     pass    Pass the packet through the filtering point

     block   Block the packet (do not let it pass the filtering point)

     call _=08m_=08e_=08t_=08h_=08o_=08d
             Call the packet processing method _=08m_=08e_=08t_=08h_=08o_=
=08d.  The processing method
             may choose to pass or block the packet.  If the packet is to be
             passed, the method may also choose to allow further rule match=
             to occur on the packet or to end rule processing on the packet.

     The following modifiers are defined:

     log     Log the packet that matched the rule.

     quick   Normally, the classification engine performs processing on the
             last rule that matches a packet.  This modifier causes a packet
             matching a rule to be processed immediately.  If futher rule p=
             cessing is requested (via the ``call'' action), any previously
             matched rules are forgotten, so that rules that may have match=
             before the quick rule are not processed after all rules have b=

     The following directions are defined:

     in      This indicates an inbound (network to host) packet.

     out     This indicates an outbound (host to network) packet.

     Note that if no direction is specified, the default is to consider both
     inbound and outbound directions.

     It is also possible to create sub-groups of rules that are processed u=
     a match of the parent rule (regardless of whether or not the rule's ac-
     tion is taken).  The sub-groups are indicated using ``{'' and ``}''
     around the grouped rules.  Consider the following set of rules:

           # Block all ICMP except for certain ones that are
           # generally OK.
           block in match icmp {
                   pass match icmp[icmptype] =3D=3D icmp-echoreply or \
                       icmp[icmptype] =3D=3D icmp-echo or \
                       icmp[icmptype] =3D=3D icmp-unreach

           # Immediately allow any packet corresponding to an
           # already-established TCP connection or any response
           # to a connection we are initiating.
           pass quick in match (tcp[tcpflags] & tcp-syn) =3D=3D 0 or \
               (tcp[tcpflags] & (tcp-syn|tcp-ack)) =3D=3D (tcp-syn|tcp-ack)

           pass in match tcp port 80

     In this example, any incoming ICMP packet will match the first rule, a=
     will default to ``block''.  However, processing then continues in the
     braced rule sub-group, and ICMP ECHO RESPONSE, ECHO REQUEST, and HOST =
     REACHABLE packets are allowed through.  Note that even though the rule=
     the sub-group does not have a ``quick'' modifier, rule processing stops
     at the end of the sub-group, and the rule immediately following the su=
     group will not be tested.

     For complete details on the packet matching expression syntax (to be u=
     with the ``match'' keyword), see the tcpdump(8) manual page.

             Configuration file for the filtering point _=08K_=08E_=08Y.

             Zembu Packet Classifier configuration device

S=08SE=08EE=08E A=08AL=08LS=08SO=08O
     bpf(4), inet(4), inet6(4), pcap(3), tcpdump(8), zpc(4)

     The z=08zp=08pc=08cc=08ct=08tl=08l command first appeared in NetBSD 1.=

     The Zembu Packet Classifier and the z=08zp=08pc=08cc=08ct=08tl=08l com=
mand were written by Jason
     R. Thorpe <> and contributed by Zembu Labs, Inc.

NetBSD                         December 23, 2000                           =