1pfmod(7M) STREAMS Modules pfmod(7M)
2
3
4
6 pfmod - STREAMS Packet Filter Module
7
9 #include <sys/pfmod.h>
10
11
12 ioctl(fd, IPUSH, "pfmod");
13
14
16 pfmod is a STREAMS module that subjects messages arriving on its read
17 queue to a packet filter and passes only those messages that the filter
18 accepts on to its upstream neighbor. Such filtering can be very useful
19 for user-level protocol implementations and for networking monitoring
20 programs that wish to view only specific types of events.
21
22 Read-side Behavior
23 pfmod applies the current packet filter to all M_DATA and M_PROTO mes‐
24 sages arriving on its read queue. The module prepares these messages
25 for examination by first skipping over all leading M_PROTO message
26 blocks to arrive at the beginning of the message's data portion. If
27 there is no data portion, pfmod accepts the message and passes it along
28 to its upstream neighbor. Otherwise, the module ensures that the part
29 of the message's data that the packet filter might examine lies in con‐
30 tiguous memory, calling the pullupmsg(9F) utility routine if necessary
31 to force contiguity. (Note: this action destroys any sharing relation‐
32 ships that the subject message might have had with other messages.)
33 Finally, it applies the packet filter to the message's data, passing
34 the entire message upstream to the next module if the filter accepts,
35 and discarding the message otherwise. See PACKET FILTERS below for
36 details on how the filter works.
37
38
39 If there is no packet filter yet in effect, the module acts as if the
40 filter exists but does nothing, implying that all incoming messages are
41 accepted. The ioctls section below describes how to associate a packet
42 filter with an instance of pfmod.
43
44
45 pfmod passes all other messages through unaltered to its upper neigh‐
46 bor.
47
48 Write-side Behavior
49 pfmod intercepts M_IOCTL messages for the ioctl described below. The
50 module passes all other messages through unaltered to its lower neigh‐
51 bor.
52
54 pfmod responds to the following ioctl.
55
56 PFIOCSETF This ioctl directs the module to replace its current
57 packet filter, if any, with the filter specified by the
58 struct packetfilt pointer named by its final argument.
59 This structure is defined in <sys/pfmod.h> as:
60
61
62 struct packetfilt {
63 uchar_t Pf_Priority; /* priority of filter */
64 uchar_t Pf_FilterLen; /* length of filter cmd list */
65 ushort_t Pf_Filter[ENMAXFILTERS]; /* filter command list */
66 };
67
68
69
70 The Pf_Priority field is included only for compatibility with other
71 packet filter implementations and is otherwise ignored. The packet fil‐
72 ter itself is specified in the Pf_Filter array as a sequence of two-
73 byte commands, with the Pf_FilterLen field giving the number of com‐
74 mands in the sequence. This implementation restricts the maximum number
75 of commands in a filter (ENMAXFILTERS) to 255. The next section
76 describes the available commands and their semantics.
77
79 A packet filter consists of the filter command list length (in units of
80 ushort_ts), and the filter command list itself. (The priority field
81 mentioned above is ignored in this implementation.) Each filter command
82 list specifies a sequence of actions that operate on an internal stack
83 of ushort_ts ("shortwords") or an offset register. The offset register
84 is initially zero. Each shortword of the command list specifies an
85 action and a binary operator. Using _n_ as shorthand for the next
86 shortword of the instruction stream and _%oreg_ for the offset regis‐
87 ter, the list of actions is:
88
89 COMMAND SHORTWORDS ACTION
90 ENF_PUSHLIT 2 Push _n_ on the stack.
91 ENF_PUSHZERO 1 Push zero on the stack.
92 ENF_PUSHONE 1 Push one on the stack.
93 ENF_PUSHFFFF 1 Push 0xFFFF on the stack.
94 ENF_PUSHFF00 1 Push 0xFF00 on the stack.
95 ENF_PUSH00FF 1 Push 0x00FF on the stack.
96 ENF_LOAD_OFFSET 2 Load _n_ into _%oreg_.
97 ENF_BRTR 2 Branch forward _n_ shortwords if
98 the top element of the stack is
99 non-zero.
100 ENF_BRFL 2 Branch forward _n_ shortwords if
101 the top element of the stack is zero.
102 ENF_POP 1 Pop the top element from the stack.
103 ENF_PUSHWORD+m 1 Push the value of shortword (_m_ +
104 _%oreg_) of the packet onto the stack.
105
106
107
108 The binary operators can be from the set {ENF_EQ, ENF_NEQ, ENF_LT,
109 ENF_LE, ENF_GT,ENF_GE, ENF_AND, ENF_OR, ENF_XOR} which operate on the
110 top two elements of the stack and replace them with its result.
111
112
113 When both an action and operator are specified in the same shortword,
114 the action is performed followed by the operation.
115
116
117 The binary operator can also be from the set {ENF_COR, ENF_CAND,
118 ENF_CNOR, ENF_CNAND}. These are "short-circuit" operators, in that they
119 terminate the execution of the filter immediately if the condition they
120 are checking for is found, and continue otherwise. All pop two elements
121 from the stack and compare them for equality; ENF_CAND returns false if
122 the result is false; ENF_COR returns true if the result is true;
123 ENF_CNAND returns true if the result is false; ENF_CNOR returns false
124 if the result is true. Unlike the other binary operators, these four do
125 not leave a result on the stack, even if they continue.
126
127
128 The short-circuit operators should be used when possible, to reduce the
129 amount of time spent evaluating filters. When they are used, you should
130 also arrange the order of the tests so that the filter will succeed or
131 fail as soon as possible; for example, checking the IP destination
132 field of a UDP packet is more likely to indicate failure than the
133 packet type field.
134
135
136 The special action ENF_NOPUSH and the special operator ENF_NOP can be
137 used to only perform the binary operation or to only push a value on
138 the stack. Since both are (conveniently) defined to be zero, indicating
139 only an action actually specifies the action followed by ENF_NOP, and
140 indicating only an operation actually specifies ENF_NOPUSH followed by
141 the operation.
142
143
144 After executing the filter command list, a non-zero value (true) left
145 on top of the stack (or an empty stack) causes the incoming packet to
146 be accepted and a zero value (false) causes the packet to be rejected.
147 (If the filter exits as the result of a short-circuit operator, the
148 top-of-stack value is ignored.) Specifying an undefined operation or
149 action in the command list or performing an illegal operation or action
150 (such as pushing a shortword offset past the end of the packet or exe‐
151 cuting a binary operator with fewer than two shortwords on the stack)
152 causes a filter to reject the packet.
153
155 The packet filter module is not dependent on any particular device
156 driver or module but is commonly used with datalink drivers such as the
157 Ethernet driver. If the underlying datalink driver supports the Data
158 Link Provider Interface (DLPI) message set, the appropriate STREAMS
159 DLPI messages must be issued to attach the stream to a particular hard‐
160 ware device and bind a datalink address to the stream before the under‐
161 lying driver will route received packets upstream. Refer to the DLPI
162 Version 2 specification for details on this interface.
163
164
165 The reverse ARP daemon program may use code similar to the following
166 fragment to construct a filter that rejects all but RARP packets. That
167 is, it accepts only packets whose Ethernet type field has the value
168 ETHERTYPE_REVARP. The filter works whether a VLAN is configured or not.
169
170 struct ether_header eh; /* used only for offset values */
171 struct packetfilt pf;
172 register ushort_t *fwp = pf.Pf_Filter;
173 ushort_t offset;
174 int fd;
175 /*
176 * Push packet filter streams module.
177 */
178 if (ioctl(fd, I_PUSH, "pfmod") < 0)
179 syserr("pfmod");
180
181 /*
182 * Set up filter. Offset is the displacement of the Ethernet
183 * type field from the beginning of the packet in units of
184 * ushort_ts.
185 */
186 offset = ((uint_t) &eh.ether_type - (uint_t) &eh.ether_dhost) /
187 sizeof (us_short);
188 *fwp++ = ENF_PUSHWORD + offset;
189 *fwp++ = ENF_PUSHLIT;
190 *fwp++ = htons(ETHERTYPE_VLAN);
191 *fwp++ = ENF_EQ;
192 *fwp++ = ENF_BRFL;
193 *fwp++ = 3; /* If this isn't ethertype VLAN, don't change oreg */
194 *fwp++ = ENF_LOAD_OFFSET;
195 *fwp++ = 2; /* size of the VLAN tag in words */
196 *fwp++ = ENF_POP;
197 *fwp++ = ENF_PUSHWORD + offset;
198 *fwp++ = ENF_PUSHLIT;
199 *fwp++ = htons(ETHERTYPE_REVARP);
200 *fwp++ = ENF_EQ;
201 pf.Pf_FilterLen = fwp - &pf.PF_Filter[0];
202
203
204
205 This filter can be abbreviated by taking advantage of the ability to
206 combine actions and operations:
207
208 *fwp++ = ENF_PUSHWORD + offset;
209 *fwp++ = ENF_PUSHLIT | ENF_EQ;
210 *fwp++ = htons(ETHERTYPE_REVARP);
211 *fwp++ = htons(ETHERTYPE_VLAN);
212 *fwp++ = ENF_BRFL | ENF_NOP;
213 *fwp++ = 3;
214 *fwp++ = ENF_LOAD_OFFSET | ENF_NOP;
215 *fwp++ = 2;
216 *fwp++ = ENF_POP | ENF_NOP;
217 *fwp++ = ENF_PUSHWORD + offset;
218 *fwp++ = ENF_PUSHLIT | ENF_EQ;
219 *fwp++ = htons(ETHERTYPE_REVARP);
220
221
223 bufmod(7M), dlpi(7P), pullupmsg(9F)
224
225
226
227SunOS 5.11 18 June 2006 pfmod(7M)