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