4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * STREAMS Packet Filter Module
29 * This module applies a filter to messages arriving on its read
30 * queue, passing on messages that the filter accepts adn discarding
31 * the others. It supports ioctls for setting the filter.
33 * On the write side, the module simply passes everything through
36 * Based on SunOS 4.x version. This version has minor changes:
37 * - general SVR4 porting stuff
38 * - change name and prefixes from "nit" buffer to streams buffer
39 * - multithreading assumes configured as D_MTQPAIR
42 #include <sys/types.h>
43 #include <sys/sysmacros.h>
44 #include <sys/errno.h>
45 #include <sys/debug.h>
47 #include <sys/stropts.h>
48 #include <sys/stream.h>
51 #include <sys/sunddi.h>
53 #include <sys/strsun.h>
54 #include <sys/pfmod.h>
55 #include <sys/modctl.h>
58 * Expanded version of the Packetfilt structure that includes
59 * some additional fields that aid filter execution efficiency.
62 struct Pf_ext_packetfilt pf
;
63 #define pf_Priority pf.Pf_Priority
64 #define pf_FilterLen pf.Pf_FilterLen
65 #define pf_Filter pf.Pf_Filter
66 /* pointer to word immediately past end of filter */
67 ushort_t
*pf_FilterEnd
;
68 /* length in bytes of packet prefix the filter examines */
73 * (Internal) packet descriptor for FilterPacket
76 ushort_t
*pd_hdr
; /* header starting address */
77 uint_t pd_hdrlen
; /* header length in shorts */
78 ushort_t
*pd_body
; /* body starting address */
79 uint_t pd_bodylen
; /* body length in shorts */
84 * Function prototypes.
86 static int pfopen(queue_t
*, dev_t
*, int, int, cred_t
*);
87 static int pfclose(queue_t
*, int, cred_t
*);
88 static void pfioctl(queue_t
*wq
, mblk_t
*mp
);
89 static int FilterPacket(struct packdesc
*, struct epacketfilt
*);
91 * To save instructions, since STREAMS ignores the return value
92 * from these functions, they are defined as void here. Kind of icky, but...
94 static void pfwput(queue_t
*, mblk_t
*);
95 static void pfrput(queue_t
*, mblk_t
*);
97 static struct module_info pf_minfo
= {
99 "pfmod", /* mi_idname */
101 INFPSZ
, /* mi_maxpsz */
106 static struct qinit pf_rinit
= {
107 (int (*)())pfrput
, /* qi_putp */
109 pfopen
, /* qi_qopen */
110 pfclose
, /* qi_qclose */
111 NULL
, /* qi_qadmin */
112 &pf_minfo
, /* qi_minfo */
116 static struct qinit pf_winit
= {
117 (int (*)())pfwput
, /* qi_putp */
120 NULL
, /* qi_qclose */
121 NULL
, /* qi_qadmin */
122 &pf_minfo
, /* qi_minfo */
126 static struct streamtab pf_info
= {
127 &pf_rinit
, /* st_rdinit */
128 &pf_winit
, /* st_wrinit */
129 NULL
, /* st_muxrinit */
130 NULL
/* st_muxwinit */
133 static struct fmodsw fsw
= {
139 static struct modlstrmod modlstrmod
= {
140 &mod_strmodops
, "streams packet filter module", &fsw
143 static struct modlinkage modlinkage
= {
144 MODREV_1
, &modlstrmod
, NULL
150 return (mod_install(&modlinkage
));
156 return (mod_remove(&modlinkage
));
160 _info(struct modinfo
*modinfop
)
162 return (mod_info(&modlinkage
, modinfop
));
167 pfopen(queue_t
*rq
, dev_t
*dev
, int oflag
, int sflag
, cred_t
*crp
)
169 struct epacketfilt
*pfp
;
173 if (sflag
!= MODOPEN
)
180 * Allocate and initialize per-Stream structure.
182 pfp
= kmem_alloc(sizeof (struct epacketfilt
), KM_SLEEP
);
183 rq
->q_ptr
= WR(rq
)->q_ptr
= (char *)pfp
;
192 pfclose(queue_t
*rq
, int flags __unused
, cred_t
*credp __unused
)
194 struct epacketfilt
*pfp
= (struct epacketfilt
*)rq
->q_ptr
;
200 kmem_free(pfp
, sizeof (struct epacketfilt
));
201 rq
->q_ptr
= WR(rq
)->q_ptr
= NULL
;
207 * Write-side put procedure. Its main task is to detect ioctls.
208 * Other message types are passed on through.
211 pfwput(queue_t
*wq
, mblk_t
*mp
)
213 switch (mp
->b_datap
->db_type
) {
225 * Read-side put procedure. It's responsible for applying the
226 * packet filter and passing upstream message on or discarding it
227 * depending upon the results.
229 * Upstream messages can start with zero or more M_PROTO mblks
230 * which are skipped over before executing the packet filter
231 * on any remaining M_DATA mblks.
234 pfrput(queue_t
*rq
, mblk_t
*mp
)
236 struct epacketfilt
*pfp
= (struct epacketfilt
*)rq
->q_ptr
;
243 switch (DB_TYPE(mp
)) {
247 * Skip over protocol information and find the start
248 * of the message body, saving the overall message
251 for (mpp
= mp
; mp
&& (DB_TYPE(mp
) == M_PROTO
); mp
= mp
->b_cont
)
255 * Null body (exclusive of M_PROTO blocks) ==> accept.
256 * Note that a null body is not the same as an empty body.
264 * Pull the packet up to the length required by
265 * the filter. Note that doing so destroys sharing
266 * relationships, which is unfortunate, since the
267 * results of pulling up here are likely to be useful
268 * for shared messages applied to a filter on a sibling
271 * Most packet sources will provide the packet in two
272 * logical pieces: an initial header in a single mblk,
273 * and a body in a sequence of mblks hooked to the
274 * header. We're prepared to deal with variant forms,
275 * but in any case, the pullup applies only to the body
279 need
= pfp
->pf_PByteLen
;
280 if (mbp
&& (MBLKL(mbp
) < need
)) {
281 int len
= msgdsize(mbp
);
283 /* XXX discard silently on pullupmsg failure */
284 if (pullupmsg(mbp
, MIN(need
, len
)) == 0) {
291 * Misalignment (not on short boundary) ==> reject.
293 if (((uintptr_t)mp
->b_rptr
& (sizeof (ushort_t
) - 1)) ||
295 ((uintptr_t)mbp
->b_rptr
& (sizeof (ushort_t
) - 1)))) {
301 * These assignments are distasteful, but necessary,
302 * since the packet filter wants to work in terms of
303 * shorts. Odd bytes at the end of header or data can't
304 * participate in the filtering operation.
306 pd
.pd_hdr
= (ushort_t
*)mp
->b_rptr
;
307 pd
.pd_hdrlen
= (mp
->b_wptr
- mp
->b_rptr
) / sizeof (ushort_t
);
309 pd
.pd_body
= (ushort_t
*)mbp
->b_rptr
;
310 pd
.pd_bodylen
= (mbp
->b_wptr
- mbp
->b_rptr
) /
320 if (FilterPacket(&pd
, pfp
))
335 * Handle write-side M_IOCTL messages.
338 pfioctl(queue_t
*wq
, mblk_t
*mp
)
340 struct epacketfilt
*pfp
= (struct epacketfilt
*)wq
->q_ptr
;
341 struct Pf_ext_packetfilt
*upfp
;
342 struct packetfilt
*opfp
;
347 struct iocblk
*iocp
= (struct iocblk
*)mp
->b_rptr
;
350 switch (iocp
->ioc_cmd
) {
353 * Verify argument length. Since the size of packet filter
354 * got increased (ENMAXFILTERS was bumped up to 2047), to
355 * maintain backwards binary compatibility, we need to
356 * check for both possible sizes.
358 switch (iocp
->ioc_count
) {
359 case sizeof (struct Pf_ext_packetfilt
):
360 error
= miocpullup(mp
,
361 sizeof (struct Pf_ext_packetfilt
));
363 miocnak(wq
, mp
, 0, error
);
366 upfp
= (struct Pf_ext_packetfilt
*)mp
->b_cont
->b_rptr
;
367 if (upfp
->Pf_FilterLen
> PF_MAXFILTERS
) {
368 miocnak(wq
, mp
, 0, EINVAL
);
372 bcopy(upfp
, pfp
, sizeof (struct Pf_ext_packetfilt
));
373 pfp
->pf_FilterEnd
= &pfp
->pf_Filter
[pfp
->pf_FilterLen
];
376 case sizeof (struct packetfilt
):
377 error
= miocpullup(mp
, sizeof (struct packetfilt
));
379 miocnak(wq
, mp
, 0, error
);
382 opfp
= (struct packetfilt
*)mp
->b_cont
->b_rptr
;
383 /* this strange comparison keeps gcc from complaining */
384 if (opfp
->Pf_FilterLen
- 1 >= ENMAXFILTERS
) {
385 miocnak(wq
, mp
, 0, EINVAL
);
389 pfp
->pf
.Pf_Priority
= opfp
->Pf_Priority
;
390 pfp
->pf
.Pf_FilterLen
= (unsigned int)opfp
->Pf_FilterLen
;
392 bcopy(opfp
->Pf_Filter
, pfp
->pf
.Pf_Filter
,
393 sizeof (opfp
->Pf_Filter
));
394 pfp
->pf_FilterEnd
= &pfp
->pf_Filter
[pfp
->pf_FilterLen
];
398 miocnak(wq
, mp
, 0, EINVAL
);
403 * Find and record maximum byte offset that the
404 * filter users. We use this when executing the
405 * filter to determine how much of the packet
406 * body to pull up. This code depends on the
409 for (fwp
= pfp
->pf_Filter
; fwp
< pfp
->pf_FilterEnd
; fwp
++) {
410 arg
= *fwp
& ((1 << ENF_NBPA
) - 1);
413 if ((arg
-= ENF_PUSHWORD
) > maxoff
)
417 case ENF_LOAD_OFFSET
:
418 /* Point to the offset */
420 if (*fwp
> maxoffreg
)
427 /* Skip over the literal. */
443 * Convert word offset to length in bytes.
445 pfp
->pf_PByteLen
= (maxoff
+ maxoffreg
+ 1) * sizeof (ushort_t
);
446 miocack(wq
, mp
, 0, 0);
455 /* #define DEBUG 1 */
456 /* #define INNERDEBUG 1 */
459 #define enprintf(a) printf a
465 * Apply the packet filter given by pfp to the packet given by
466 * pp. Return nonzero iff the filter accepts the packet.
468 * The packet comes in two pieces, a header and a body, since
469 * that's the most convenient form for our caller. The header
470 * is in contiguous memory, whereas the body is in a mbuf.
471 * Our caller will have adjusted the mbuf chain so that its first
472 * min(MLEN, length(body)) bytes are guaranteed contiguous. For
473 * the sake of efficiency (and some laziness) the filter is prepared
474 * to examine only these two contiguous pieces. Furthermore, it
475 * assumes that the header length is even, so that there's no need
476 * to glue the last byte of header to the first byte of data.
479 #define opx(i) ((i) >> ENF_NBPA)
482 FilterPacket(struct packdesc
*pp
, struct epacketfilt
*pfp
)
484 int maxhdr
= pp
->pd_hdrlen
;
485 int maxword
= maxhdr
+ pp
->pd_bodylen
;
492 ushort_t stack
[ENMAXFILTERS
+1];
494 fp
= &pfp
->pf_Filter
[0];
495 fpe
= pfp
->pf_FilterEnd
;
497 enprintf(("FilterPacket(%p, %p, %p, %p):\n", pp
, pfp
, fp
, fpe
));
500 * Push TRUE on stack to start. The stack size is chosen such
501 * that overflow can't occur -- each operation can push at most
502 * one item on the stack, and the stack size equals the maximum
505 sp
= &stack
[ENMAXFILTERS
];
509 op
= *fp
>> ENF_NBPA
;
510 arg
= *fp
& ((1 << ENF_NBPA
) - 1);
517 * Since arg is unsigned,
518 * if it were less than ENF_PUSHWORD before,
519 * it would now be huge.
521 if (arg
+ offreg
< maxhdr
)
522 *--sp
= pp
->pd_hdr
[arg
+ offreg
];
523 else if (arg
+ offreg
< maxword
)
524 *--sp
= pp
->pd_body
[arg
- maxhdr
+ offreg
];
526 enprintf(("=>0(len)\n"));
548 case ENF_LOAD_OFFSET
:
557 enprintf(("BRTR: fp>=fpe\n"));
567 enprintf(("BRFL: fp>=fpe\n"));
573 if (sp
> &stack
[ENMAXFILTERS
]) {
574 enprintf(("stack underflow\n"));
582 if (sp
< &stack
[2]) { /* check stack overflow: small yellow zone */
583 enprintf(("=>0(--sp)\n"));
591 * all non-NOP operators binary, must have at least two operands
592 * on stack to evaluate.
594 if (sp
> &stack
[ENMAXFILTERS
-2]) {
595 enprintf(("=>0(sp++)\n"));
602 enprintf(("=>0(def)\n"));
632 /* short-circuit operators */
636 enprintf(("=>COR %x\n", *sp
));
642 enprintf(("=>CAND %x\n", *sp
));
648 enprintf(("=>COR %x\n", *sp
));
654 enprintf(("=>CNAND %x\n", *sp
));
660 enprintf(("=>%x\n", *sp
));