packetfilter - Ethernet packet filter
options PACKETFILTER
The packet filter pseudo-device driver provides a raw
interface to Ethernets and similar network data link layers.
Packets received that are not used by the kernel (for
example, to support the IP and DECnet protocol families)
are available through this mechanism. The packet filter
driver is kernel-resident code provided by the Tru64 UNIX
operating system. The driver appears to applications as a
set of character special files, one for each open packet
filter application. (Throughout this reference page, the
word file refers to such a character special file.)
To include packet filter support in your kernel, you must
build a new kernel by using the doconfig command. Choose
the PACKETFILTER option in addition to any other options
you want. Then, reboot your system. For more information,
see the System Administration manual and doconfig(8).
You can modify the number of packet filter devices on a
system by using either dxkerneltuner or the sysconfig command.
The attribute name is npacketfilter. See
sys_attrs_net(5) for more information.
You can also view the amount of memory that the pfilt subsystem
uses by using the vmstat -M command (the type is
PFILT).
You create the minor device files with the MAKEDEV(8)
script using these commands: # cd /dev # MAKEDEV pfilt
A single call to MAKEDEV with an argument of pfilt creates
64 character special files in /dev/pf, which are named
pfiltnnn, where nnn is the unit number. Calls to MAKEDEV
with the following arguments create additional packet filter
devices as indicated:
---------------------------------
Argument Action
---------------------------------
pfilt Creates 64 devices
pfilt64 Creates 64 devices
pfilt128 Creates 128 devices
pfilt256 Creates 256 devices
pfilt512 Creates 512 devices
pfilt1024 Creates 1024 devices
pfilt2048 Creates 2048 devices
pfilt3072 Creates 3072 devices
pfilt4096 Creates 4096 devices
---------------------------------
The maximum number of packet filter special files is limited
to 4096, which is the maximum number of minor device
numbers allowed for each major device number. (See
MAKEDEV(8) for more information on making system special
files.)
For opening these special files, the operating system provides
the pfopen(3) library routine. For more information,
see pfopen(3).
Associated with each open instance of a packet filter special
file is a user-settable packet filter ``program''
that is used to select which incoming packets are delivered
by that packet filter special file. Whenever a
packet is received from the net, the packet filter driver
successively applies the filter programs of each of the
open packet filter files to the packet, until one filter
program ``accepts'' the packet. When a filter accepts the
packet, it is placed on the packet input queue of the
associated special file. If no filters accept the packet,
it is discarded. The format of a packet filter is
described later.
Reads from these files return the next packet from a queue
of packets that have matched the filter. If the read
operation specifies insufficient buffer space to store the
entire packet, the packet is truncated and the trailing
contents lost. Writes to these files transmit packets on
the network, with each write operation generating exactly
one packet.
The packet filter supports a variety of different Ethernet
data-link levels: Packets consist of fourteen or more
bytes, with the first six bytes specifying the destination
Ethernet address, the next six bytes the source Ethernet
address, and the next two bytes specifying the packet
type. See <netinet/if_ether.h>. (802.3 packets follow the
same format, except that the last field gives the packet
length). FDDI packets start with a 13-byte header; the
first byte is the ``frame control'' field, which is normally
followed by a 6-byte (Ethernet-style) destination
address and a 6-byte source address. For alignment reasons,
the packet filter prepends a 3-byte padding field to
incoming packets, and expects to see a corresponding
padding field on transmitted packets. See the declaration
for "struct fddi_header" in <netinet/if_fddi.h>. FDDI
headers are usually followed by 802.2 headers; see
<net/if_llc.h>.
The remaining words are interpreted according to the
packet type. Note that 16-bit and 32-bit quantities may
have to be byteswapped (and possibly short-swapped) to be
intelligible on Tru64 UNIX systems.
The packet filters treat the entire packet, including
headers, as uninterpreted data. The user must supply the
headers for transmitted packets (although the system makes
sure that the source address is correct) and the headers
of received packets are delivered to the user. The packet
filter mechanism does not know anything about the data
portion of the packets it sends and receives.
In addition to the FIONREAD ioctl request (described in
the tty(7) reference page), the application can apply several
special ioctl requests to an open packet filter file.
The calls are divided into five categories: packet-filter
specifying, packet handling, device configuration, administrative,
and miscellaneous.
The Tru64 UNIX packet filter also supports most of the BSD
Packet Filter (BPF) ioctl commands. This provides nearly
complete source-level compatibility with existing BPF
application code. The BPF packet filter format is quite
different from the format described in this reference page
and may be far more efficient or flexible for many applications.
For more information on the BSD Packet Filter
Extensions, see bpf(7).
Packet-filter Specification ioctl Request [Toc] [Back]
The EIOCSETF ioctl is central to the operation of the
packet filter interface, because it specifies which packets
the application wishes to receive. It is used to set
the packet filter ``program'' for an open packet filter
file, and is of the form: ioctl(fildes, EIOCSETF, filter)
struct enfilter *filter
The enfilter structure is defined in <net/pfilt.h> as:
struct enfilter { u_char enf_Priority;
u_char enf_FilterLen;
u_short enf_Filter[ENMAXFILTERS];
};
A packet filter consists of a priority, the filter command
list length (in shortwords), and the filter command list
itself. Each filter command list specifies a sequence of
actions that operate on an internal stack. Each shortword
of the command list specifies an action and a binary operator.
Command List Actions [Toc] [Back]
The action can be one of the following: Pushes the next
shortword of the command list on the stack. Pushes shortword
N of the incoming packet on the stack. Pushes a
zero. Is slightly faster than ENF_PUSHLIT with an
explicit literal. Pushes a one. Is slightly faster than
ENF_PUSHLIT with an explicit literal. Pushes 0xFFFF. Is
slightly faster than ENF_PUSHLIT with an explicit literal.
Pushes 0x00FF. Is slightly faster than ENF_PUSHLIT with
an explicit literal. Pushes 0xFF00. Is slightly faster
than ENF_PUSHLIT with an explicit literal. Defined as
zero.
Binary Operators [Toc] [Back]
When both an action and an operator are specified in the
same shortword, the action is performed, followed by the
operation. You can combine an action with an operator
using bitwise OR; for example,
((ENF_PUSHWORD+3) | ENF_EQ)
The binary operator, which can be one of the following,
operates on the top two elements of the stack and replaces
them with its result: Returns true if the result is equal.
Returns true if the result is not equal. Returns true if
the result is less than. Returns true if the result is
less than or equal. Returns true if the result is greater
than. Returns true if the result is greater than or
equal. Returns the result of the binary AND operation.
Returns the result of the binary OR operation. Returns
the result of the binary XOR operation. Defined as zero.
Returns false immediately if the result is false, and continues
execution of the filter otherwise. (Short-circuit
operator) Returns true immediately if the result is true,
and continues execution of the filter otherwise. (Shortcircuit
operator) Returns true immediately if the result
is false, and continues execution of the filter otherwise.
(Short-circuit operator) Returns false immediately if the
result is true, and continues execution of the filter otherwise.
(Short-circuit operator)
The short-circuit operators are so called because they
terminate the execution of the filter immediately if the
condition they are checking for is found, and continue
otherwise. All the short-circuit operators pop two elements
from the stack and compare them for equality. Unlike
the other binary operators, these four operators do not
leave a result on the stack, even if they continue.
Use the short-circuit operators whenever possible, to
reduce the amount of time spent evaluating filters. When
you use them, you should also arrange the order of the
tests so that the filter will succeed or fail as soon as
possible. For example, checking a word in an address field
of an Ethernet packet is more likely to indicate failure
than the Ethernet type field.
The special action ENF_NOPUSH and the special operator
ENF_NOP can be used to only perform the binary operation
or to only push a value on the stack. Because both are
defined to be zero, specifying only an action actually
specifies the action followed by ENF_NOP, and specifying
only an operation actually specifies ENF_NOPUSH followed
by the operation.
After executing the filter command list, a nonzero value
(true) left on top of the stack (or an empty stack) causes
the incoming packet to be accepted for the corresponding
packet filter file and a zero value (false) causes the
packet to be passed through the next packet filter. If the
filter exits as the result of a short-circuit operator,
the top-of-stack value is ignored. Specifying an undefined
operation or action in the command list or performing
an illegal operation or action (such as pushing a
shortword offset past the end of the packet or executing a
binary operator with fewer than two shortwords on the
stack) causes a filter to reject the packet.
To resolve problems with overlapping or conflicting packet
filters, the filters for each open packet filter file are
ordered by the driver according to their priority (lowest
priority is 0, highest is 255). When processing incoming
packets, filters are applied according to their priority
(from highest to lowest) and for identical priority values
according to their relative ``busyness'' (the filter that
has previously matched the most packets is checked first),
until one or more filters accept the packet or all filters
reject it and it is discarded.
Normally once a packet is delivered to a filter, it is not
presented to any other filters. However, if the packet is
accepted by a filter in nonexclusive mode (ENNONEXCL set
using EIOCMBIS, described in the following section), the
packet is passed along to lower-priority filters and may
be delivered more than once. The use of nonexclusive filters
imposes an additional cost on the system, because it
increases the average number of filters applied to each
packet.
The packet filter for a packet filter file is initialized
with length 0 at priority 0 by open(2), and hence, by
default, accepts all packets in which no higher-priority
filter is interested.
Priorities should be assigned so that, in general, the
more packets a filter is expected to match, the higher its
priority. This prevents a lot of checking of packets
against filters that are unlikely to match them.
The filter in this example accepts incoming RARP (Reverse
Address Resolution Protocol) broadcast packets.
The filter first checks the Ethernet type of the packet.
If it is not a RARP (Reverse ARP) packet, it is discarded.
Then, the RARP type field is checked for a reverse request
(type 3), followed by a check for a broadcast destination
address. Note that the packet type field is checked before
the destination address, because the total number of
broadcast packets on the network is larger than the number
of RARP packets. Thus, the filter is ordered with a minimum
amount of processing overhead.
struct enfilter f;
buildfilter() {
f.enf_Priority = 36; /* anything > 2 should work
*/
f.enf_FilterLen = 0;
/* packet type is last short in header */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 6;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT;
f.enf_Filter[f.enf_FilterLen++] = 0x3580;
f.enf_Filter[f.enf_FilterLen++] =
ENF_CAND; /* Ethernet type == 0x8035 (RARP) */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 10;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT;
f.enf_Filter[f.enf_FilterLen++] = 0x0300;
f.enf_Filter[f.enf_FilterLen++] =
ENF_CAND; /* reverse request type = 0003 */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 0;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT;
f.enf_Filter[f.enf_FilterLen++] = 0xFFFF;
f.enf_Filter[f.enf_FilterLen++] =
ENF_CAND; /* dest addr = FF-FF */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 1;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT;
f.enf_Filter[f.enf_FilterLen++] = 0xFFFF;
f.enf_Filter[f.enf_FilterLen++] =
ENF_CAND; /* dest addr = FF-FF */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 2;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT;
f.enf_Filter[f.enf_FilterLen++] = 0xFFFF;
f.enf_Filter[f.enf_FilterLen++] =
ENF_CAND; /* dest addr = FF-FF */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 2;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT;
f.enf_Filter[f.enf_FilterLen++] = 0xFFFF;
f.enf_Filter[f.enf_FilterLen++] =
ENF_EQ; /* dest addr = FF-FF */
return; }
Note that shortwords, such as the packet type field, are
in network byte-order. The literals you compare them to
may have to be byte-swapped on machines like the VAX.
By taking advantage of the ability to specify both an
action and operation in each word of the command list, you
could abbreviate the filter to the following:
struct enfilter f;
buildfilter() {
f.enf_Priority = 36; /* anything > 2 should work */
f.enf_FilterLen = 0;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 6;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT |
ENF_CAND;
f.enf_Filter[f.enf_FilterLen++] =
0x3580; /* Ethernet type == 0x8035 (RARP)
*/
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 10;
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHLIT |
ENF_CAND;
f.enf_Filter[f.enf_FilterLen++] =
0x0300; /* reverse request type = 0003 */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 0;
f.enf_Filter[f.enf_FilterLen++] =
ENF_PUSHFFFF | ENF_CAND; /* dest addr = FF-FF */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 1;
f.enf_Filter[f.enf_FilterLen++] =
ENF_PUSHFFFF | ENF_CAND; /* dest addr = FF-FF */
f.enf_Filter[f.enf_FilterLen++] = ENF_PUSHWORD + 2;
f.enf_Filter[f.enf_FilterLen++] =
ENF_PUSHFFFF | ENF_EQ; /* dest addr = FF-FF */
return; }
Packet-Handling ioctl Requests [Toc] [Back]
These ioctl requests control how the packet filter processes
input packets and returns them to the application
process. The most useful of these requests set and clear
so-called ``mode bits'' for the file and are of this form:
ioctl(fildes, code, bits) u_short *bits;
In these calls, bits is a bitmask specifying which bits to
set or clear. The applicable codes are: Sets the specified
mode bits. Clears the specified mode bits.
The bits are: If set, a received packet is preceded by a
header structure (see the description of enstamp following)
that includes a time stamp and other information. If
clear, each read(2) system call returns at most one
packet. If set, a read call might return more than one
packet, each of which is preceded by an enstamp header.
If set, this filter will be applied to promiscuouslyreceived
packets. This puts the interface into ``promiscuous
mode'' only if this has been allowed by the superuser
using the EIOCALLOWPROMISC ioctl call (described later).
If set, this filter will see packets sent and received by
the kernel-resident protocols of the local host. (Normally,
these packets are not copied to the packet filter.)
This mode takes effect only if this has been allowed by
the superuser using the EIOCALLOWCOPYALL ioctl call
(described later). If set, packets accepted by this filter
will be available to any lower-priority filters. If
clear, no lower-priority filter will see packets accepted
by this filter. If clear, means that the driver should
disable the effect of EIOCENBS (described later) once it
has delivered a signal. If set (the default), the effect
of EIOCENBS persists. If set, a received packet is preceded
by a BPF-style header (see bpf(7).
The enstamp structure contains useful information about
the packet that immediately follows it; in ENBATCH mode,
it also allows the reader to separate the packets in a
batch. It is defined in <net/pfilt.h> as:
struct enstamp { u_short ens_stamplen;
u_short ens_flags;
u_short ens_count;
u_short ens_dropped;
u_int ens_ifoverflows;
struct timevalens_tstamp; };
The fields are: The length of enstamp structure in bytes.
The packet data follows immediately. Indicates how the
packet was received. The bits are: Received promiscuously
(unicast to some other host). Received as a broadcast.
Received as a multicast. Received in a trailer encapsulation.
The packet has been rearranged into header format.
The length of the packet in bytes (does not include the
enstamp header). The number of packets accepted by this
filter but dropped because the input queue was full; this
is a cumulative count since the previous enstamp was read
from this packet filter file. This count may be completely
wrong if the ENNONEXCL mode bit is set for this
filter. The total number of input overflows reported by
the network interface since the system was booted. The
approximate time the packet was received.
If the buffer returned by a batched read(2) contains more
than one packet, the offset from the beginning of the
buffer at which each enstamp structure begins is an integer
multiple of the word-size of the processor. For example,
on a VAX, each enstamp is aligned on a longword
boundary (provided that the buffer address passed to the
read(2) system call is aligned). The alignment (in units
of bytes) is given by the constant ENALIGNMENT, defined in
<net/pfilt.h>. If you have an integer x, you can use the
macro ENALIGNx to get the least integer that is a multiple
of ENALIGNMENT and not less than x. For example, this code
fragment reads and processes one batch:
char *buffer = &(BigBuffer[0]); int buflen; int pktlen,
stamplen; struct enstamp *stamp;
buflen = read(f, buffer, sizeof(BigBuffer)); while (buflen
> 0) {
stamp = (struct enstamp *)buffer;
pktlen = stamp->ens_count;
stamplen = stamp->ens_stamplen;
ProcessPacket(&(buffer[stamplen]), pktlen); /* your
code here */
if (buflen == (pktlen + stamplen))
break; /* last packet
in batch */
pktlen = ENALIGN(pktlen); /* account for alignment
padding */
buflen -= (pktlen + stamplen);
buffer += (pktlen + stamplen); /* move to
next stamp */ }
If a buffer filled by a batched read contains more than
one packet, the final packet is never truncated. If, however,
the entire buffer is not big enough to contain a
single packet, the packet will be truncated; this is also
true for unbatched reads. Therefore, the buffer passed to
the read(2) system call should always be big enough to
hold the largest possible packet plus an enstamp structure.
(See the EIOCDEVP ioctl request later in this reference
page for information on how to determine the maximum
packet size. See also the EIOCTRUNCATE ioctl request for
an example that delivers only the desired number of bytes
of a packet.)
Normally, a packet filter application blocks in the read
system call until a received packet is available for reading.
There are several ways to avoid blocking indefinitely:
an application can use the select(2) system call,
it can set a ``timeout'' for the packet filter file, or it
can request the delivery of a signal (see sigvec(2)) when
a packet matches the filter. The packet filter interface
limits the number of packets that can be queued for delivery
for a specific packet filter file. Application programs
can vary this ``backlog'', if necessary, using the
following call:
ioctl(fildes, EIOCSETW, maxwaitingp) u_int
*maxwaitingp;
The argument maxwaitingp points to an integer containing
the input queue size to be set. If this is
greater than the maximum allowable size (see EIOCMAXBACKLOG
later), it is set to the maximum. If it
is zero, it is set to a default value. After
changing the packet filter program, the input queue
may contain packets that were accepted under the
old filter. To flush the queue of incoming packets,
use the following:
ioctl(fildes, EIOCFLUSH, 0) An application, such as
a network load monitor, that does not want to see
the entire packet can ask the packet filter to
truncate received packets at a specified length.
This action may improve performance by reducing
data movement.
To specify truncation, use:
ioctl(fildes, EIOCTRUNCATE, truncationp) u_int
*truncationp;
The argument truncationp points to an integer specifying
the truncation length, in bytes. Packets
shorter than this length are passed intact.
This example, a revision of the previous example, illustrates
the use of EIOCTRUNCATE, which causes the packet
filter to deliver only the first n bytes of a packet, not
the entire packet.
char *buffer = &(BigBuffer[0]); int buflen; int pktlen,
stamplen; struct enstamp *stamp; int truncation =
SIZE_OF_INTERESTING_PART_OF_PACKET;
if (ioctl(f, EIOCTRUNCATE, &truncation) < 0)
exit(1);
while (1) {
buflen = read(f, buffer, sizeof(BigBuffer));
while (buflen > 0) {
stamp = (struct enstamp *)buffer;
pktlen = stamp->ens_count; /* ens_count is untruncated
length */
stamplen = stamp->ens_stamplen;
ProcessPacket(&(buffer[stamplen]), pktlen); /* your
code here */
if (pktlen > truncation) /* truncated portion not
in buffer */
pktlen = truncation;
if (buflen == (pktlen + stamplen))
break; /* last
packet in batch */
pktlen = ENALIGN(pktlen); /* account for alignment
padding */
buflen -= (pktlen + stamplen);
buffer += (pktlen + stamplen); /* move to
next stamp */
} }
Two calls control the timeout mechanism; they are of the
following form:
#include <net/time.h> ioctl(fildes, code, tvp)
struct timeval *tvp;
The tvp argument is the address of a struct timeval containing
the timeout interval (this is a relative value,
not an absolute time).
The codes are: Returns the current timeout value. Sets
the timeout value. When the value is positive, a read(2)
call returns a 0 if no packet arrives during the period.
When the timeout value is zero, reads block indefinitely
(this is the default). When the value is negative, a
read(2) call returns a 0 immediately if there are no
queued packets. Note that the largest legal timeout value
is a few million seconds.
Two calls control the signal-on-reception mechanism; they
are of the following form:
ioctl(fildes, code, signp) u_int *signp;
The argument signp is a pointer to an integer containing
the number of the signal to be sent when an input packet
arrives. The applicable codes are: Enables the specified
signal when an input packet is received for this file. If
the ENHOLDSIG flag (see EIOCMBIS later) is not set, further
signals are automatically disabled whenever a signal
is sent to prevent nesting, and hence must be explicitly
re-enabled after processing. When the signal number is 0,
this call is equivalent to EIOCINHS. Disables signaling
on packet reception. The signp argument is ignored. This
is the default when the file is first opened.
Device Configuration ioctl Requests [Toc] [Back]
Each packet filter file is associated with a specific network
interface. To find out the name of the interface
underlying the packet filter file, use the following:
#include <net/socket.h> #include <net/if.h>
ioctl(fildes, EIOCIFNAME, ifr) struct ifreq *ifr;
The interface name (for example, ``ln0'') is
returned in ifr->ifr_name; other fields of the
struct ifreq are not set. To set the interface
associated with a packet filter file, use the
following:
ioctl(fildes, EIOCSETIF, ifr) struct ifreq *ifr;
The interface name should be passed ifr->ifr_name;
other fields of the struct ifreq are ignored. The
name provided may be one of the actual interface
names, such as ``ln0'' or ``xna1'', or it may be a
pseudo-interface name of the form ``pfn'', used to
specify the nth interface attached to the system.
For example, ``pf0'' specifies the first interface.
This is useful for applications that do not know
the names of specific interfaces. Pseudo-interface
names are never returned by EIOCIFNAME. To get
device parameters of the network interface underlying
the packet filter file, use the following:
ioctl(fildes, EIOCDEVP, param) struct endevp
*param;
The endevp structure is defined in <net/pfilt.h>
as:
struct endevp {
u_char end_dev_type;
u_char end_addr_len;
u_short end_hdr_len;
u_short end_MTU;
u_char end_addr[EN_MAX_ADDR_LEN];
u_char end_broadaddr[EN_MAX_ADDR_LEN];
};
The fields are: Specifies the device type:
ENDT_10MB or ENDT_FDDI. (ENDT_3MB and ENDT_BS3MB
are defined but no longer supported.) Specifies
the address length in bytes (for example, 1 or 6).
Specifies the total header length in bytes (for
example, 4 or 14). Specifies the maximum packet
size, including header, in bytes. The address of
this interface; aligned so that the low order byte
of the address is in end_addr[0]. The hardware
destination address for broadcasts on this network.
Administrative ioctl Requests [Toc] [Back]
The maximum queue length that can be set using EIOCSETW
depends on whether the process is running as the superuser
or not. If so, the maximum is a kernel constant; otherwise,
the maximum is a value that can be set, by the superuser,
for each interface. To set the maximum non-superuser
backlog for an interface, use EIOCSETIF to bind to
the interface, and then use the following:
ioctl(fildes, EIOCMAXBACKLOG, maxbacklogp) int
*maxbacklogp;
The argument maxbacklogp points to an integer containing
the maximum value. (If maxbacklogp points
to an integer containing a negative value, it is
replaced with the current backlog value, and no
action is taken.) Certain kinds of network-monitoring
applications need to place the interface in
``promiscuous mode'', where it receives all packets
on the network. Promiscuous mode can be set by the
superuser with the /usr/sbin/ifconfig command, or
the superuser can configure an interface to go into
promiscuous mode automatically if any packet filter
applications have the ENPROMISC mode bit set. To
do so, use EIOCSETIF to bind to the interface, and
then use the following:
ioctl(fildes, EIOCALLOWPROMISC, allowp) int
*allowp;
The argument allowp points to an integer containing
a Boolean value (nonzero means promiscuous mode is
set automatically). (If allowp points to an integer
containing a negative value, it is replaced with
the current Boolean value, and no action is taken.)
Certain promiscuous-mode network-monitoring applications
need to see unicast packets sent or
received by the local host. For reasons of efficiency,
these packets are not normally provided to
the packet filter, but in ``copy all'' mode they
are. The superuser can configure an interface to
go into copy-all mode automatically if any packet
filter applications have the ENCOPYALL mode bit
set. To do so, use EIOCSETIF to bind to the interface,
and then use the following:
ioctl(fildes, EIOCALLOWCOPYALL, allowp) int
*allowp;
The argument allowp points to an integer containing
a Boolean value (nonzero means copy-all mode is set
automatically). (If allowp points to an integer
containing a negative value, it is replaced with
the current Boolean value, and no action is taken.)
To find out how many packet filter files remain for
opening, use this ioctl, which places the number in
the integer pointed to by mfree:
ioctl(fildes, EIOCMFREE, mfree) int *mfree;
Miscellaneous ioctl Requests [Toc] [Back]
Two calls are provided for backwards compatibility and
should not be used in new code. These calls are used to
set and fetch parameters of a packet filter file (not the
underlying device; see EIOCDEVP). The form for these
calls is:
#include <sys/types.h> #include <net/pfilt.h>
ioctl(fildes, code, param) struct eniocb *param;
The structure eniocb is defined in <net/pfilt.h> as:
struct eniocb { u_char en_addr;
u_char en_maxfilters;
u_char en_maxwaiting;
u_char en_maxpriority;
int en_rtout; };
The applicable codes are: Fetch the parameters for this
file. Set the parameters for this file. All the fields,
which are described later, except en_rtout, are read-only.
No longer maintained; use EIOCDEVP. The maximum length of
a filter command list; see EIOCSETF. The maximum number
of packets that can be queued for reading on the packet
filter file; use EIOCMAXBACKLOG. The highest allowable
filter priority; see EIOCSETF. The number of clock ticks
to wait before timing out on a read request and returning
a zero length. If zero, reads block indefinitely until a
packet arrives. If negative, read requests return a zero
length immediately if there are no packets in the input
queue. Initialized to zero by open(2), indicating no timeout.
(Use EIOCSRTIMEOUT and EIOCGRTIMEOUT.)
A previous restriction against accessing data words past
approximately the first hundred bytes in a packet has been
removed. However, it becomes slightly more costly to
examine words that are not near the beginning of the
packet.
Because packets are streams of bytes, yet the filters
operate on short words, and standard network byte order is
usually opposite from little-endian byte-order, the relational
operators ENF_LT, ENF_LE, ENF_GT, and ENF_GE are
not particularly useful. If this becomes a severe problem,
a byte-swapping operator could be added.
Packet filter special files. Example packet filter program.
Commands: vmstat(1), dxkerneltuner(8), ifconfig(8),
MAKEDEV(8), nfswatch(8), pfconfig(8), pfstat(1), sysconfig(8), tcpdump(8)
Files: bpf(7), fta(7), fza(7), ln(7), tty(7), xna(7)
Routines: pfopen(3)
SystemAttributes: sys_attrs_net(5)
packetfilter(7)
[ Back ] |