packetfilter(7)packetfilter(7)NAMEpacketfilter - Ethernet packet filter
SYNOPSIS
options PACKETFILTER
DESCRIPTION
The packet filter pseudo-device driver provides a raw interface to Eth‐
ernets and similar network data link layers. Packets received that are
not used by the kernel (for example, to support the IP and DECnet pro‐
tocol 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 spe‐
cial 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 insuffi‐
cient 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 con‐
trol'' field, which is normally followed by a 6-byte (Ethernet-style)
destination address and a 6-byte source address. For alignment rea‐
sons, the packet filter prepends a 3-byte padding field to incoming
packets, and expects to see a corresponding padding field on transmit‐
ted packets. See the declaration for "struct fddi_header" in
<netinet/if_fddi.h>. FDDI headers are usually followed by 802.2 head‐
ers; 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 pos‐
sibly short-swapped) to be intelligible on Tru64 UNIX systems.
The packet filters treat the entire packet, including headers, as unin‐
terpreted data. The user must supply the headers for transmitted pack‐
ets (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) ref‐
erence page), the application can apply several special ioctl requests
to an open packet filter file. The calls are divided into five cate‐
gories: packet-filter specifying, packet handling, device configura‐
tion, administrative, and miscellaneous.
The Tru64 UNIX packet filter also supports most of the BSD Packet Fil‐
ter (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
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 com‐
mand 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
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_PUSH‐
LIT 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
When both an action and an operator are specified in the same short‐
word, the action is performed, followed by the operation. You can com‐
bine 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. (Short-circuit operator) Returns true immedi‐
ately 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 Eth‐
ernet 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 specify‐
ing 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 val‐
ues according to their relative ``busyness'' (the filter that has pre‐
viously 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 fol‐
lowing 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 Reso‐
lution 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 process‐
ing 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 opera‐
tion 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
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 struc‐
ture (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 promiscuously-received 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. (Nor‐
mally, 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 fil‐
ters. 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 for‐
mat. 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 deter‐
mine 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 num‐
ber of packets that can be queued for delivery for a specific packet
filter file. Application programs can vary this ``backlog'', if neces‐
sary, 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 max‐
imum. If it is zero, it is set to a default value. After chang‐
ing the packet filter program, the input queue may contain pack‐
ets 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 speci‐
fied 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_INTEREST‐
ING_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 argu‐
ment is ignored. This is the default when the file is first opened.
Device Configuration ioctl Requests
Each packet filter file is associated with a specific network inter‐
face. To find out the name of the interface underlying the packet fil‐
ter 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 appli‐
cations 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 exam‐
ple, 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
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. Promiscu‐
ous 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 applica‐
tions 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
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 indefi‐
nitely until a packet arrives. If negative, read requests return a zero
length immediately if there are no packets in the input queue. Initial‐
ized to zero by open(2), indicating no timeout. (Use EIOCSRTIMEOUT and
EIOCGRTIMEOUT.)
RESTRICTIONS
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.
FILES
Packet filter special files. Example packet filter program.
SEE ALSO
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)