xref: /titanic_44/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_pf.c (revision 942214a9d3873106f26cc86dd4aef6ac6176b830)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS	*/
27 
28 #include <stdio.h>
29 #include <stddef.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/isa_defs.h>
37 
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/dlpi.h>
41 #include <sys/vlan.h>
42 #include <net/if.h>
43 #include <netinet/in_systm.h>
44 #include <netinet/in.h>
45 #include <netinet/ip.h>
46 #include <netinet/if_ether.h>
47 #include <netinet/tcp.h>
48 #include <netinet/udp.h>
49 #include <netdb.h>
50 #include <rpc/rpc.h>
51 #include <setjmp.h>
52 
53 #include <sys/pfmod.h>
54 #include "snoop.h"
55 #include "snoop_vlan.h"
56 
57 /*
58  * This module generates code for the kernel packet filter.
59  * The kernel packet filter is more efficient since it
60  * operates without context switching or moving data into
61  * the capture buffer.  On the other hand, it is limited
62  * in its filtering ability i.e. can't cope with variable
63  * length headers, can't compare the packet size, 1 and 4 octet
64  * comparisons are awkward, code space is limited to ENMAXFILTERS
65  * halfwords, etc.
66  * The parser is the same for the user-level packet filter though
67  * more limited in the variety of expressions it can generate
68  * code for.  If the pf compiler finds an expression it can't
69  * handle, it tries to set up a split filter in kernel and do the
70  * remaining filtering in userland. If that also fails, it resorts
71  * to userland filter. (See additional comment in pf_compile)
72  */
73 
74 extern struct Pf_ext_packetfilt pf;
75 static ushort_t *pfp;
76 jmp_buf env;
77 
78 int eaddr;	/* need ethernet addr */
79 
80 int opstack;	/* operand stack depth */
81 
82 #define	EQ(val)		(strcmp(token, val) == 0)
83 #define	IPV4_ONLY	0
84 #define	IPV6_ONLY	1
85 #define	IPV4_AND_IPV6	2
86 
87 /*
88  * The following constants represent the offsets in bytes from the beginning
89  * of the packet of the link and IP(v6) layer source/destination/type fields,
90  * initialized for Ethernet. Media specific code can set any unavailable
91  * link layer property's offset to -1 to indicate that the property's value
92  * is not available from the frame.
93  */
94 static int link_header_len = 14, link_type_offset = 12;
95 static int link_dest_offset = 0, link_src_offset = 6;
96 static int link_addr_len = 6;
97 
98 #define	IPV4_SRCADDR_OFFSET	(link_header_len + 12)
99 #define	IPV4_DSTADDR_OFFSET	(link_header_len + 16)
100 #define	IPV6_SRCADDR_OFFSET	(link_header_len + 8)
101 #define	IPV6_DSTADDR_OFFSET	(link_header_len + 24)
102 #define	IPV4_TYPE_HEADER_OFFSET	(9)
103 #define	IPV6_TYPE_HEADER_OFFSET	(6)
104 
105 static int inBrace = 0, inBraceOR = 0;
106 static int foundOR = 0;
107 char *tkp, *sav_tkp;
108 char *token;
109 enum { EOL, ALPHA, NUMBER, FIELD, ADDR_IP, ADDR_ETHER, SPECIAL,
110 	ADDR_IP6 } tokentype;
111 uint_t tokenval;
112 
113 enum direction { ANY, TO, FROM };
114 enum direction dir;
115 
116 extern void next();
117 
118 static void pf_expression();
119 static void pf_check_vlan_tag(uint_t offset);
120 static void pf_clear_offset_register();
121 static void pf_emit_load_offset(uint_t offset);
122 static void pf_match_ethertype(uint_t ethertype);
123 static void pf_check_transport_protocol(uint_t transport_protocol);
124 static void pf_compare_value_mask_generic(int offset, uint_t len,
125     uint_t val, int mask, uint_t op);
126 
127 /*
128  * This pointer points to the function that last generated
129  * instructions to change the offset register.  It's used
130  * for comparisons to see if we need to issue more instructions
131  * to change the register.
132  *
133  * It's initialized to pf_clear_offset_register because the offset
134  * register in pfmod is initialized to zero, similar to the state
135  * it would be in after executing the instructions issued by
136  * pf_clear_offset_register.
137  */
138 static void *last_offset_operation = (void*)pf_clear_offset_register;
139 
140 static void
141 pf_emit(x)
142 	ushort_t x;
143 {
144 	if (pfp > &pf.Pf_Filter[PF_MAXFILTERS - 1])
145 		longjmp(env, 1);
146 	*pfp++ = x;
147 }
148 
149 static void
150 pf_codeprint(code, len)
151 	ushort_t *code;
152 	int len;
153 {
154 	ushort_t *pc;
155 	ushort_t *plast = code + len;
156 	int op, action;
157 
158 	if (len > 0) {
159 		printf("Kernel Filter:\n");
160 	}
161 
162 	for (pc = code; pc < plast; pc++) {
163 		printf("\t%3d: ", pc - code);
164 
165 		op = *pc & 0xfc00;	/* high 10 bits */
166 		action = *pc & 0x3ff;	/* low   6 bits */
167 
168 		switch (action) {
169 		case ENF_PUSHLIT:
170 			printf("PUSHLIT ");
171 			break;
172 		case ENF_PUSHZERO:
173 			printf("PUSHZERO ");
174 			break;
175 #ifdef ENF_PUSHONE
176 		case ENF_PUSHONE:
177 			printf("PUSHONE ");
178 			break;
179 #endif
180 #ifdef ENF_PUSHFFFF
181 		case ENF_PUSHFFFF:
182 			printf("PUSHFFFF ");
183 			break;
184 #endif
185 #ifdef ENF_PUSHFF00
186 		case ENF_PUSHFF00:
187 			printf("PUSHFF00 ");
188 			break;
189 #endif
190 #ifdef ENF_PUSH00FF
191 		case ENF_PUSH00FF:
192 			printf("PUSH00FF ");
193 			break;
194 #endif
195 		case ENF_LOAD_OFFSET:
196 			printf("LOAD_OFFSET ");
197 			break;
198 		case ENF_BRTR:
199 			printf("BRTR ");
200 			break;
201 		case ENF_BRFL:
202 			printf("BRFL ");
203 			break;
204 		case ENF_POP:
205 			printf("POP ");
206 			break;
207 		}
208 
209 		if (action >= ENF_PUSHWORD)
210 			printf("PUSHWORD %d ", action - ENF_PUSHWORD);
211 
212 		switch (op) {
213 		case ENF_EQ:
214 			printf("EQ ");
215 			break;
216 		case ENF_LT:
217 			printf("LT ");
218 			break;
219 		case ENF_LE:
220 			printf("LE ");
221 			break;
222 		case ENF_GT:
223 			printf("GT ");
224 			break;
225 		case ENF_GE:
226 			printf("GE ");
227 			break;
228 		case ENF_AND:
229 			printf("AND ");
230 			break;
231 		case ENF_OR:
232 			printf("OR ");
233 			break;
234 		case ENF_XOR:
235 			printf("XOR ");
236 			break;
237 		case ENF_COR:
238 			printf("COR ");
239 			break;
240 		case ENF_CAND:
241 			printf("CAND ");
242 			break;
243 		case ENF_CNOR:
244 			printf("CNOR ");
245 			break;
246 		case ENF_CNAND:
247 			printf("CNAND ");
248 			break;
249 		case ENF_NEQ:
250 			printf("NEQ ");
251 			break;
252 		}
253 
254 		if (action == ENF_PUSHLIT ||
255 		    action == ENF_LOAD_OFFSET ||
256 		    action == ENF_BRTR ||
257 		    action == ENF_BRFL) {
258 			pc++;
259 			printf("\n\t%3d:   %d (0x%04x)", pc - code, *pc, *pc);
260 		}
261 
262 		printf("\n");
263 	}
264 }
265 
266 /*
267  * Emit packet filter code to check a
268  * field in the packet for a particular value.
269  * Need different code for each field size.
270  * Since the pf can only compare 16 bit quantities
271  * we have to use masking to compare byte values.
272  * Long word (32 bit) quantities have to be done
273  * as two 16 bit comparisons.
274  */
275 static void
276 pf_compare_value(int offset, uint_t len, uint_t val)
277 {
278 	/*
279 	 * If the property being filtered on is absent in the media
280 	 * packet, error out.
281 	 */
282 	if (offset == -1)
283 		pr_err("filter option unsupported on media");
284 
285 	switch (len) {
286 	case 1:
287 		pf_emit(ENF_PUSHWORD + offset / 2);
288 #if defined(_BIG_ENDIAN)
289 		if (offset % 2)
290 #else
291 		if (!(offset % 2))
292 #endif
293 		{
294 #ifdef ENF_PUSH00FF
295 			pf_emit(ENF_PUSH00FF | ENF_AND);
296 #else
297 			pf_emit(ENF_PUSHLIT | ENF_AND);
298 			pf_emit(0x00FF);
299 #endif
300 			pf_emit(ENF_PUSHLIT | ENF_EQ);
301 			pf_emit(val);
302 		} else {
303 #ifdef ENF_PUSHFF00
304 			pf_emit(ENF_PUSHFF00 | ENF_AND);
305 #else
306 			pf_emit(ENF_PUSHLIT | ENF_AND);
307 			pf_emit(0xFF00);
308 #endif
309 			pf_emit(ENF_PUSHLIT | ENF_EQ);
310 			pf_emit(val << 8);
311 		}
312 		break;
313 
314 	case 2:
315 		pf_emit(ENF_PUSHWORD + offset / 2);
316 		pf_emit(ENF_PUSHLIT | ENF_EQ);
317 		pf_emit((ushort_t)val);
318 		break;
319 
320 	case 4:
321 		pf_emit(ENF_PUSHWORD + offset / 2);
322 		pf_emit(ENF_PUSHLIT | ENF_EQ);
323 #if defined(_BIG_ENDIAN)
324 		pf_emit(val >> 16);
325 #elif defined(_LITTLE_ENDIAN)
326 		pf_emit(val & 0xffff);
327 #else
328 #error One of _BIG_ENDIAN and _LITTLE_ENDIAN must be defined
329 #endif
330 		pf_emit(ENF_PUSHWORD + (offset / 2) + 1);
331 		pf_emit(ENF_PUSHLIT | ENF_EQ);
332 #if defined(_BIG_ENDIAN)
333 		pf_emit(val & 0xffff);
334 #else
335 		pf_emit(val >> 16);
336 #endif
337 		pf_emit(ENF_AND);
338 		break;
339 	}
340 }
341 
342 /*
343  * same as pf_compare_value, but only for emiting code to
344  * compare ipv6 addresses.
345  */
346 static void
347 pf_compare_value_v6(int offset, uint_t len, struct in6_addr val)
348 {
349 	int i;
350 
351 	for (i = 0; i < len; i += 2) {
352 		pf_emit(ENF_PUSHWORD + offset / 2 + i / 2);
353 		pf_emit(ENF_PUSHLIT | ENF_EQ);
354 		pf_emit(*(uint16_t *)&val.s6_addr[i]);
355 		if (i != 0)
356 			pf_emit(ENF_AND);
357 	}
358 }
359 
360 
361 /*
362  * Same as above except mask the field value
363  * before doing the comparison.  The comparison checks
364  * to make sure the values are equal.
365  */
366 static void
367 pf_compare_value_mask(int offset, uint_t len, uint_t val, int mask)
368 {
369 	pf_compare_value_mask_generic(offset, len, val, mask, ENF_EQ);
370 }
371 
372 /*
373  * Same as above except the values are compared to see if they are not
374  * equal.
375  */
376 static void
377 pf_compare_value_mask_neq(int offset, uint_t len, uint_t val, int mask)
378 {
379 	pf_compare_value_mask_generic(offset, len, val, mask, ENF_NEQ);
380 }
381 
382 /*
383  * Similar to pf_compare_value.
384  *
385  * This is the utility function that does the actual work to compare
386  * two values using a mask.  The comparison operation is passed into
387  * the function.
388  */
389 static void
390 pf_compare_value_mask_generic(int offset, uint_t len, uint_t val, int mask,
391     uint_t op)
392 {
393 	/*
394 	 * If the property being filtered on is absent in the media
395 	 * packet, error out.
396 	 */
397 	if (offset == -1)
398 		pr_err("filter option unsupported on media");
399 
400 	switch (len) {
401 	case 1:
402 		pf_emit(ENF_PUSHWORD + offset / 2);
403 #if defined(_BIG_ENDIAN)
404 		if (offset % 2)
405 #else
406 		if (!offset % 2)
407 #endif
408 		{
409 			pf_emit(ENF_PUSHLIT | ENF_AND);
410 			pf_emit(mask & 0x00ff);
411 			pf_emit(ENF_PUSHLIT | op);
412 			pf_emit(val);
413 		} else {
414 			pf_emit(ENF_PUSHLIT | ENF_AND);
415 			pf_emit((mask << 8) & 0xff00);
416 			pf_emit(ENF_PUSHLIT | op);
417 			pf_emit(val << 8);
418 		}
419 		break;
420 
421 	case 2:
422 		pf_emit(ENF_PUSHWORD + offset / 2);
423 		pf_emit(ENF_PUSHLIT | ENF_AND);
424 		pf_emit(htons((ushort_t)mask));
425 		pf_emit(ENF_PUSHLIT | op);
426 		pf_emit(htons((ushort_t)val));
427 		break;
428 
429 	case 4:
430 		pf_emit(ENF_PUSHWORD + offset / 2);
431 		pf_emit(ENF_PUSHLIT | ENF_AND);
432 		pf_emit(htons((ushort_t)((mask >> 16) & 0xffff)));
433 		pf_emit(ENF_PUSHLIT | op);
434 		pf_emit(htons((ushort_t)((val >> 16) & 0xffff)));
435 
436 		pf_emit(ENF_PUSHWORD + (offset / 2) + 1);
437 		pf_emit(ENF_PUSHLIT | ENF_AND);
438 		pf_emit(htons((ushort_t)(mask & 0xffff)));
439 		pf_emit(ENF_PUSHLIT | op);
440 		pf_emit(htons((ushort_t)(val & 0xffff)));
441 
442 		pf_emit(ENF_AND);
443 		break;
444 	}
445 }
446 
447 /*
448  * Generate pf code to match an IPv4 or IPv6 address.
449  */
450 static void
451 pf_ipaddr_match(which, hostname, inet_type)
452 	enum direction which;
453 	char *hostname;
454 	int inet_type;
455 {
456 	bool_t found_host;
457 	uint_t *addr4ptr;
458 	uint_t addr4;
459 	struct in6_addr *addr6ptr;
460 	int h_addr_index;
461 	struct hostent *hp = NULL;
462 	int error_num = 0;
463 	boolean_t first = B_TRUE;
464 	int pass = 0;
465 
466 	/*
467 	 * The addr4offset and addr6offset variables simplify the code which
468 	 * generates the address comparison filter.  With these two variables,
469 	 * duplicate code need not exist for the TO and FROM case.
470 	 * A value of -1 describes the ANY case (TO and FROM).
471 	 */
472 	int addr4offset;
473 	int addr6offset;
474 
475 	found_host = 0;
476 
477 	if (tokentype == ADDR_IP) {
478 		hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
479 		if (hp == NULL) {
480 			if (error_num == TRY_AGAIN) {
481 				pr_err("could not resolve %s (try again later)",
482 				    hostname);
483 			} else {
484 				pr_err("could not resolve %s", hostname);
485 			}
486 		}
487 		inet_type = IPV4_ONLY;
488 	} else if (tokentype == ADDR_IP6) {
489 		hp = getipnodebyname(hostname, AF_INET6, 0, &error_num);
490 		if (hp == NULL) {
491 			if (error_num == TRY_AGAIN) {
492 				pr_err("could not resolve %s (try again later)",
493 				    hostname);
494 			} else {
495 				pr_err("could not resolve %s", hostname);
496 			}
497 		}
498 		inet_type = IPV6_ONLY;
499 	} else if (tokentype == ALPHA) {
500 		/* Some hostname i.e. tokentype is ALPHA */
501 		switch (inet_type) {
502 		case IPV4_ONLY:
503 			/* Only IPv4 address is needed */
504 			hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
505 			if (hp != NULL) {
506 				found_host = 1;
507 			}
508 			break;
509 		case IPV6_ONLY:
510 			/* Only IPv6 address is needed */
511 			hp = getipnodebyname(hostname, AF_INET6, 0, &error_num);
512 			if (hp != NULL) {
513 				found_host = 1;
514 			}
515 			break;
516 		case IPV4_AND_IPV6:
517 			/* Both IPv4 and IPv6 are needed */
518 			hp = getipnodebyname(hostname, AF_INET6,
519 			    AI_ALL | AI_V4MAPPED, &error_num);
520 			if (hp != NULL) {
521 				found_host = 1;
522 			}
523 			break;
524 		default:
525 			found_host = 0;
526 		}
527 
528 		if (!found_host) {
529 			if (error_num == TRY_AGAIN) {
530 				pr_err("could not resolve %s (try again later)",
531 				    hostname);
532 			} else {
533 				pr_err("could not resolve %s", hostname);
534 			}
535 		}
536 	} else {
537 		pr_err("unknown token type: %s", hostname);
538 	}
539 
540 	switch (which) {
541 	case TO:
542 		addr4offset = IPV4_DSTADDR_OFFSET;
543 		addr6offset = IPV6_DSTADDR_OFFSET;
544 		break;
545 	case FROM:
546 		addr4offset = IPV4_SRCADDR_OFFSET;
547 		addr6offset = IPV6_SRCADDR_OFFSET;
548 		break;
549 	case ANY:
550 		addr4offset = -1;
551 		addr6offset = -1;
552 		break;
553 	}
554 
555 	if (hp != NULL && hp->h_addrtype == AF_INET) {
556 		pf_match_ethertype(ETHERTYPE_IP);
557 		pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
558 		h_addr_index = 0;
559 		addr4ptr = (uint_t *)hp->h_addr_list[h_addr_index];
560 		while (addr4ptr != NULL) {
561 			if (addr4offset == -1) {
562 				pf_compare_value(IPV4_SRCADDR_OFFSET, 4,
563 				    *addr4ptr);
564 				if (h_addr_index != 0)
565 					pf_emit(ENF_OR);
566 				pf_compare_value(IPV4_DSTADDR_OFFSET, 4,
567 				    *addr4ptr);
568 				pf_emit(ENF_OR);
569 			} else {
570 				pf_compare_value(addr4offset, 4,
571 				    *addr4ptr);
572 				if (h_addr_index != 0)
573 					pf_emit(ENF_OR);
574 			}
575 			addr4ptr = (uint_t *)hp->h_addr_list[++h_addr_index];
576 		}
577 		pf_emit(ENF_AND);
578 	} else {
579 		/* first pass: IPv4 addresses */
580 		h_addr_index = 0;
581 		addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
582 		first = B_TRUE;
583 		while (addr6ptr != NULL) {
584 			if (IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
585 				if (first) {
586 					pf_match_ethertype(ETHERTYPE_IP);
587 					pf_check_vlan_tag(
588 					    ENCAP_ETHERTYPE_OFF/2);
589 					pass++;
590 				}
591 				IN6_V4MAPPED_TO_INADDR(addr6ptr,
592 				    (struct in_addr *)&addr4);
593 				if (addr4offset == -1) {
594 					pf_compare_value(IPV4_SRCADDR_OFFSET, 4,
595 					    addr4);
596 					if (!first)
597 						pf_emit(ENF_OR);
598 					pf_compare_value(IPV4_DSTADDR_OFFSET, 4,
599 					    addr4);
600 					pf_emit(ENF_OR);
601 				} else {
602 					pf_compare_value(addr4offset, 4,
603 					    addr4);
604 					if (!first)
605 						pf_emit(ENF_OR);
606 				}
607 				if (first)
608 					first = B_FALSE;
609 			}
610 			addr6ptr = (struct in6_addr *)
611 				hp->h_addr_list[++h_addr_index];
612 		}
613 		if (!first) {
614 			pf_emit(ENF_AND);
615 		}
616 		/* second pass: IPv6 addresses */
617 		h_addr_index = 0;
618 		addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
619 		first = B_TRUE;
620 		while (addr6ptr != NULL) {
621 			if (!IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
622 				if (first) {
623 					pf_match_ethertype(ETHERTYPE_IPV6);
624 					pf_check_vlan_tag(
625 					    ENCAP_ETHERTYPE_OFF/2);
626 					pass++;
627 				}
628 				if (addr6offset == -1) {
629 					pf_compare_value_v6(IPV6_SRCADDR_OFFSET,
630 					    16, *addr6ptr);
631 					if (!first)
632 						pf_emit(ENF_OR);
633 					pf_compare_value_v6(IPV6_DSTADDR_OFFSET,
634 					    16, *addr6ptr);
635 					pf_emit(ENF_OR);
636 				} else {
637 					pf_compare_value_v6(addr6offset, 16,
638 					    *addr6ptr);
639 					if (!first)
640 						pf_emit(ENF_OR);
641 				}
642 				if (first)
643 					first = B_FALSE;
644 			}
645 			addr6ptr = (struct in6_addr *)
646 				hp->h_addr_list[++h_addr_index];
647 		}
648 		if (!first) {
649 			pf_emit(ENF_AND);
650 		}
651 		if (pass == 2) {
652 			pf_emit(ENF_OR);
653 		}
654 	}
655 
656 	if (hp != NULL) {
657 		freehostent(hp);
658 	}
659 }
660 
661 
662 static void
663 pf_compare_address(int offset, uint_t len, uchar_t *addr)
664 {
665 	uint32_t val;
666 	uint16_t sval;
667 	boolean_t didone = B_FALSE;
668 
669 	/*
670 	 * If the property being filtered on is absent in the media
671 	 * packet, error out.
672 	 */
673 	if (offset == -1)
674 		pr_err("filter option unsupported on media");
675 
676 	while (len > 0) {
677 		if (len >= 4) {
678 			(void) memcpy(&val, addr, 4);
679 			pf_compare_value(offset, 4, val);
680 			addr += 4;
681 			offset += 4;
682 			len -= 4;
683 		} else if (len >= 2) {
684 			(void) memcpy(&sval, addr, 2);
685 			pf_compare_value(offset, 2, sval);
686 			addr += 2;
687 			offset += 2;
688 			len -= 2;
689 		} else {
690 			pf_compare_value(offset++, 1, *addr++);
691 			len--;
692 		}
693 		if (didone)
694 			pf_emit(ENF_AND);
695 		didone = B_TRUE;
696 	}
697 }
698 
699 /*
700  * Compare ethernet addresses.
701  */
702 static void
703 pf_etheraddr_match(which, hostname)
704 	enum direction which;
705 	char *hostname;
706 {
707 	struct ether_addr e, *ep = NULL;
708 
709 	if (isxdigit(*hostname))
710 		ep = ether_aton(hostname);
711 	if (ep == NULL) {
712 		if (ether_hostton(hostname, &e))
713 			if (!arp_for_ether(hostname, &e))
714 				pr_err("cannot obtain ether addr for %s",
715 					hostname);
716 		ep = &e;
717 	}
718 
719 	pf_clear_offset_register();
720 
721 	switch (which) {
722 	case TO:
723 		pf_compare_address(link_dest_offset, link_addr_len,
724 		    (uchar_t *)ep);
725 		break;
726 	case FROM:
727 		pf_compare_address(link_src_offset, link_addr_len,
728 		    (uchar_t *)ep);
729 		break;
730 	case ANY:
731 		pf_compare_address(link_dest_offset, link_addr_len,
732 		    (uchar_t *)ep);
733 		pf_compare_address(link_src_offset, link_addr_len,
734 		    (uchar_t *)ep);
735 		pf_emit(ENF_OR);
736 		break;
737 	}
738 }
739 
740 /*
741  * Emit code to compare the network part of
742  * an IP address.
743  */
744 static void
745 pf_netaddr_match(which, netname)
746 	enum direction which;
747 	char *netname;
748 {
749 	uint_t addr;
750 	uint_t mask = 0xff000000;
751 	struct netent *np;
752 
753 	if (isdigit(*netname)) {
754 		addr = inet_network(netname);
755 	} else {
756 		np = getnetbyname(netname);
757 		if (np == NULL)
758 			pr_err("net %s not known", netname);
759 		addr = np->n_net;
760 	}
761 
762 	/*
763 	 * Left justify the address and figure
764 	 * out a mask based on the supplied address.
765 	 * Set the mask according to the number of zero
766 	 * low-order bytes.
767 	 * Note: this works only for whole octet masks.
768 	 */
769 	if (addr) {
770 		while ((addr & ~mask) != 0) {
771 			mask |= (mask >> 8);
772 		}
773 	}
774 
775 	pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
776 
777 	switch (which) {
778 	case TO:
779 		pf_compare_value_mask(IPV4_DSTADDR_OFFSET, 4, addr, mask);
780 		break;
781 	case FROM:
782 		pf_compare_value_mask(IPV4_SRCADDR_OFFSET, 4, addr, mask);
783 		break;
784 	case ANY:
785 		pf_compare_value_mask(IPV4_SRCADDR_OFFSET, 4, addr, mask);
786 		pf_compare_value_mask(IPV4_DSTADDR_OFFSET, 4, addr, mask);
787 		pf_emit(ENF_OR);
788 		break;
789 	}
790 }
791 
792 /*
793  * A helper function to keep the code to emit instructions
794  * to change the offset register in one place.
795  *
796  * INPUTS: offset - An value representing an offset in 16-bit
797  *                  words.
798  * OUTPUTS:  If there is enough room in the storage for the
799  *           packet filtering program, instructions to load
800  *           a constant to the offset register.  Otherwise,
801  *           nothing.
802  */
803 static void
804 pf_emit_load_offset(uint_t offset)
805 {
806 	pf_emit(ENF_LOAD_OFFSET | ENF_NOP);
807 	pf_emit(offset);
808 }
809 
810 /*
811  * Clear pfmod's offset register.
812  *
813  * INPUTS:  none
814  * OUTPUTS:  Instructions to clear the offset register if
815  *           there is enough space remaining in the packet
816  *           filtering program structure's storage, and
817  *           the last thing done to the offset register was
818  *           not clearing the offset register.  Otherwise,
819  *           nothing.
820  */
821 static void
822 pf_clear_offset_register()
823 {
824 	if (last_offset_operation != (void*)pf_clear_offset_register) {
825 		pf_emit_load_offset(0);
826 		last_offset_operation = (void*)pf_clear_offset_register;
827 	}
828 }
829 
830 /*
831  * This function will issue opcodes to check if a packet
832  * is VLAN tagged, and if so, update the offset register
833  * with the appropriate offset.
834  *
835  * Note that if the packet is not VLAN tagged, then the offset
836  * register will be cleared.
837  *
838  * If the interface type is not an ethernet type, then this
839  * function returns without doing anything.
840  *
841  * If the last attempt to change the offset register occured because
842  * of a call to this function that was called with the same offset,
843  * then we don't issue packet filtering instructions.
844  *
845  * INPUTS:  offset - an offset in 16 bit words.  The function
846  *                   will set the offset register to this
847  *                   value if the packet is VLAN tagged.
848  * OUTPUTS:  If the conditions are met, packet filtering instructions.
849  */
850 static void
851 pf_check_vlan_tag(uint_t offset)
852 {
853 	static uint_t last_offset = 0;
854 
855 	if ((interface->mac_type == DL_ETHER ||
856 	    interface->mac_type == DL_CSMACD) &&
857 	    (last_offset_operation != (void*)pf_check_vlan_tag ||
858 	    last_offset != offset)) {
859 		/*
860 		 * First thing is to clear the offset register.
861 		 * We don't know what state it is in, and if it
862 		 * is not zero, then we have no idea what we load
863 		 * when we execute ENF_PUSHWORD.
864 		 */
865 		pf_clear_offset_register();
866 
867 		/*
868 		 * Check the ethertype.
869 		 */
870 		pf_compare_value(link_type_offset, 2, htons(ETHERTYPE_VLAN));
871 
872 		/*
873 		 * And if it's not VLAN, don't load offset to the offset
874 		 * register.
875 		 */
876 		pf_emit(ENF_BRFL | ENF_NOP);
877 		pf_emit(3);
878 
879 		/*
880 		 * Otherwise, load offset to the offset register.
881 		 */
882 		pf_emit_load_offset(offset);
883 
884 		/*
885 		 * Now get rid of the results of the comparison,
886 		 * we don't want the results of the comparison to affect
887 		 * other logic in the packet filtering program.
888 		 */
889 		pf_emit(ENF_POP | ENF_NOP);
890 
891 		/*
892 		 * Set the last operation at the end, or any time
893 		 * after the call to pf_clear_offset because
894 		 * pf_clear_offset uses it.
895 		 */
896 		last_offset_operation = (void*)pf_check_vlan_tag;
897 		last_offset = offset;
898 	}
899 }
900 
901 /*
902  * Utility function used to emit packet filtering code
903  * to match an ethertype.
904  *
905  * INPUTS:  ethertype - The ethertype we want to check for.
906  *                      Don't call htons on the ethertype before
907  *                      calling this function.
908  * OUTPUTS:  If there is sufficient storage available, packet
909  *           filtering code to check an ethertype.  Otherwise,
910  *           nothing.
911  */
912 static void
913 pf_match_ethertype(uint_t ethertype)
914 {
915 	/*
916 	 * If the user wants to filter on ethertype VLAN,
917 	 * then clear the offset register so that the offset
918 	 * for ENF_PUSHWORD points to the right place in the
919 	 * packet.
920 	 *
921 	 * Otherwise, call pf_check_vlan_tag to set the offset
922 	 * register such that the contents of the offset register
923 	 * plus the argument for ENF_PUSHWORD point to the right
924 	 * part of the packet, whether or not the packet is VLAN
925 	 * tagged.  We call pf_check_vlan_tag with an offset of
926 	 * two words because if the packet is VLAN tagged, we have
927 	 * to move past the ethertype in the ethernet header, and
928 	 * past the lower two octets of the VLAN header to get to
929 	 * the ethertype in the VLAN header.
930 	 */
931 	if (ethertype == ETHERTYPE_VLAN)
932 		pf_clear_offset_register();
933 	else
934 		pf_check_vlan_tag(2);
935 
936 	pf_compare_value(link_type_offset, 2, htons(ethertype));
937 }
938 
939 typedef struct {
940 	int	transport_protocol;
941 	int	network_protocol;
942 	/*
943 	 * offset is the offset in bytes from the beginning
944 	 * of the network protocol header to where the transport
945 	 * protocol type is.
946 	 */
947 	int	offset;
948 } transport_protocol_table_t;
949 
950 static transport_protocol_table_t mapping_table[] = {
951 	{IPPROTO_TCP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
952 	{IPPROTO_TCP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
953 	{IPPROTO_UDP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
954 	{IPPROTO_UDP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
955 	{IPPROTO_OSPF, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
956 	{IPPROTO_OSPF, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
957 	{IPPROTO_SCTP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
958 	{IPPROTO_SCTP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
959 	{IPPROTO_ICMP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
960 	{IPPROTO_ICMPV6, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
961 	{IPPROTO_ENCAP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
962 	{IPPROTO_ESP, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
963 	{IPPROTO_ESP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
964 	{IPPROTO_AH, ETHERTYPE_IP,   IPV4_TYPE_HEADER_OFFSET},
965 	{IPPROTO_AH, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET},
966 	{-1, 0, 0}	/* must be the final entry */
967 };
968 
969 /*
970  * This function uses the table above to generate a
971  * piece of a packet filtering program to check a transport
972  * protocol type.
973  *
974  * INPUTS:  tranport_protocol - the transport protocol we're
975  *                              interested in.
976  * OUTPUTS:  If there is sufficient storage, then packet filtering
977  *           code to check a transport protocol type.  Otherwise,
978  *           nothing.
979  */
980 static void
981 pf_check_transport_protocol(uint_t transport_protocol)
982 {
983 	int i = 0;
984 	uint_t number_of_matches = 0;
985 
986 	for (i = 0; mapping_table[i].transport_protocol != -1; i++) {
987 		if (transport_protocol ==
988 		    (uint_t)mapping_table[i].transport_protocol) {
989 			number_of_matches++;
990 			pf_match_ethertype(mapping_table[i].network_protocol);
991 			pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
992 			pf_compare_value(
993 				mapping_table[i].offset + link_header_len, 1,
994 				transport_protocol);
995 			pf_emit(ENF_AND);
996 			if (number_of_matches > 1) {
997 				/*
998 				 * Since we have two or more matches, in
999 				 * order to have a correct and complete
1000 				 * program we need to OR the result of
1001 				 * each block of comparisons together.
1002 				 */
1003 				pf_emit(ENF_OR);
1004 			}
1005 		}
1006 	}
1007 }
1008 
1009 static void
1010 pf_primary()
1011 {
1012 	for (;;) {
1013 		if (tokentype == FIELD)
1014 			break;
1015 
1016 		if (EQ("ip")) {
1017 			pf_match_ethertype(ETHERTYPE_IP);
1018 			opstack++;
1019 			next();
1020 			break;
1021 		}
1022 
1023 		if (EQ("ip6")) {
1024 			pf_match_ethertype(ETHERTYPE_IPV6);
1025 			opstack++;
1026 			next();
1027 			break;
1028 		}
1029 
1030 		if (EQ("pppoe")) {
1031 			pf_match_ethertype(ETHERTYPE_PPPOED);
1032 			pf_match_ethertype(ETHERTYPE_PPPOES);
1033 			pf_emit(ENF_OR);
1034 			opstack++;
1035 			next();
1036 			break;
1037 		}
1038 
1039 		if (EQ("pppoed")) {
1040 			pf_match_ethertype(ETHERTYPE_PPPOED);
1041 			opstack++;
1042 			next();
1043 			break;
1044 		}
1045 
1046 		if (EQ("pppoes")) {
1047 			pf_match_ethertype(ETHERTYPE_PPPOES);
1048 			opstack++;
1049 			next();
1050 			break;
1051 		}
1052 
1053 		if (EQ("arp")) {
1054 			pf_match_ethertype(ETHERTYPE_ARP);
1055 			opstack++;
1056 			next();
1057 			break;
1058 		}
1059 
1060 		if (EQ("vlan")) {
1061 			pf_match_ethertype(ETHERTYPE_VLAN);
1062 			pf_compare_value_mask_neq(VLAN_ID_OFFSET, 2,
1063 			    0, VLAN_ID_MASK);
1064 			pf_emit(ENF_AND);
1065 			opstack++;
1066 			next();
1067 			break;
1068 		}
1069 
1070 		if (EQ("vlan-id")) {
1071 			next();
1072 			if (tokentype != NUMBER)
1073 				pr_err("VLAN ID expected");
1074 			pf_match_ethertype(ETHERTYPE_VLAN);
1075 			pf_compare_value_mask(VLAN_ID_OFFSET, 2, tokenval,
1076 			    VLAN_ID_MASK);
1077 			pf_emit(ENF_AND);
1078 			opstack++;
1079 			next();
1080 			break;
1081 		}
1082 
1083 		if (EQ("rarp")) {
1084 			pf_match_ethertype(ETHERTYPE_REVARP);
1085 			opstack++;
1086 			next();
1087 			break;
1088 		}
1089 
1090 		if (EQ("tcp")) {
1091 			pf_check_transport_protocol(IPPROTO_TCP);
1092 			opstack++;
1093 			next();
1094 			break;
1095 		}
1096 
1097 		if (EQ("udp")) {
1098 			pf_check_transport_protocol(IPPROTO_UDP);
1099 			opstack++;
1100 			next();
1101 			break;
1102 		}
1103 
1104 		if (EQ("ospf")) {
1105 			pf_check_transport_protocol(IPPROTO_OSPF);
1106 			opstack++;
1107 			next();
1108 			break;
1109 		}
1110 
1111 
1112 		if (EQ("sctp")) {
1113 			pf_check_transport_protocol(IPPROTO_SCTP);
1114 			opstack++;
1115 			next();
1116 			break;
1117 		}
1118 
1119 		if (EQ("icmp")) {
1120 			pf_check_transport_protocol(IPPROTO_ICMP);
1121 			opstack++;
1122 			next();
1123 			break;
1124 		}
1125 
1126 		if (EQ("icmp6")) {
1127 			pf_check_transport_protocol(IPPROTO_ICMPV6);
1128 			opstack++;
1129 			next();
1130 			break;
1131 		}
1132 
1133 		if (EQ("ip-in-ip")) {
1134 			pf_check_transport_protocol(IPPROTO_ENCAP);
1135 			opstack++;
1136 			next();
1137 			break;
1138 		}
1139 
1140 		if (EQ("esp")) {
1141 			pf_check_transport_protocol(IPPROTO_ESP);
1142 			opstack++;
1143 			next();
1144 			break;
1145 		}
1146 
1147 		if (EQ("ah")) {
1148 			pf_check_transport_protocol(IPPROTO_AH);
1149 			opstack++;
1150 			next();
1151 			break;
1152 		}
1153 
1154 		if (EQ("(")) {
1155 			inBrace++;
1156 			next();
1157 			pf_expression();
1158 			if (EQ(")")) {
1159 				if (inBrace)
1160 					inBraceOR--;
1161 				inBrace--;
1162 				next();
1163 			}
1164 			break;
1165 		}
1166 
1167 		if (EQ("to") || EQ("dst")) {
1168 			dir = TO;
1169 			next();
1170 			continue;
1171 		}
1172 
1173 		if (EQ("from") || EQ("src")) {
1174 			dir = FROM;
1175 			next();
1176 			continue;
1177 		}
1178 
1179 		if (EQ("ether")) {
1180 			eaddr = 1;
1181 			next();
1182 			continue;
1183 		}
1184 
1185 		if (EQ("inet")) {
1186 			next();
1187 			if (EQ("host"))
1188 				next();
1189 			if (tokentype != ALPHA && tokentype != ADDR_IP)
1190 				pr_err("host/IPv4 addr expected after inet");
1191 			pf_ipaddr_match(dir, token, IPV4_ONLY);
1192 			opstack++;
1193 			next();
1194 			break;
1195 		}
1196 
1197 		if (EQ("inet6")) {
1198 			next();
1199 			if (EQ("host"))
1200 				next();
1201 			if (tokentype != ALPHA && tokentype != ADDR_IP6)
1202 				pr_err("host/IPv6 addr expected after inet6");
1203 			pf_ipaddr_match(dir, token, IPV6_ONLY);
1204 			opstack++;
1205 			next();
1206 			break;
1207 		}
1208 
1209 		if (EQ("proto")) {
1210 			next();
1211 			if (tokentype != NUMBER)
1212 				pr_err("IP proto type expected");
1213 			pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2);
1214 			pf_compare_value(IPV4_TYPE_HEADER_OFFSET, 1, tokenval);
1215 			opstack++;
1216 			next();
1217 			break;
1218 		}
1219 
1220 		if (EQ("broadcast")) {
1221 			pf_clear_offset_register();
1222 			pf_compare_value(link_dest_offset, 4, 0xffffffff);
1223 			opstack++;
1224 			next();
1225 			break;
1226 		}
1227 
1228 		if (EQ("multicast")) {
1229 			pf_clear_offset_register();
1230 			pf_compare_value_mask(link_dest_offset, 1, 0x01, 0x01);
1231 			opstack++;
1232 			next();
1233 			break;
1234 		}
1235 
1236 		if (EQ("ethertype")) {
1237 			next();
1238 			if (tokentype != NUMBER)
1239 				pr_err("ether type expected");
1240 			pf_match_ethertype(tokenval);
1241 			opstack++;
1242 			next();
1243 			break;
1244 		}
1245 
1246 		if (EQ("net") || EQ("dstnet") || EQ("srcnet")) {
1247 			if (EQ("dstnet"))
1248 				dir = TO;
1249 			else if (EQ("srcnet"))
1250 				dir = FROM;
1251 			next();
1252 			pf_netaddr_match(dir, token);
1253 			dir = ANY;
1254 			opstack++;
1255 			next();
1256 			break;
1257 		}
1258 
1259 		/*
1260 		 * Give up on anything that's obviously
1261 		 * not a primary.
1262 		 */
1263 		if (EQ("and") || EQ("or") ||
1264 		    EQ("not") || EQ("decnet") || EQ("apple") ||
1265 		    EQ("length") || EQ("less") || EQ("greater") ||
1266 		    EQ("port") || EQ("srcport") || EQ("dstport") ||
1267 		    EQ("rpc") || EQ("gateway") || EQ("nofrag") ||
1268 		    EQ("bootp") || EQ("dhcp") || EQ("slp") || EQ("ldap")) {
1269 			break;
1270 		}
1271 
1272 		if (EQ("host") || EQ("between") ||
1273 		    tokentype == ALPHA || /* assume its a hostname */
1274 		    tokentype == ADDR_IP ||
1275 		    tokentype == ADDR_IP6 ||
1276 		    tokentype == ADDR_ETHER) {
1277 			if (EQ("host") || EQ("between"))
1278 				next();
1279 			if (eaddr || tokentype == ADDR_ETHER) {
1280 				pf_etheraddr_match(dir, token);
1281 			} else if (tokentype == ALPHA) {
1282 				pf_ipaddr_match(dir, token, IPV4_AND_IPV6);
1283 			} else if (tokentype == ADDR_IP) {
1284 				pf_ipaddr_match(dir, token, IPV4_ONLY);
1285 			} else {
1286 				pf_ipaddr_match(dir, token, IPV6_ONLY);
1287 			}
1288 			dir = ANY;
1289 			eaddr = 0;
1290 			opstack++;
1291 			next();
1292 			break;
1293 		}
1294 
1295 		break;	/* unknown token */
1296 	}
1297 }
1298 
1299 static void
1300 pf_alternation()
1301 {
1302 	int s = opstack;
1303 
1304 	pf_primary();
1305 	for (;;) {
1306 		if (EQ("and"))
1307 			next();
1308 		pf_primary();
1309 		if (opstack != s + 2)
1310 			break;
1311 		pf_emit(ENF_AND);
1312 		opstack--;
1313 	}
1314 }
1315 
1316 static void
1317 pf_expression()
1318 {
1319 	pf_alternation();
1320 	while (EQ("or") || EQ(",")) {
1321 		if (inBrace)
1322 			inBraceOR++;
1323 		else
1324 			foundOR++;
1325 		next();
1326 		pf_alternation();
1327 		pf_emit(ENF_OR);
1328 		opstack--;
1329 	}
1330 }
1331 
1332 /*
1333  * Attempt to compile the expression
1334  * in the string "e".  If we can generate
1335  * pf code for it then return 1 - otherwise
1336  * return 0 and leave it up to the user-level
1337  * filter.
1338  */
1339 int
1340 pf_compile(e, print)
1341 	char *e;
1342 	int print;
1343 {
1344 	char *argstr;
1345 	char *sav_str, *ptr, *sav_ptr;
1346 	int inBr = 0, aheadOR = 0;
1347 
1348 	argstr = strdup(e);
1349 	sav_str = e;
1350 	tkp = argstr;
1351 	dir = ANY;
1352 
1353 	pfp = &pf.Pf_Filter[0];
1354 	if (setjmp(env)) {
1355 		return (0);
1356 	}
1357 
1358 	/*
1359 	 * Set media specific packet offsets that this code uses.
1360 	 */
1361 	if (interface->mac_type == DL_IB) {
1362 		link_header_len = 4;
1363 		link_type_offset = 0;
1364 		link_dest_offset = link_src_offset = -1;
1365 		link_addr_len = 20;
1366 	}
1367 
1368 	next();
1369 	pf_expression();
1370 
1371 	if (tokentype != EOL) {
1372 		/*
1373 		 * The idea here is to do as much filtering as possible in
1374 		 * the kernel. So even if we find a token we don't understand,
1375 		 * we try to see if we can still set up a portion of the filter
1376 		 * in the kernel and use the userland filter to filter the
1377 		 * remaining stuff. Obviously, if our filter expression is of
1378 		 * type A AND B, we can filter A in kernel and then apply B
1379 		 * to the packets that got through. The same is not true for
1380 		 * a filter of type A OR B. We can't apply A first and then B
1381 		 * on the packets filtered through A.
1382 		 *
1383 		 * (We need to keep track of the fact when we find an OR,
1384 		 * and the fact that we are inside brackets when we find OR.
1385 		 * The variable 'foundOR' tells us if there was an OR behind,
1386 		 * 'inBraceOR' tells us if we found an OR before we could find
1387 		 * the end brace i.e. ')', and variable 'aheadOR' checks if
1388 		 * there is an OR in the expression ahead. if either of these
1389 		 * cases become true, we can't split the filtering)
1390 		 */
1391 
1392 		if (foundOR || inBraceOR) {
1393 			/* FORGET IN KERNEL FILTERING */
1394 			return (0);
1395 		} else {
1396 
1397 			/* CHECK IF NO OR AHEAD */
1398 			sav_ptr = (char *)((uintptr_t)sav_str +
1399 						(uintptr_t)sav_tkp -
1400 						(uintptr_t)argstr);
1401 			ptr = sav_ptr;
1402 			while (*ptr != '\0') {
1403 				switch (*ptr) {
1404 				case '(':
1405 					inBr++;
1406 					break;
1407 				case ')':
1408 					inBr--;
1409 					break;
1410 				case 'o':
1411 				case 'O':
1412 					if ((*(ptr + 1) == 'R' ||
1413 						*(ptr + 1) == 'r') && !inBr)
1414 						aheadOR = 1;
1415 					break;
1416 				case ',':
1417 					if (!inBr)
1418 						aheadOR = 1;
1419 					break;
1420 				}
1421 				ptr++;
1422 			}
1423 			if (!aheadOR) {
1424 				/* NO OR AHEAD, SPLIT UP THE FILTERING */
1425 				pf.Pf_FilterLen = pfp - &pf.Pf_Filter[0];
1426 				pf.Pf_Priority = 5;
1427 				if (print) {
1428 					pf_codeprint(&pf.Pf_Filter[0],
1429 							pf.Pf_FilterLen);
1430 				}
1431 				compile(sav_ptr, print);
1432 				return (2);
1433 			} else
1434 				return (0);
1435 		}
1436 	}
1437 
1438 	pf.Pf_FilterLen = pfp - &pf.Pf_Filter[0];
1439 	pf.Pf_Priority = 5;	/* unimportant, so long as > 2 */
1440 	if (print) {
1441 		pf_codeprint(&pf.Pf_Filter[0], pf.Pf_FilterLen);
1442 	}
1443 	return (1);
1444 }
1445