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 <stdlib.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 <stddef.h>
36#include <unistd.h>
37#include <stropts.h>
38#include <sys/socket.h>
39#include <sys/sockio.h>
40#include <sys/vlan.h>
41#include <net/if.h>
42#include <netinet/in.h>
43#include <netinet/ip.h>
44#include <inet/ip6.h>
45#include <inet/ip.h>
46#include <netinet/if_ether.h>
47#include <netinet/tcp.h>
48#include <netinet/udp.h>
49#include <netdb.h>
50#include <arpa/inet.h>
51#include <rpc/rpc.h>
52#include <rpc/rpcent.h>
53#include <sys/dlpi.h>
54
55#include <snoop.h>
56#include "snoop_vlan.h"
57
58#define	IPV4_ONLY	0
59#define	IPV6_ONLY	1
60#define	IPV4_AND_IPV6	2
61
62/*
63 * The following constants represent the offsets in bytes from the beginning
64 * of the IP(v6) header of the source and destination IP(v6) addresses.
65 * These are useful when generating filter code.
66 */
67#define	IPV4_SRCADDR_OFFSET	12
68#define	IPV4_DSTADDR_OFFSET	16
69#define	IPV6_SRCADDR_OFFSET	8
70#define	IPV6_DSTADDR_OFFSET	24
71#define	IP_VERS(p)	(((*(uchar_t *)p) & 0xf0) >> 4)
72#define	MASKED_IPV4_VERS	0x40
73#define	MASKED_IPV6_VERS	0x60
74#define	IP_HDR_LEN(p)	(((*(uchar_t *)p) & 0xf) * 4)
75#define	TCP_HDR_LEN(p)	((((*((uchar_t *)p+12)) >> 4) & 0xf) * 4)
76
77/*
78 * Coding the constant below is tacky, but the compiler won't let us
79 * be more clever.  E.g., &((struct ip *)0)->ip_xxx
80 */
81#define	IP_PROTO_OF(p)	(((uchar_t *)p)[9])
82
83/*
84 * AppleTalk uses 802.2 Ethernet encapsulation with LLC/SNAP headers,
85 * for 8 octets of overhead, and the common AppleTalk DDP Ethernet
86 * header is another 4 octets.
87 *
88 * The following constants represents the offsets in bytes from the beginning
89 * of the Ethernet payload to various parts of the DDP header.
90 */
91
92#define	AT_DST_NET_OFFSET	12
93#define	AT_SRC_NET_OFFSET	14
94#define	AT_DST_NODE_OFFSET	16
95#define	AT_SRC_NODE_OFFSET	17
96
97/*
98 * Offset for the source and destination zoneid in the ipnet header.
99 */
100#define	IPNET_SRCZONE_OFFSET 16
101#define	IPNET_DSTZONE_OFFSET 20
102
103int eaddr;	/* need ethernet addr */
104
105int opstack;	/* operand stack depth */
106
107/*
108 * These are the operators of the user-level filter.
109 * STOP ends execution of the filter expression and
110 * returns the truth value at the top of the stack.
111 * OP_LOAD_OCTET, OP_LOAD_SHORT and OP_LOAD_LONG pop
112 * an offset value from the stack and load a value of
113 * an appropriate size from the packet (octet, short or
114 * long).  The offset is computed from a base value that
115 * may be set via the OP_OFFSET operators.
116 * OP_EQ, OP_NE, OP_GT, OP_GE, OP_LT, OP_LE pop two values
117 * from the stack and return the result of their comparison.
118 * OP_AND, OP_OR, OP_XOR pop two values from the stack and
119 * do perform a bitwise operation on them - returning a result
120 * to the stack.  OP_NOT inverts the bits of the value on the
121 * stack.
122 * OP_BRFL and OP_BRTR branch to an offset in the code array
123 * depending on the value at the top of the stack: true (not 0)
124 * or false (0).
125 * OP_ADD, OP_SUB, OP_MUL, OP_DIV and OP_REM pop two values
126 * from the stack and perform arithmetic.
127 * The OP_OFFSET operators change the base from which the
128 * OP_LOAD operators compute their offsets.
129 * OP_OFFSET_ZERO sets the offset to zero - beginning of packet.
130 * OP_OFFSET_LINK sets the base to the first octet after
131 * the link (DLC) header.  OP_OFFSET_IP, OP_OFFSET_TCP,
132 * and OP_OFFSET_UDP do the same for those headers - they
133 * set the offset base to the *end* of the header - not the
134 * beginning.  The OP_OFFSET_RPC operator is a bit unusual.
135 * It points the base at the cached RPC header.  For the
136 * purposes of selection, RPC reply headers look like call
137 * headers except for the direction value.
138 * OP_OFFSET_ETHERTYPE sets base according to the following
139 * algorithm:
140 *   if the packet is not VLAN tagged, then set base to
141 *         the ethertype field in the ethernet header
142 *   else set base to the ethertype field of the VLAN header
143 * OP_OFFSET_POP restores the offset base to the value prior
144 * to the most recent OP_OFFSET call.
145 */
146enum optype {
147	OP_STOP = 0,
148	OP_LOAD_OCTET,
149	OP_LOAD_SHORT,
150	OP_LOAD_LONG,
151	OP_LOAD_CONST,
152	OP_LOAD_LENGTH,
153	OP_EQ,
154	OP_NE,
155	OP_GT,
156	OP_GE,
157	OP_LT,
158	OP_LE,
159	OP_AND,
160	OP_OR,
161	OP_XOR,
162	OP_NOT,
163	OP_BRFL,
164	OP_BRTR,
165	OP_ADD,
166	OP_SUB,
167	OP_MUL,
168	OP_DIV,
169	OP_REM,
170	OP_OFFSET_POP,
171	OP_OFFSET_ZERO,
172	OP_OFFSET_LINK,
173	OP_OFFSET_IP,
174	OP_OFFSET_TCP,
175	OP_OFFSET_UDP,
176	OP_OFFSET_RPC,
177	OP_OFFSET_SLP,
178	OP_OFFSET_ETHERTYPE,
179	OP_LAST
180};
181
182static char *opnames[] = {
183	"STOP",
184	"LOAD_OCTET",
185	"LOAD_SHORT",
186	"LOAD_LONG",
187	"LOAD_CONST",
188	"LOAD_LENGTH",
189	"EQ",
190	"NE",
191	"GT",
192	"GE",
193	"LT",
194	"LE",
195	"AND",
196	"OR",
197	"XOR",
198	"NOT",
199	"BRFL",
200	"BRTR",
201	"ADD",
202	"SUB",
203	"MUL",
204	"DIV",
205	"REM",
206	"OFFSET_POP",
207	"OFFSET_ZERO",
208	"OFFSET_ETHER",
209	"OFFSET_IP",
210	"OFFSET_TCP",
211	"OFFSET_UDP",
212	"OFFSET_RPC",
213	"OP_OFFSET_SLP",
214	"OFFSET_ETHERTYPE",
215	""
216};
217
218#define	MAXOPS 1024
219#define	MAXSS	64
220static uint_t oplist[MAXOPS];	/* array of operators */
221static uint_t *curr_op;		/* last op generated */
222
223extern int valid_slp(uchar_t *, int);	/* decides if a SLP msg is valid */
224extern struct hostent *lgetipnodebyname(const char *, int, int, int *);
225
226static void alternation();
227static uint_t chain();
228static void codeprint();
229static void emitop();
230static void emitval();
231static void expression();
232static struct xid_entry *find_rpc();
233static void optimize();
234static void ethertype_match();
235
236/*
237 * Get a ushort from a possibly unaligned character buffer.
238 *
239 * INPUTS:  buffer - where the data is.  Must be at least
240 *          sizeof(uint16_t) bytes long.
241 * OUPUTS:  An unsigned short that contains the data at buffer.
242 *          No calls to ntohs or htons are done on the data.
243 */
244static uint16_t
245get_u16(uchar_t *buffer)
246{
247	uint8_t	*bufraw = buffer;
248
249	/*
250	 * ntohs is used only as a cheap way to flip the bits
251	 * around on a little endian platform.  The value will
252	 * still be in host order or network order, depending on
253	 * the order it was in when it was passed in.
254	 */
255	return (ntohs(bufraw[0] << 8 | bufraw[1]));
256}
257
258/*
259 * Returns the ULP for an IPv4 or IPv6 packet
260 * Assumes that the packet has already been checked to verify
261 * that it's either IPv4 or IPv6
262 *
263 * XXX Will need to be updated for AH and ESP
264 * XXX when IPsec is supported for v6.
265 */
266static uchar_t
267ip_proto_of(uchar_t *ip)
268{
269	uchar_t		nxt;
270	boolean_t	not_done = B_TRUE;
271	uchar_t		*ptr = ip;
272
273	switch (IP_VERS(ip)) {
274	case IPV4_VERSION:
275		return (IP_PROTO_OF(ip));
276	case IPV6_VERSION:
277
278		nxt = ip[6];
279		ptr += 40;		/* size of ip6 header */
280		do {
281			switch (nxt) {
282			/*
283			 * XXX Add IPsec headers here when supported for v6
284			 * XXX (the AH will have a different size...)
285			 */
286			case IPPROTO_HOPOPTS:
287			case IPPROTO_ROUTING:
288			case IPPROTO_FRAGMENT:
289			case IPPROTO_DSTOPTS:
290				ptr += (8 * (ptr[1] + 1));
291				nxt = *ptr;
292				break;
293
294			default:
295				not_done = B_FALSE;
296				break;
297			}
298		} while (not_done);
299		return (nxt);
300	default:
301		break;			/* shouldn't get here... */
302	}
303	return (0);
304}
305
306/*
307 * Returns the total IP header length.
308 * For v4, this includes any options present.
309 * For v6, this is the length of the IPv6 header plus
310 * any extension headers present.
311 *
312 * XXX Will need to be updated for AH and ESP
313 * XXX when IPsec is supported for v6.
314 */
315static int
316ip_hdr_len(uchar_t *ip)
317{
318	uchar_t		nxt;
319	int		hdr_len;
320	boolean_t	not_done = B_TRUE;
321	int		len = 40;	/* IPv6 header size */
322	uchar_t		*ptr = ip;
323
324	switch (IP_VERS(ip)) {
325	case IPV4_VERSION:
326		return (IP_HDR_LEN(ip));
327	case IPV6_VERSION:
328		nxt = ip[6];
329		ptr += len;
330		do {
331			switch (nxt) {
332			/*
333			 * XXX Add IPsec headers here when supported for v6
334			 * XXX (the AH will have a different size...)
335			 */
336			case IPPROTO_HOPOPTS:
337			case IPPROTO_ROUTING:
338			case IPPROTO_FRAGMENT:
339			case IPPROTO_DSTOPTS:
340				hdr_len = (8 * (ptr[1] + 1));
341				len += hdr_len;
342				ptr += hdr_len;
343				nxt = *ptr;
344				break;
345
346			default:
347				not_done = B_FALSE;
348				break;
349			}
350		} while (not_done);
351		return (len);
352	default:
353		break;
354	}
355	return (0);			/* not IP */
356}
357
358static void
359codeprint()
360{
361	uint_t *op;
362
363	printf("User filter:\n");
364
365	for (op = oplist; *op; op++) {
366		if (*op <= OP_LAST)
367			printf("\t%2d: %s\n", op - oplist, opnames[*op]);
368		else
369			printf("\t%2d: (%d)\n", op - oplist, *op);
370
371		switch (*op) {
372		case OP_LOAD_CONST:
373		case OP_BRTR:
374		case OP_BRFL:
375			op++;
376			if ((int)*op < 0)
377				printf("\t%2d:   0x%08x (%d)\n",
378				    op - oplist, *op, *op);
379			else
380				printf("\t%2d:   %d (0x%08x)\n",
381				    op - oplist, *op, *op);
382		}
383	}
384	printf("\t%2d: STOP\n", op - oplist);
385	printf("\n");
386}
387
388
389/*
390 * Take a pass through the generated code and optimize
391 * branches.  A branch true (BRTR) that has another BRTR
392 * at its destination can use the address of the destination
393 * BRTR.  A BRTR that points to a BRFL (branch false) should
394 * point to the address following the BRFL.
395 * A similar optimization applies to BRFL operators.
396 */
397static void
398optimize(uint_t *oplistp)
399{
400	uint_t *op;
401
402	for (op = oplistp; *op; op++) {
403		switch (*op) {
404		case OP_LOAD_CONST:
405			op++;
406			break;
407		case OP_BRTR:
408			op++;
409			optimize(&oplist[*op]);
410			if (oplist[*op] == OP_BRFL)
411				*op += 2;
412			else if (oplist[*op] == OP_BRTR)
413				*op = oplist[*op + 1];
414			break;
415		case OP_BRFL:
416			op++;
417			optimize(&oplist[*op]);
418			if (oplist[*op] == OP_BRTR)
419				*op += 2;
420			else if (oplist[*op] == OP_BRFL)
421				*op = oplist[*op + 1];
422			break;
423		}
424	}
425}
426
427/*
428 * RPC packets are tough to filter.
429 * While the call packet has all the interesting
430 * info: program number, version, procedure etc,
431 * the reply packet has none of this information.
432 * If we want to do useful filtering based on this
433 * information then we have to stash the information
434 * from the call packet, and use the XID in the reply
435 * to find the stashed info.  The stashed info is
436 * kept in a circular lifo, assuming that a call packet
437 * will be followed quickly by its reply.
438 */
439
440struct xid_entry {
441	unsigned	x_xid;		/* The XID (32 bits) */
442	unsigned	x_dir;		/* CALL or REPLY */
443	unsigned	x_rpcvers;	/* Protocol version (2) */
444	unsigned	x_prog;		/* RPC program number */
445	unsigned	x_vers;		/* RPC version number */
446	unsigned	x_proc;		/* RPC procedure number */
447};
448static struct xid_entry	xe_table[XID_CACHE_SIZE];
449static struct xid_entry	*xe_first = &xe_table[0];
450static struct xid_entry	*xe	  = &xe_table[0];
451static struct xid_entry	*xe_last  = &xe_table[XID_CACHE_SIZE - 1];
452
453static struct xid_entry *
454find_rpc(struct rpc_msg *rpc)
455{
456	struct xid_entry *x;
457
458	for (x = xe; x >= xe_first; x--)
459		if (x->x_xid == rpc->rm_xid)
460			return (x);
461	for (x = xe_last; x > xe; x--)
462		if (x->x_xid == rpc->rm_xid)
463			return (x);
464	return (NULL);
465}
466
467static void
468stash_rpc(struct rpc_msg *rpc)
469{
470	struct xid_entry *x;
471
472	if (find_rpc(rpc))
473		return;
474
475	x = xe++;
476	if (xe > xe_last)
477		xe = xe_first;
478	x->x_xid  = rpc->rm_xid;
479	x->x_dir  = htonl(REPLY);
480	x->x_prog = rpc->rm_call.cb_prog;
481	x->x_vers = rpc->rm_call.cb_vers;
482	x->x_proc = rpc->rm_call.cb_proc;
483}
484
485/*
486 * SLP can multicast requests, and recieve unicast replies in which
487 * neither the source nor destination port is identifiable as a SLP
488 * port. Hence, we need to do as RPC does, and keep track of packets we
489 * are interested in. For SLP, however, we use ports, not XIDs, and
490 * a smaller cache size is more efficient since every incoming packet
491 * needs to be checked.
492 */
493
494#define	SLP_CACHE_SIZE 64
495static uint_t slp_table[SLP_CACHE_SIZE];
496static int slp_index	= 0;
497
498/*
499 * Returns the index of dport in the table if found, otherwise -1.
500 */
501static int
502find_slp(uint_t dport) {
503    int i;
504
505    if (!dport)
506	return (0);
507
508    for (i = slp_index; i >= 0; i--)
509	if (slp_table[i] == dport) {
510	    return (i);
511	}
512    for (i = SLP_CACHE_SIZE - 1; i > slp_index; i--)
513	if (slp_table[i] == dport) {
514	    return (i);
515	}
516    return (-1);
517}
518
519static void stash_slp(uint_t sport) {
520    if (slp_table[slp_index - 1] == sport)
521	/* avoid redundancy due to multicast retransmissions */
522	return;
523
524    slp_table[slp_index++] = sport;
525    if (slp_index == SLP_CACHE_SIZE)
526	slp_index = 0;
527}
528
529/*
530 * This routine takes a packet and returns true or false
531 * according to whether the filter expression selects it
532 * or not.
533 * We assume here that offsets for short and long values
534 * are even - we may die with an alignment error if the
535 * CPU doesn't support odd addresses.  Note that long
536 * values are loaded as two shorts so that 32 bit word
537 * alignment isn't important.
538 *
539 * IPv6 is a bit stickier to handle than IPv4...
540 */
541
542int
543want_packet(uchar_t *pkt, int len, int origlen)
544{
545	uint_t stack[MAXSS];	/* operand stack */
546	uint_t *op;		/* current operator */
547	uint_t *sp;		/* top of operand stack */
548	uchar_t *base;		/* base for offsets into packet */
549	uchar_t *ip;		/* addr of IP header, unaligned */
550	uchar_t *tcp;		/* addr of TCP header, unaligned */
551	uchar_t *udp;		/* addr of UDP header, unaligned */
552	struct rpc_msg rpcmsg;	/* addr of RPC header */
553	struct rpc_msg *rpc;
554	int newrpc = 0;
555	uchar_t *slphdr;		/* beginning of SLP header */
556	uint_t slp_sport, slp_dport;
557	int off, header_size;
558	uchar_t *offstack[MAXSS];	/* offset stack */
559	uchar_t **offp;		/* current offset */
560	uchar_t *opkt = NULL;
561	uint_t olen;
562
563	sp = stack;
564	*sp = 1;
565	base = pkt;
566	offp = offstack;
567
568	header_size = (*interface->header_len)((char *)pkt, len);
569
570	for (op = oplist; *op; op++) {
571		switch ((enum optype) *op) {
572		case OP_LOAD_OCTET:
573			if ((base + *sp) > (pkt + len))
574				return (0); /* packet too short */
575
576			*sp = *((uchar_t *)(base + *sp));
577			break;
578		case OP_LOAD_SHORT:
579			off = *sp;
580
581			if ((base + off + sizeof (uint16_t) - 1) > (pkt + len))
582				return (0); /* packet too short */
583
584			*sp = ntohs(get_u16((uchar_t *)(base + off)));
585			break;
586		case OP_LOAD_LONG:
587			off = *sp;
588
589			if ((base + off + sizeof (uint32_t) - 1) > (pkt + len))
590				return (0); /* packet too short */
591
592			/*
593			 * Handle 3 possible alignments
594			 */
595			switch ((((unsigned)base) + off) % sizeof (uint_t)) {
596			case 0:
597				*sp = *(uint_t *)(base + off);
598				break;
599
600			case 2:
601				*((ushort_t *)(sp)) =
602				    *((ushort_t *)(base + off));
603				*(((ushort_t *)sp) + 1) =
604				    *((ushort_t *)(base + off) + 1);
605				break;
606
607			case 1:
608			case 3:
609				*((uchar_t *)(sp)) =
610				    *((uchar_t *)(base + off));
611				*(((uchar_t *)sp) + 1) =
612				    *((uchar_t *)(base + off) + 1);
613				*(((uchar_t *)sp) + 2) =
614				    *((uchar_t *)(base + off) + 2);
615				*(((uchar_t *)sp) + 3) =
616				    *((uchar_t *)(base + off) + 3);
617				break;
618			}
619			*sp = ntohl(*sp);
620			break;
621		case OP_LOAD_CONST:
622			if (sp >= &stack[MAXSS])
623				return (0);
624			*(++sp) = *(++op);
625			break;
626		case OP_LOAD_LENGTH:
627			if (sp >= &stack[MAXSS])
628				return (0);
629			*(++sp) = origlen;
630			break;
631		case OP_EQ:
632			if (sp < &stack[1])
633				return (0);
634			sp--;
635			*sp = *sp == *(sp + 1);
636			break;
637		case OP_NE:
638			if (sp < &stack[1])
639				return (0);
640			sp--;
641			*sp = *sp != *(sp + 1);
642			break;
643		case OP_GT:
644			if (sp < &stack[1])
645				return (0);
646			sp--;
647			*sp = *sp > *(sp + 1);
648			break;
649		case OP_GE:
650			if (sp < &stack[1])
651				return (0);
652			sp--;
653			*sp = *sp >= *(sp + 1);
654			break;
655		case OP_LT:
656			if (sp < &stack[1])
657				return (0);
658			sp--;
659			*sp = *sp < *(sp + 1);
660			break;
661		case OP_LE:
662			if (sp < &stack[1])
663				return (0);
664			sp--;
665			*sp = *sp <= *(sp + 1);
666			break;
667		case OP_AND:
668			if (sp < &stack[1])
669				return (0);
670			sp--;
671			*sp &= *(sp + 1);
672			break;
673		case OP_OR:
674			if (sp < &stack[1])
675				return (0);
676			sp--;
677			*sp |= *(sp + 1);
678			break;
679		case OP_XOR:
680			if (sp < &stack[1])
681				return (0);
682			sp--;
683			*sp ^= *(sp + 1);
684			break;
685		case OP_NOT:
686			*sp = !*sp;
687			break;
688		case OP_BRFL:
689			op++;
690			if (!*sp)
691				op = &oplist[*op] - 1;
692			break;
693		case OP_BRTR:
694			op++;
695			if (*sp)
696				op = &oplist[*op] - 1;
697			break;
698		case OP_ADD:
699			if (sp < &stack[1])
700				return (0);
701			sp--;
702			*sp += *(sp + 1);
703			break;
704		case OP_SUB:
705			if (sp < &stack[1])
706				return (0);
707			sp--;
708			*sp -= *(sp + 1);
709			break;
710		case OP_MUL:
711			if (sp < &stack[1])
712				return (0);
713			sp--;
714			*sp *= *(sp + 1);
715			break;
716		case OP_DIV:
717			if (sp < &stack[1])
718				return (0);
719			sp--;
720			*sp /= *(sp + 1);
721			break;
722		case OP_REM:
723			if (sp < &stack[1])
724				return (0);
725			sp--;
726			*sp %= *(sp + 1);
727			break;
728		case OP_OFFSET_POP:
729			if (offp < &offstack[0])
730				return (0);
731			base = *offp--;
732			if (opkt != NULL) {
733				pkt = opkt;
734				len = olen;
735				opkt = NULL;
736			}
737			break;
738		case OP_OFFSET_ZERO:
739			if (offp >= &offstack[MAXSS])
740				return (0);
741			*++offp = base;
742			base = pkt;
743			break;
744		case OP_OFFSET_LINK:
745			if (offp >= &offstack[MAXSS])
746				return (0);
747			*++offp = base;
748			base = pkt + header_size;
749			/*
750			 * If the offset exceeds the packet length,
751			 * we should not be interested in this packet...
752			 * Just return 0.
753			 */
754			if (base > pkt + len) {
755				return (0);
756			}
757			break;
758		case OP_OFFSET_IP:
759			if (offp >= &offstack[MAXSS])
760				return (0);
761			*++offp = base;
762			ip = pkt + header_size;
763			base = ip + ip_hdr_len(ip);
764			if (base == ip) {
765				return (0);			/* not IP */
766			}
767			if (base > pkt + len) {
768				return (0);			/* bad pkt */
769			}
770			break;
771		case OP_OFFSET_TCP:
772			if (offp >= &offstack[MAXSS])
773				return (0);
774			*++offp = base;
775			ip = pkt + header_size;
776			tcp = ip + ip_hdr_len(ip);
777			if (tcp == ip) {
778				return (0);			    /* not IP */
779			}
780			base = tcp + TCP_HDR_LEN(tcp);
781			if (base > pkt + len) {
782				return (0);
783			}
784			break;
785		case OP_OFFSET_UDP:
786			if (offp >= &offstack[MAXSS])
787				return (0);
788			*++offp = base;
789			ip = pkt + header_size;
790			udp = ip + ip_hdr_len(ip);
791			if (udp == ip) {
792				return (0);			    /* not IP */
793			}
794			base = udp + sizeof (struct udphdr);
795			if (base > pkt + len) {
796				return (0);
797			}
798			break;
799		case OP_OFFSET_RPC:
800			if (offp >= &offstack[MAXSS])
801				return (0);
802			*++offp = base;
803			ip = pkt + header_size;
804			rpc = NULL;
805
806			if (IP_VERS(ip) != IPV4_VERSION &&
807			    IP_VERS(ip) != IPV6_VERSION) {
808				if (sp >= &stack[MAXSS])
809					return (0);
810				*(++sp) = 0;
811				break;
812			}
813
814			switch (ip_proto_of(ip)) {
815			case IPPROTO_UDP:
816				udp = ip + ip_hdr_len(ip);
817				rpc = (struct rpc_msg *)(udp +
818				    sizeof (struct udphdr));
819				break;
820			case IPPROTO_TCP:
821				tcp = ip + ip_hdr_len(ip);
822				/*
823				 * Need to skip an extra 4 for the xdr_rec
824				 * field.
825				 */
826				rpc = (struct rpc_msg *)(tcp +
827				    TCP_HDR_LEN(tcp) + 4);
828				break;
829			}
830			/*
831			 * We need to have at least 24 bytes of a RPC
832			 * packet to look at to determine the validity
833			 * of it.
834			 */
835			if (rpc == NULL || (uchar_t *)rpc + 24 > pkt + len) {
836				if (sp >= &stack[MAXSS])
837					return (0);
838				*(++sp) = 0;
839				break;
840			}
841			/* align */
842			(void) memcpy(&rpcmsg, rpc, 24);
843			if (!valid_rpc((char *)&rpcmsg, 24)) {
844				if (sp >= &stack[MAXSS])
845					return (0);
846				*(++sp) = 0;
847				break;
848			}
849			if (ntohl(rpcmsg.rm_direction) == CALL) {
850				base = (uchar_t *)rpc;
851				newrpc = 1;
852				if (sp >= &stack[MAXSS])
853					return (0);
854				*(++sp) = 1;
855			} else {
856				opkt = pkt;
857				olen = len;
858
859				pkt = base = (uchar_t *)find_rpc(&rpcmsg);
860				len = sizeof (struct xid_entry);
861				if (sp >= &stack[MAXSS])
862					return (0);
863				*(++sp) = base != NULL;
864			}
865			break;
866		case OP_OFFSET_SLP:
867			slphdr = NULL;
868			ip = pkt + header_size;
869
870			if (IP_VERS(ip) != IPV4_VERSION &&
871			    IP_VERS(ip) != IPV6_VERSION) {
872				if (sp >= &stack[MAXSS])
873					return (0);
874				*(++sp) = 0;
875				break;
876			}
877
878			switch (ip_proto_of(ip)) {
879				struct udphdr udp_h;
880				struct tcphdr tcp_h;
881			case IPPROTO_UDP:
882				udp = ip + ip_hdr_len(ip);
883				/* align */
884				memcpy(&udp_h, udp, sizeof (udp_h));
885				slp_sport = ntohs(udp_h.uh_sport);
886				slp_dport = ntohs(udp_h.uh_dport);
887				slphdr = udp + sizeof (struct udphdr);
888				break;
889			case IPPROTO_TCP:
890				tcp = ip + ip_hdr_len(ip);
891				/* align */
892				memcpy(&tcp_h, tcp, sizeof (tcp_h));
893				slp_sport = ntohs(tcp_h.th_sport);
894				slp_dport = ntohs(tcp_h.th_dport);
895				slphdr = tcp + TCP_HDR_LEN(tcp);
896				break;
897			}
898			if (slphdr == NULL || slphdr > pkt + len) {
899				if (sp >= &stack[MAXSS])
900					return (0);
901				*(++sp) = 0;
902				break;
903			}
904			if (slp_sport == 427 || slp_dport == 427) {
905				if (sp >= &stack[MAXSS])
906					return (0);
907				*(++sp) = 1;
908				if (slp_sport != 427 && slp_dport == 427)
909					stash_slp(slp_sport);
910				break;
911			} else if (find_slp(slp_dport) != -1) {
912				if (valid_slp(slphdr, len)) {
913					if (sp >= &stack[MAXSS])
914						return (0);
915					*(++sp) = 1;
916					break;
917				}
918				/* else fallthrough to reject */
919			}
920			if (sp >= &stack[MAXSS])
921				return (0);
922			*(++sp) = 0;
923			break;
924		case OP_OFFSET_ETHERTYPE:
925			/*
926			 * Set base to the location of the ethertype as
927			 * appropriate for this link type.  Note that it's
928			 * not called "ethertype" for every link type, but
929			 * we need to call it something.
930			 */
931			if (offp >= &offstack[MAXSS])
932				return (0);
933			*++offp = base;
934			base = pkt + interface->network_type_offset;
935
936			/*
937			 * Below, we adjust the offset for unusual
938			 * link-layer headers that may have the protocol
939			 * type in a variable location beyond what was set
940			 * above.
941			 */
942			switch (interface->mac_type) {
943			case DL_ETHER:
944			case DL_CSMACD:
945				/*
946				 * If this is a VLAN-tagged packet, we need
947				 * to point to the ethertype field in the
948				 * VLAN header.  Move past the ethertype
949				 * field in the ethernet header.
950				 */
951				if (ntohs(get_u16(base)) == ETHERTYPE_VLAN)
952					base += (ENCAP_ETHERTYPE_OFF);
953				break;
954			}
955			if (base > pkt + len) {
956				/* Went too far, drop the packet */
957				return (0);
958			}
959			break;
960		}
961	}
962
963	if (*sp && newrpc)
964		stash_rpc(&rpcmsg);
965
966	return (*sp);
967}
968
969static void
970load_const(uint_t constval)
971{
972	emitop(OP_LOAD_CONST);
973	emitval(constval);
974}
975
976static void
977load_value(int offset, int len)
978{
979	if (offset >= 0)
980		load_const(offset);
981
982	switch (len) {
983		case 1:
984			emitop(OP_LOAD_OCTET);
985			break;
986		case 2:
987			emitop(OP_LOAD_SHORT);
988			break;
989		case 4:
990			emitop(OP_LOAD_LONG);
991			break;
992	}
993}
994
995/*
996 * Emit code to compare a field in
997 * the packet against a constant value.
998 */
999static void
1000compare_value(uint_t offset, uint_t len, uint_t val)
1001{
1002	load_const(val);
1003	load_value(offset, len);
1004	emitop(OP_EQ);
1005}
1006
1007static void
1008compare_addr_v4(uint_t offset, uint_t len, uint_t val)
1009{
1010	load_const(ntohl(val));
1011	load_value(offset, len);
1012	emitop(OP_EQ);
1013}
1014
1015static void
1016compare_addr_v6(uint_t offset, uint_t len, struct in6_addr val)
1017{
1018	int i;
1019	uint32_t value;
1020
1021	for (i = 0; i < len; i += 4) {
1022		value = ntohl(*(uint32_t *)&val.s6_addr[i]);
1023		load_const(value);
1024		load_value(offset + i, 4);
1025		emitop(OP_EQ);
1026		if (i != 0)
1027			emitop(OP_AND);
1028	}
1029}
1030
1031/*
1032 * Same as above except do the comparison
1033 * after and'ing a mask value.  Useful
1034 * for comparing IP network numbers
1035 */
1036static void
1037compare_value_mask(uint_t offset, uint_t len, uint_t val, int mask)
1038{
1039	load_value(offset, len);
1040	load_const(mask);
1041	emitop(OP_AND);
1042	load_const(val);
1043	emitop(OP_EQ);
1044}
1045
1046/*
1047 * Compare two zoneid's. The arg val passed in is stored in network
1048 * byte order.
1049 */
1050static void
1051compare_value_zone(uint_t offset, uint32_t val)
1052{
1053	load_const(ntohl(val));
1054	load_value(offset, 4);
1055	emitop(OP_EQ);
1056}
1057
1058/* Emit an operator into the code array */
1059static void
1060emitop(enum optype opcode)
1061{
1062	if (curr_op >= &oplist[MAXOPS])
1063		pr_err("expression too long");
1064	*curr_op++ = opcode;
1065}
1066
1067/*
1068 * Remove n operators recently emitted into
1069 * the code array.  Used by alternation().
1070 */
1071static void
1072unemit(int numops)
1073{
1074	curr_op -= numops;
1075}
1076
1077
1078/*
1079 * Same as emitop except that we're emitting
1080 * a value that's not an operator.
1081 */
1082static void
1083emitval(uint_t val)
1084{
1085	if (curr_op >= &oplist[MAXOPS])
1086		pr_err("expression too long");
1087	*curr_op++ = val;
1088}
1089
1090/*
1091 * Used to chain forward branches together
1092 * for later resolution by resolve_chain().
1093 */
1094static uint_t
1095chain(int p)
1096{
1097	uint_t pos = curr_op - oplist;
1098
1099	emitval(p);
1100	return (pos);
1101}
1102
1103/*
1104 * Proceed backward through the code array
1105 * following a chain of forward references.
1106 * At each reference install the destination
1107 * branch offset.
1108 */
1109static void
1110resolve_chain(uint_t p)
1111{
1112	uint_t n;
1113	uint_t pos = curr_op - oplist;
1114
1115	while (p) {
1116		n = oplist[p];
1117		oplist[p] = pos;
1118		p = n;
1119	}
1120}
1121
1122#define	EQ(val) (strcmp(token, val) == 0)
1123
1124char *tkp, *sav_tkp;
1125char *token;
1126enum { EOL, ALPHA, NUMBER, FIELD, ADDR_IP, ADDR_ETHER, SPECIAL,
1127	ADDR_IP6, ADDR_AT } tokentype;
1128uint_t tokenval;
1129
1130/*
1131 * This is the scanner.  Each call returns the next
1132 * token in the filter expression.  A token is either:
1133 * EOL:		The end of the line - no more tokens.
1134 * ALPHA:	A name that begins with a letter and contains
1135 *		letters or digits, hyphens or underscores.
1136 * NUMBER:	A number.  The value can be represented as
1137 * 		a decimal value (1234) or an octal value
1138 *		that begins with zero (066) or a hex value
1139 *		that begins with 0x or 0X (0xff).
1140 * FIELD:	A name followed by a left square bracket.
1141 * ADDR_IP:	An IP address.  Any sequence of digits
1142 *		separated by dots e.g. 109.104.40.13
1143 * ADDR_ETHER:	An ethernet address.  Any sequence of hex
1144 *		digits separated by colons e.g. 8:0:20:0:76:39
1145 * SPECIAL:	A special character e.g. ">" or "(".  The scanner
1146 *		correctly handles digraphs - two special characters
1147 *		that constitute a single token e.g. "==" or ">=".
1148 * ADDR_IP6:    An IPv6 address.
1149 *
1150 * ADDR_AT:	An AppleTalk Phase II address. A sequence of two numbers
1151 *		separated by a dot.
1152 *
1153 * The current token is maintained in "token" and and its
1154 * type in "tokentype".  If tokentype is NUMBER then the
1155 * value is held in "tokenval".
1156 */
1157
1158static const char *namechars =
1159	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.";
1160static const char *numchars = "0123456789abcdefABCDEFXx:.";
1161
1162void
1163next()
1164{
1165	static int savechar;
1166	char *p;
1167	int size, size1;
1168	int base, colons, dots, alphas, double_colon;
1169
1170	colons = 0;
1171	double_colon = 0;
1172
1173	if (*tkp == '\0') {
1174		token = tkp;
1175		*tkp = savechar;
1176	}
1177
1178	sav_tkp = tkp;
1179
1180	while (isspace(*tkp)) tkp++;
1181	token = tkp;
1182	if (*token == '\0') {
1183		tokentype = EOL;
1184		return;
1185	}
1186
1187	/* A token containing ':' cannot be ALPHA type */
1188	tkp = token + strspn(token, numchars);
1189	for (p = token; p < tkp; p++) {
1190		if (*p == ':') {
1191			colons++;
1192			if (*(p+1) == ':')
1193				double_colon++;
1194		}
1195	}
1196
1197	tkp = token;
1198	if (isalpha(*tkp) && !colons) {
1199		tokentype = ALPHA;
1200		tkp += strspn(tkp, namechars);
1201		if (*tkp == '[') {
1202			tokentype = FIELD;
1203			*tkp++ = '\0';
1204		}
1205	} else
1206
1207	/*
1208	 * RFC1123 states that host names may now start with digits. Need
1209	 * to change parser to account for this. Also, need to distinguish
1210	 * between 1.2.3.4 and 1.2.3.a where the first case is an IP address
1211	 * and the second is a domain name. 333aaa needs to be distinguished
1212	 * from 0x333aaa. The first is a host name and the second is a number.
1213	 *
1214	 * The (colons > 1) conditional differentiates between ethernet
1215	 * and IPv6 addresses, and an expression of the form base[expr:size],
1216	 * which can only contain one ':' character.
1217	 */
1218	if (isdigit(*tkp) || colons > 1) {
1219		tkp = token + strspn(token, numchars);
1220		dots = alphas = 0;
1221		for (p = token; p < tkp; p++) {
1222			if (*p == '.')
1223				dots++;
1224			else if (isalpha(*p))
1225				alphas = 1;
1226		}
1227		if (colons > 1) {
1228			if (colons == 5 && double_colon == 0) {
1229				tokentype = ADDR_ETHER;
1230			} else {
1231				tokentype = ADDR_IP6;
1232			}
1233		} else if (dots) {
1234			size = tkp - token;
1235			size1 = strspn(token, "0123456789.");
1236			if (dots == 1 && size == size1) {
1237				tokentype = ADDR_AT;
1238			} else
1239				if (dots != 3 || size != size1) {
1240					tokentype = ALPHA;
1241					if (*tkp != '\0' && !isspace(*tkp)) {
1242						tkp += strspn(tkp, namechars);
1243						if (*tkp == '[') {
1244							tokentype = FIELD;
1245							*tkp++ = '\0';
1246						}
1247					}
1248				} else
1249					tokentype = ADDR_IP;
1250		} else if (token + strspn(token, namechars) <= tkp) {
1251			/*
1252			 * With the above check, if there are more
1253			 * characters after the last digit, assume
1254			 * that it is not a number.
1255			 */
1256			tokentype = NUMBER;
1257			p = tkp;
1258			tkp = token;
1259			base = 10;
1260			if (*tkp == '0') {
1261				base = 8;
1262				tkp++;
1263				if (*tkp == 'x' || *tkp == 'X')
1264					base = 16;
1265			}
1266			if ((base == 10 || base == 8) && alphas) {
1267				tokentype = ALPHA;
1268				tkp = p;
1269			} else if (base == 16) {
1270				size = 2 + strspn(token+2,
1271				    "0123456789abcdefABCDEF");
1272				size1 = p - token;
1273				if (size != size1) {
1274					tokentype = ALPHA;
1275					tkp = p;
1276				} else
1277				/*
1278				 * handles the case of 0x so an error message
1279				 * is not printed. Treats 0x as 0.
1280				 */
1281				if (size == 2) {
1282					tokenval = 0;
1283					tkp = token +2;
1284				} else {
1285					tokenval = strtoul(token, &tkp, base);
1286				}
1287			} else {
1288				tokenval = strtoul(token, &tkp, base);
1289			}
1290		} else {
1291			tokentype = ALPHA;
1292			tkp += strspn(tkp, namechars);
1293			if (*tkp == '[') {
1294				tokentype = FIELD;
1295				*tkp++ = '\0';
1296			}
1297		}
1298	} else {
1299		tokentype = SPECIAL;
1300		tkp++;
1301		if ((*token == '=' && *tkp == '=') ||
1302		    (*token == '>' && *tkp == '=') ||
1303		    (*token == '<' && *tkp == '=') ||
1304		    (*token == '!' && *tkp == '='))
1305				tkp++;
1306	}
1307
1308	savechar = *tkp;
1309	*tkp = '\0';
1310}
1311
1312typedef struct match_type {
1313	char		*m_name;
1314	int		m_offset;
1315	int		m_size;
1316	int		m_value;
1317	int		m_depend;
1318	enum optype	m_optype;
1319} match_type_t;
1320
1321static match_type_t ether_match_types[] = {
1322	/*
1323	 * Table initialized assuming Ethernet data link headers.
1324	 * m_offset is an offset beyond the offset op, which is why
1325	 * the offset is zero for when snoop needs to check an ethertype.
1326	 */
1327	"ip",		0,  2, ETHERTYPE_IP,	 -1,	OP_OFFSET_ETHERTYPE,
1328	"ip6",		0,  2, ETHERTYPE_IPV6,	 -1,	OP_OFFSET_ETHERTYPE,
1329	"arp",		0,  2, ETHERTYPE_ARP,	 -1,	OP_OFFSET_ETHERTYPE,
1330	"rarp",		0,  2, ETHERTYPE_REVARP, -1,	OP_OFFSET_ETHERTYPE,
1331	"pppoed",	0,  2, ETHERTYPE_PPPOED, -1,	OP_OFFSET_ETHERTYPE,
1332	"pppoes",	0,  2, ETHERTYPE_PPPOES, -1,	OP_OFFSET_ETHERTYPE,
1333	"tcp",		9,  1, IPPROTO_TCP,	 0,	OP_OFFSET_LINK,
1334	"tcp",		6,  1, IPPROTO_TCP,	 1,	OP_OFFSET_LINK,
1335	"udp",		9,  1, IPPROTO_UDP,	 0,	OP_OFFSET_LINK,
1336	"udp",		6,  1, IPPROTO_UDP,	 1,	OP_OFFSET_LINK,
1337	"icmp",		9,  1, IPPROTO_ICMP,	 0,	OP_OFFSET_LINK,
1338	"icmp6",	6,  1, IPPROTO_ICMPV6,	 1,	OP_OFFSET_LINK,
1339	"ospf",		9,  1, IPPROTO_OSPF,	 0,	OP_OFFSET_LINK,
1340	"ospf",		6,  1, IPPROTO_OSPF,	 1,	OP_OFFSET_LINK,
1341	"ip-in-ip",	9,  1, IPPROTO_ENCAP,	 0,	OP_OFFSET_LINK,
1342	"esp",		9,  1, IPPROTO_ESP,	 0,	OP_OFFSET_LINK,
1343	"esp",		6,  1, IPPROTO_ESP,	 1,	OP_OFFSET_LINK,
1344	"ah",		9,  1, IPPROTO_AH,	 0,	OP_OFFSET_LINK,
1345	"ah",		6,  1, IPPROTO_AH,	 1,	OP_OFFSET_LINK,
1346	"sctp",		9,  1, IPPROTO_SCTP,	 0,	OP_OFFSET_LINK,
1347	"sctp",		6,  1, IPPROTO_SCTP,	 1,	OP_OFFSET_LINK,
1348	0,		0,  0, 0,		 0,	0
1349};
1350
1351static match_type_t ipnet_match_types[] = {
1352	/*
1353	 * Table initialized assuming Ethernet data link headers.
1354	 * m_offset is an offset beyond the offset op, which is why
1355	 * the offset is zero for when snoop needs to check an ethertype.
1356	 */
1357	"ip",		0,  1, IPV4_VERSION,    -1,	OP_OFFSET_ETHERTYPE,
1358	"ip6",		0,  1, IPV6_VERSION,    -1,	OP_OFFSET_ETHERTYPE,
1359	"tcp",		9,  1, IPPROTO_TCP,	 0,	OP_OFFSET_LINK,
1360	"tcp",		6,  1, IPPROTO_TCP,	 1,	OP_OFFSET_LINK,
1361	"udp",		9,  1, IPPROTO_UDP,	 0,	OP_OFFSET_LINK,
1362	"udp",		6,  1, IPPROTO_UDP,	 1,	OP_OFFSET_LINK,
1363	"icmp",		9,  1, IPPROTO_ICMP,	 0,	OP_OFFSET_LINK,
1364	"icmp6",	6,  1, IPPROTO_ICMPV6,	 1,	OP_OFFSET_LINK,
1365	"ospf",		9,  1, IPPROTO_OSPF,	 0,	OP_OFFSET_LINK,
1366	"ospf",		6,  1, IPPROTO_OSPF,	 1,	OP_OFFSET_LINK,
1367	"ip-in-ip",	9,  1, IPPROTO_ENCAP,	 0,	OP_OFFSET_LINK,
1368	"esp",		9,  1, IPPROTO_ESP,	 0,	OP_OFFSET_LINK,
1369	"esp",		6,  1, IPPROTO_ESP,	 1,	OP_OFFSET_LINK,
1370	"ah",		9,  1, IPPROTO_AH,	 0,	OP_OFFSET_LINK,
1371	"ah",		6,  1, IPPROTO_AH,	 1,	OP_OFFSET_LINK,
1372	"sctp",		9,  1, IPPROTO_SCTP,	 0,	OP_OFFSET_LINK,
1373	"sctp",		6,  1, IPPROTO_SCTP,	 1,	OP_OFFSET_LINK,
1374	0,		0,  0, 0,		 0,	0
1375};
1376
1377static match_type_t iptun_match_types[] = {
1378	"ip",		0,  1, IPPROTO_ENCAP,	-1,	OP_OFFSET_ETHERTYPE,
1379	"ip6",		0,  1, IPPROTO_IPV6,	-1,	OP_OFFSET_ETHERTYPE,
1380	"tcp",		9,  1, IPPROTO_TCP,	0,	OP_OFFSET_LINK,
1381	"tcp",		6,  1, IPPROTO_TCP,	1,	OP_OFFSET_LINK,
1382	"udp",		9,  1, IPPROTO_UDP,	0,	OP_OFFSET_LINK,
1383	"udp",		6,  1, IPPROTO_UDP,	1,	OP_OFFSET_LINK,
1384	"icmp",		9,  1, IPPROTO_ICMP,	0,	OP_OFFSET_LINK,
1385	"icmp6",	6,  1, IPPROTO_ICMPV6,	1,	OP_OFFSET_LINK,
1386	"ospf",		9,  1, IPPROTO_OSPF,	0,	OP_OFFSET_LINK,
1387	"ospf",		6,  1, IPPROTO_OSPF,	1,	OP_OFFSET_LINK,
1388	"ip-in-ip",	9,  1, IPPROTO_ENCAP,	0,	OP_OFFSET_LINK,
1389	"esp",		9,  1, IPPROTO_ESP,	0,	OP_OFFSET_LINK,
1390	"esp",		6,  1, IPPROTO_ESP,	1,	OP_OFFSET_LINK,
1391	"ah",		9,  1, IPPROTO_AH,	0,	OP_OFFSET_LINK,
1392	"ah",		6,  1, IPPROTO_AH,	1,	OP_OFFSET_LINK,
1393	"sctp",		9,  1, IPPROTO_SCTP,	0,	OP_OFFSET_LINK,
1394	"sctp",		6,  1, IPPROTO_SCTP,	1,	OP_OFFSET_LINK,
1395	0,		0,  0, 0,		0,	0
1396};
1397
1398static void
1399generate_check(match_type_t match_types[], int index, int type)
1400{
1401	match_type_t *mtp = &match_types[index];
1402	/*
1403	 * Note: this code assumes the above dependencies are
1404	 * not cyclic.  This *should* always be true.
1405	 */
1406	if (mtp->m_depend != -1)
1407		generate_check(match_types, mtp->m_depend, type);
1408
1409	emitop(mtp->m_optype);
1410	load_value(mtp->m_offset, mtp->m_size);
1411	load_const(mtp->m_value);
1412	emitop(OP_OFFSET_POP);
1413
1414	emitop(OP_EQ);
1415
1416	if (mtp->m_depend != -1)
1417		emitop(OP_AND);
1418}
1419
1420/*
1421 * Generate code based on the keyword argument.
1422 * This word is looked up in the match_types table
1423 * and checks a field within the packet for a given
1424 * value e.g. ether or ip type field.  The match
1425 * can also have a dependency on another entry e.g.
1426 * "tcp" requires that the packet also be "ip".
1427 */
1428static int
1429comparison(char *s)
1430{
1431	unsigned int	i, n_checks = 0;
1432	match_type_t	*match_types;
1433
1434	switch (interface->mac_type) {
1435	case DL_ETHER:
1436		match_types = ether_match_types;
1437		break;
1438	case DL_IPNET:
1439		match_types = ipnet_match_types;
1440		break;
1441	case DL_IPV4:
1442	case DL_IPV6:
1443	case DL_6TO4:
1444		match_types = iptun_match_types;
1445		break;
1446	default:
1447		return (0);
1448	}
1449
1450	for (i = 0; match_types[i].m_name != NULL; i++) {
1451		if (strcmp(s, match_types[i].m_name) != 0)
1452			continue;
1453
1454		n_checks++;
1455		generate_check(match_types, i, interface->mac_type);
1456		if (n_checks > 1)
1457			emitop(OP_OR);
1458	}
1459
1460	return (n_checks > 0);
1461}
1462
1463enum direction { ANY, TO, FROM };
1464enum direction dir;
1465
1466/*
1467 * Generate code to match an IP address.  The address
1468 * may be supplied either as a hostname or in dotted format.
1469 * For source packets both the IP source address and ARP
1470 * src are checked.
1471 * Note: we don't check packet type here - whether IP or ARP.
1472 * It's possible that we'll do an improper match.
1473 */
1474static void
1475ipaddr_match(enum direction which, char *hostname, int inet_type)
1476{
1477	bool_t found_host;
1478	int m = 0, n = 0;
1479	uint_t *addr4ptr;
1480	uint_t addr4;
1481	struct in6_addr *addr6ptr;
1482	int h_addr_index;
1483	struct hostent *hp = NULL;
1484	int error_num = 0;
1485	boolean_t freehp = B_FALSE;
1486	boolean_t first = B_TRUE;
1487
1488	/*
1489	 * The addr4offset and addr6offset variables simplify the code which
1490	 * generates the address comparison filter.  With these two variables,
1491	 * duplicate code need not exist for the TO and FROM case.
1492	 * A value of -1 describes the ANY case (TO and FROM).
1493	 */
1494	int addr4offset;
1495	int addr6offset;
1496
1497	found_host = 0;
1498
1499	if (tokentype == ADDR_IP) {
1500		hp = lgetipnodebyname(hostname, AF_INET, 0, &error_num);
1501		if (hp == NULL) {
1502			hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
1503			freehp = 1;
1504		}
1505		if (hp == NULL) {
1506			if (error_num == TRY_AGAIN) {
1507				pr_err("couldn't resolve %s (try again later)",
1508				    hostname);
1509			} else {
1510				pr_err("couldn't resolve %s", hostname);
1511			}
1512		}
1513		inet_type = IPV4_ONLY;
1514	} else if (tokentype == ADDR_IP6) {
1515		hp = lgetipnodebyname(hostname, AF_INET6, 0, &error_num);
1516		if (hp == NULL) {
1517			hp = getipnodebyname(hostname, AF_INET6, 0, &error_num);
1518			freehp = 1;
1519		}
1520		if (hp == NULL) {
1521			if (error_num == TRY_AGAIN) {
1522				pr_err("couldn't resolve %s (try again later)",
1523				    hostname);
1524			} else {
1525				pr_err("couldn't resolve %s", hostname);
1526			}
1527		}
1528		inet_type = IPV6_ONLY;
1529	} else {
1530		/* Some hostname i.e. tokentype is ALPHA */
1531		switch (inet_type) {
1532		case IPV4_ONLY:
1533			/* Only IPv4 address is needed */
1534			hp = lgetipnodebyname(hostname, AF_INET, 0, &error_num);
1535			if (hp == NULL) {
1536				hp = getipnodebyname(hostname, AF_INET,	0,
1537				    &error_num);
1538				freehp = 1;
1539			}
1540			if (hp != NULL) {
1541				found_host = 1;
1542			}
1543			break;
1544		case IPV6_ONLY:
1545			/* Only IPv6 address is needed */
1546			hp = lgetipnodebyname(hostname, AF_INET6, 0,
1547			    &error_num);
1548			if (hp == NULL) {
1549				hp = getipnodebyname(hostname, AF_INET6, 0,
1550				    &error_num);
1551				freehp = 1;
1552			}
1553			if (hp != NULL) {
1554				found_host = 1;
1555			}
1556			break;
1557		case IPV4_AND_IPV6:
1558			/* Both IPv4 and IPv6 are needed */
1559			hp = lgetipnodebyname(hostname, AF_INET6,
1560			    AI_ALL | AI_V4MAPPED, &error_num);
1561			if (hp == NULL) {
1562				hp = getipnodebyname(hostname, AF_INET6,
1563				    AI_ALL | AI_V4MAPPED, &error_num);
1564				freehp = 1;
1565			}
1566			if (hp != NULL) {
1567				found_host = 1;
1568			}
1569			break;
1570		default:
1571			found_host = 0;
1572		}
1573
1574		if (!found_host) {
1575			if (error_num == TRY_AGAIN) {
1576				pr_err("could not resolve %s (try again later)",
1577				    hostname);
1578			} else {
1579				pr_err("could not resolve %s", hostname);
1580			}
1581		}
1582	}
1583
1584	if (hp == NULL)
1585		return;
1586
1587	switch (which) {
1588	case TO:
1589		addr4offset = IPV4_DSTADDR_OFFSET;
1590		addr6offset = IPV6_DSTADDR_OFFSET;
1591		break;
1592	case FROM:
1593		addr4offset = IPV4_SRCADDR_OFFSET;
1594		addr6offset = IPV6_SRCADDR_OFFSET;
1595		break;
1596	case ANY:
1597		addr4offset = -1;
1598		addr6offset = -1;
1599		break;
1600	}
1601
1602	/*
1603	 * The code below generates the filter.
1604	 */
1605	if (hp->h_addrtype == AF_INET) {
1606		ethertype_match(interface->network_type_ip);
1607		emitop(OP_BRFL);
1608		n = chain(n);
1609		emitop(OP_OFFSET_LINK);
1610		h_addr_index = 0;
1611		addr4ptr = (uint_t *)hp->h_addr_list[h_addr_index];
1612		while (addr4ptr != NULL) {
1613			if (addr4offset == -1) {
1614				compare_addr_v4(IPV4_SRCADDR_OFFSET, 4,
1615				    *addr4ptr);
1616				emitop(OP_BRTR);
1617				m = chain(m);
1618				compare_addr_v4(IPV4_DSTADDR_OFFSET, 4,
1619				    *addr4ptr);
1620			} else {
1621				compare_addr_v4(addr4offset, 4, *addr4ptr);
1622			}
1623			addr4ptr = (uint_t *)hp->h_addr_list[++h_addr_index];
1624			if (addr4ptr != NULL) {
1625				emitop(OP_BRTR);
1626				m = chain(m);
1627			}
1628		}
1629		if (m != 0) {
1630			resolve_chain(m);
1631		}
1632		emitop(OP_OFFSET_POP);
1633		resolve_chain(n);
1634	} else {
1635		/* first pass: IPv4 addresses */
1636		h_addr_index = 0;
1637		addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
1638		first = B_TRUE;
1639		while (addr6ptr != NULL) {
1640			if (IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
1641				if (first) {
1642					ethertype_match(
1643					    interface->network_type_ip);
1644					emitop(OP_BRFL);
1645					n = chain(n);
1646					emitop(OP_OFFSET_LINK);
1647					first = B_FALSE;
1648				} else {
1649					emitop(OP_BRTR);
1650					m = chain(m);
1651				}
1652				IN6_V4MAPPED_TO_INADDR(addr6ptr,
1653				    (struct in_addr *)&addr4);
1654				if (addr4offset == -1) {
1655					compare_addr_v4(IPV4_SRCADDR_OFFSET, 4,
1656					    addr4);
1657					emitop(OP_BRTR);
1658					m = chain(m);
1659					compare_addr_v4(IPV4_DSTADDR_OFFSET, 4,
1660					    addr4);
1661				} else {
1662					compare_addr_v4(addr4offset, 4, addr4);
1663				}
1664			}
1665			addr6ptr = (struct in6_addr *)
1666			    hp->h_addr_list[++h_addr_index];
1667		}
1668		/* second pass: IPv6 addresses */
1669		h_addr_index = 0;
1670		addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
1671		first = B_TRUE;
1672		while (addr6ptr != NULL) {
1673			if (!IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
1674				if (first) {
1675					/*
1676					 * bypass check for IPv6 addresses
1677					 * when we have an IPv4 packet
1678					 */
1679					if (n != 0) {
1680						emitop(OP_BRTR);
1681						m = chain(m);
1682						emitop(OP_BRFL);
1683						m = chain(m);
1684						resolve_chain(n);
1685						n = 0;
1686					}
1687					ethertype_match(
1688					    interface->network_type_ipv6);
1689					emitop(OP_BRFL);
1690					n = chain(n);
1691					emitop(OP_OFFSET_LINK);
1692					first = B_FALSE;
1693				} else {
1694					emitop(OP_BRTR);
1695					m = chain(m);
1696				}
1697				if (addr6offset == -1) {
1698					compare_addr_v6(IPV6_SRCADDR_OFFSET,
1699					    16, *addr6ptr);
1700					emitop(OP_BRTR);
1701					m = chain(m);
1702					compare_addr_v6(IPV6_DSTADDR_OFFSET,
1703					    16, *addr6ptr);
1704				} else {
1705					compare_addr_v6(addr6offset, 16,
1706					    *addr6ptr);
1707				}
1708			}
1709			addr6ptr = (struct in6_addr *)
1710			    hp->h_addr_list[++h_addr_index];
1711		}
1712		if (m != 0) {
1713			resolve_chain(m);
1714		}
1715		emitop(OP_OFFSET_POP);
1716		resolve_chain(n);
1717	}
1718
1719	/* only free struct hostent returned by getipnodebyname() */
1720	if (freehp) {
1721		freehostent(hp);
1722	}
1723}
1724
1725/*
1726 * Match on zoneid. The arg zone passed in is in network byte order.
1727 */
1728static void
1729zone_match(enum direction which, uint32_t zone)
1730{
1731
1732	switch (which) {
1733	case TO:
1734		compare_value_zone(IPNET_DSTZONE_OFFSET, zone);
1735		break;
1736	case FROM:
1737		compare_value_zone(IPNET_SRCZONE_OFFSET, zone);
1738		break;
1739	case ANY:
1740		compare_value_zone(IPNET_SRCZONE_OFFSET, zone);
1741		compare_value_zone(IPNET_DSTZONE_OFFSET, zone);
1742		emitop(OP_OR);
1743	}
1744}
1745
1746/*
1747 * Generate code to match an AppleTalk address.  The address
1748 * must be given as two numbers with a dot between
1749 *
1750 */
1751static void
1752ataddr_match(enum direction which, char *hostname)
1753{
1754	uint_t net;
1755	uint_t node;
1756	uint_t m, n;
1757
1758	sscanf(hostname, "%u.%u", &net, &node);
1759
1760	emitop(OP_OFFSET_LINK);
1761	switch (which) {
1762	case TO:
1763		compare_value(AT_DST_NET_OFFSET, 2, net);
1764		emitop(OP_BRFL);
1765		m = chain(0);
1766		compare_value(AT_DST_NODE_OFFSET, 1, node);
1767		resolve_chain(m);
1768		break;
1769	case FROM:
1770		compare_value(AT_SRC_NET_OFFSET, 2, net);
1771		emitop(OP_BRFL);
1772		m = chain(0);
1773		compare_value(AT_SRC_NODE_OFFSET, 1, node);
1774		resolve_chain(m);
1775		break;
1776	case ANY:
1777		compare_value(AT_DST_NET_OFFSET, 2, net);
1778		emitop(OP_BRFL);
1779		m = chain(0);
1780		compare_value(AT_DST_NODE_OFFSET, 1, node);
1781		resolve_chain(m);
1782		emitop(OP_BRTR);
1783		n = chain(0);
1784		compare_value(AT_SRC_NET_OFFSET, 2, net);
1785		emitop(OP_BRFL);
1786		m = chain(0);
1787		compare_value(AT_SRC_NODE_OFFSET, 1, node);
1788		resolve_chain(m);
1789		resolve_chain(n);
1790		break;
1791	}
1792	emitop(OP_OFFSET_POP);
1793}
1794
1795/*
1796 * Compare ethernet addresses. The address may
1797 * be provided either as a hostname or as a
1798 * 6 octet colon-separated address.
1799 */
1800static void
1801etheraddr_match(enum direction which, char *hostname)
1802{
1803	uint_t addr;
1804	ushort_t *addrp;
1805	int to_offset, from_offset;
1806	struct ether_addr e, *ep = NULL;
1807	int m;
1808
1809	/*
1810	 * First, check the interface type for whether src/dest address
1811	 * is determinable; if not, retreat early.
1812	 */
1813	switch (interface->mac_type) {
1814	case DL_ETHER:
1815		from_offset = ETHERADDRL;
1816		to_offset = 0;
1817		break;
1818
1819	case DL_IB:
1820		/*
1821		 * If an ethernet address is attempted to be used
1822		 * on an IPoIB interface, flag error. Link address
1823		 * based filtering is unsupported on IPoIB, so there
1824		 * is no ipibaddr_match() or parsing support for IPoIB
1825		 * 20 byte link addresses.
1826		 */
1827		pr_err("filter option unsupported on media");
1828		break;
1829
1830	case DL_FDDI:
1831		from_offset = 7;
1832		to_offset = 1;
1833		break;
1834
1835	default:
1836		/*
1837		 * Where do we find "ether" address for FDDI & TR?
1838		 * XXX can improve?  ~sparker
1839		 */
1840		load_const(1);
1841		return;
1842	}
1843
1844	if (isxdigit(*hostname))
1845		ep = ether_aton(hostname);
1846	if (ep == NULL) {
1847		if (ether_hostton(hostname, &e))
1848			if (!arp_for_ether(hostname, &e))
1849				pr_err("cannot obtain ether addr for %s",
1850				    hostname);
1851		ep = &e;
1852	}
1853	memcpy(&addr, (ushort_t *)ep, 4);
1854	addrp = (ushort_t *)ep + 2;
1855
1856	emitop(OP_OFFSET_ZERO);
1857	switch (which) {
1858	case TO:
1859		compare_value(to_offset, 4, ntohl(addr));
1860		emitop(OP_BRFL);
1861		m = chain(0);
1862		compare_value(to_offset + 4, 2, ntohs(*addrp));
1863		resolve_chain(m);
1864		break;
1865	case FROM:
1866		compare_value(from_offset, 4, ntohl(addr));
1867		emitop(OP_BRFL);
1868		m = chain(0);
1869		compare_value(from_offset + 4, 2, ntohs(*addrp));
1870		resolve_chain(m);
1871		break;
1872	case ANY:
1873		compare_value(to_offset, 4, ntohl(addr));
1874		compare_value(to_offset + 4, 2, ntohs(*addrp));
1875		emitop(OP_AND);
1876		emitop(OP_BRTR);
1877		m = chain(0);
1878
1879		compare_value(from_offset, 4, ntohl(addr));
1880		compare_value(from_offset + 4, 2, ntohs(*addrp));
1881		emitop(OP_AND);
1882		resolve_chain(m);
1883		break;
1884	}
1885	emitop(OP_OFFSET_POP);
1886}
1887
1888static void
1889ethertype_match(int val)
1890{
1891	int ether_offset = interface->network_type_offset;
1892
1893	/*
1894	 * If the user is interested in ethertype VLAN,
1895	 * then we need to set the offset to the beginning of the packet.
1896	 * But if the user is interested in another ethertype,
1897	 * such as IPv4, then we need to take into consideration
1898	 * the fact that the packet might be VLAN tagged.
1899	 */
1900	if (interface->mac_type == DL_ETHER ||
1901	    interface->mac_type == DL_CSMACD) {
1902		if (val != ETHERTYPE_VLAN) {
1903			/*
1904			 * OP_OFFSET_ETHERTYPE puts us at the ethertype
1905			 * field whether or not there is a VLAN tag,
1906			 * so ether_offset goes to zero if we get here.
1907			 */
1908			emitop(OP_OFFSET_ETHERTYPE);
1909			ether_offset = 0;
1910		} else {
1911			emitop(OP_OFFSET_ZERO);
1912		}
1913	}
1914	compare_value(ether_offset, interface->network_type_len, val);
1915	if (interface->mac_type == DL_ETHER ||
1916	    interface->mac_type == DL_CSMACD) {
1917		emitop(OP_OFFSET_POP);
1918	}
1919}
1920
1921/*
1922 * Match a network address.  The host part
1923 * is masked out.  The network address may
1924 * be supplied either as a netname or in
1925 * IP dotted format.  The mask to be used
1926 * for the comparison is assumed from the
1927 * address format (see comment below).
1928 */
1929static void
1930netaddr_match(enum direction which, char *netname)
1931{
1932	uint_t addr;
1933	uint_t mask = 0xff000000;
1934	uint_t m;
1935	struct netent *np;
1936
1937	if (isdigit(*netname)) {
1938		addr = inet_network(netname);
1939	} else {
1940		np = getnetbyname(netname);
1941		if (np == NULL)
1942			pr_err("net %s not known", netname);
1943		addr = np->n_net;
1944	}
1945
1946	/*
1947	 * Left justify the address and figure
1948	 * out a mask based on the supplied address.
1949	 * Set the mask according to the number of zero
1950	 * low-order bytes.
1951	 * Note: this works only for whole octet masks.
1952	 */
1953	if (addr) {
1954		while ((addr & ~mask) != 0) {
1955			mask |= (mask >> 8);
1956		}
1957	}
1958
1959	emitop(OP_OFFSET_LINK);
1960	switch (which) {
1961	case TO:
1962		compare_value_mask(16, 4, addr, mask);
1963		break;
1964	case FROM:
1965		compare_value_mask(12, 4, addr, mask);
1966		break;
1967	case ANY:
1968		compare_value_mask(12, 4, addr, mask);
1969		emitop(OP_BRTR);
1970		m = chain(0);
1971		compare_value_mask(16, 4, addr, mask);
1972		resolve_chain(m);
1973		break;
1974	}
1975	emitop(OP_OFFSET_POP);
1976}
1977
1978/*
1979 * Match either a UDP or TCP port number.
1980 * The port number may be provided either as
1981 * port name as listed in /etc/services ("nntp") or as
1982 * the port number itself (2049).
1983 */
1984static void
1985port_match(enum direction which, char *portname)
1986{
1987	struct servent *sp;
1988	uint_t m, port;
1989
1990	if (isdigit(*portname)) {
1991		port = atoi(portname);
1992	} else {
1993		sp = getservbyname(portname, NULL);
1994		if (sp == NULL)
1995			pr_err("invalid port number or name: %s", portname);
1996		port = ntohs(sp->s_port);
1997	}
1998
1999	emitop(OP_OFFSET_IP);
2000
2001	switch (which) {
2002	case TO:
2003		compare_value(2, 2, port);
2004		break;
2005	case FROM:
2006		compare_value(0, 2, port);
2007		break;
2008	case ANY:
2009		compare_value(2, 2, port);
2010		emitop(OP_BRTR);
2011		m = chain(0);
2012		compare_value(0, 2, port);
2013		resolve_chain(m);
2014		break;
2015	}
2016	emitop(OP_OFFSET_POP);
2017}
2018
2019/*
2020 * Generate code to match packets with a specific
2021 * RPC program number.  If the progname is a name
2022 * it is converted to a number via /etc/rpc.
2023 * The program version and/or procedure may be provided
2024 * as extra qualifiers.
2025 */
2026static void
2027rpc_match_prog(enum direction which, char *progname, int vers, int proc)
2028{
2029	struct rpcent *rpc;
2030	uint_t prog;
2031	uint_t m, n;
2032
2033	if (isdigit(*progname)) {
2034		prog = atoi(progname);
2035	} else {
2036		rpc = (struct rpcent *)getrpcbyname(progname);
2037		if (rpc == NULL)
2038			pr_err("invalid program name: %s", progname);
2039		prog = rpc->r_number;
2040	}
2041
2042	emitop(OP_OFFSET_RPC);
2043	emitop(OP_BRFL);
2044	n = chain(0);
2045
2046	compare_value(12, 4, prog);
2047	emitop(OP_BRFL);
2048	m = chain(0);
2049	if (vers >= 0) {
2050		compare_value(16, 4, vers);
2051		emitop(OP_BRFL);
2052		m = chain(m);
2053	}
2054	if (proc >= 0) {
2055		compare_value(20, 4, proc);
2056		emitop(OP_BRFL);
2057		m = chain(m);
2058	}
2059
2060	switch (which) {
2061	case TO:
2062		compare_value(4, 4, CALL);
2063		emitop(OP_BRFL);
2064		m = chain(m);
2065		break;
2066	case FROM:
2067		compare_value(4, 4, REPLY);
2068		emitop(OP_BRFL);
2069		m = chain(m);
2070		break;
2071	}
2072	resolve_chain(m);
2073	resolve_chain(n);
2074	emitop(OP_OFFSET_POP);
2075}
2076
2077/*
2078 * Generate code to parse a field specification
2079 * and load the value of the field from the packet
2080 * onto the operand stack.
2081 * The field offset may be specified relative to the
2082 * beginning of the ether header, IP header, UDP header,
2083 * or TCP header.  An optional size specification may
2084 * be provided following a colon.  If no size is given
2085 * one byte is assumed e.g.
2086 *
2087 *	ether[0]	The first byte of the ether header
2088 *	ip[2:2]		The second 16 bit field of the IP header
2089 */
2090static void
2091load_field()
2092{
2093	int size = 1;
2094	int s;
2095
2096
2097	if (EQ("ether"))
2098		emitop(OP_OFFSET_ZERO);
2099	else if (EQ("ip") || EQ("ip6") || EQ("pppoed") || EQ("pppoes"))
2100		emitop(OP_OFFSET_LINK);
2101	else if (EQ("udp") || EQ("tcp") || EQ("icmp") || EQ("ip-in-ip") ||
2102	    EQ("ah") || EQ("esp"))
2103		emitop(OP_OFFSET_IP);
2104	else
2105		pr_err("invalid field type");
2106	next();
2107	s = opstack;
2108	expression();
2109	if (opstack != s + 1)
2110		pr_err("invalid field offset");
2111	opstack--;
2112	if (*token == ':') {
2113		next();
2114		if (tokentype != NUMBER)
2115			pr_err("field size expected");
2116		size = tokenval;
2117		if (size != 1 && size != 2 && size != 4)
2118			pr_err("field size invalid");
2119		next();
2120	}
2121	if (*token != ']')
2122		pr_err("right bracket expected");
2123
2124	load_value(-1, size);
2125	emitop(OP_OFFSET_POP);
2126}
2127
2128/*
2129 * Check that the operand stack
2130 * contains n arguments
2131 */
2132static void
2133checkstack(int numargs)
2134{
2135	if (opstack != numargs)
2136		pr_err("invalid expression at \"%s\".", token);
2137}
2138
2139static void
2140primary()
2141{
2142	int m, m2, s;
2143
2144	for (;;) {
2145		if (tokentype == FIELD) {
2146			load_field();
2147			opstack++;
2148			next();
2149			break;
2150		}
2151
2152		if (comparison(token)) {
2153			opstack++;
2154			next();
2155			break;
2156		}
2157
2158		if (EQ("not") || EQ("!")) {
2159			next();
2160			s = opstack;
2161			primary();
2162			checkstack(s + 1);
2163			emitop(OP_NOT);
2164			break;
2165		}
2166
2167		if (EQ("(")) {
2168			next();
2169			s = opstack;
2170			expression();
2171			checkstack(s + 1);
2172			if (!EQ(")"))
2173				pr_err("right paren expected");
2174			next();
2175		}
2176
2177		if (EQ("to") || EQ("dst")) {
2178			dir = TO;
2179			next();
2180			continue;
2181		}
2182
2183		if (EQ("from") || EQ("src")) {
2184			dir = FROM;
2185			next();
2186			continue;
2187		}
2188
2189		if (EQ("ether")) {
2190			eaddr = 1;
2191			next();
2192			continue;
2193		}
2194
2195		if (EQ("proto")) {
2196			next();
2197			if (tokentype != NUMBER)
2198				pr_err("IP proto type expected");
2199			emitop(OP_OFFSET_LINK);
2200			compare_value(IPV4_TYPE_HEADER_OFFSET, 1, tokenval);
2201			emitop(OP_OFFSET_POP);
2202			opstack++;
2203			next();
2204			continue;
2205		}
2206
2207		if (EQ("broadcast")) {
2208			/*
2209			 * Be tricky: FDDI ether dst address begins at
2210			 * byte one.  Since the address is really six
2211			 * bytes long, this works for FDDI & ethernet.
2212			 * XXX - Token ring?
2213			 */
2214			emitop(OP_OFFSET_ZERO);
2215			if (interface->mac_type == DL_IB)
2216				pr_err("filter option unsupported on media");
2217			compare_value(1, 4, 0xffffffff);
2218			emitop(OP_OFFSET_POP);
2219			opstack++;
2220			next();
2221			break;
2222		}
2223
2224		if (EQ("multicast")) {
2225			/* XXX Token ring? */
2226			emitop(OP_OFFSET_ZERO);
2227			if (interface->mac_type == DL_FDDI) {
2228				compare_value_mask(1, 1, 0x01, 0x01);
2229			} else if (interface->mac_type == DL_IB) {
2230				pr_err("filter option unsupported on media");
2231			} else {
2232				compare_value_mask(0, 1, 0x01, 0x01);
2233			}
2234			emitop(OP_OFFSET_POP);
2235			opstack++;
2236			next();
2237			break;
2238		}
2239
2240		if (EQ("decnet")) {
2241			/* XXX Token ring? */
2242			if (interface->mac_type == DL_FDDI) {
2243				load_value(19, 2);	/* ether type */
2244				load_const(0x6000);
2245				emitop(OP_GE);
2246				emitop(OP_BRFL);
2247				m = chain(0);
2248				load_value(19, 2);	/* ether type */
2249				load_const(0x6009);
2250				emitop(OP_LE);
2251				resolve_chain(m);
2252			} else {
2253				emitop(OP_OFFSET_ETHERTYPE);
2254				load_value(0, 2);	/* ether type */
2255				load_const(0x6000);
2256				emitop(OP_GE);
2257				emitop(OP_BRFL);
2258				m = chain(0);
2259				load_value(0, 2);	/* ether type */
2260				load_const(0x6009);
2261				emitop(OP_LE);
2262				resolve_chain(m);
2263				emitop(OP_OFFSET_POP);
2264			}
2265			opstack++;
2266			next();
2267			break;
2268		}
2269
2270		if (EQ("vlan-id")) {
2271			next();
2272			if (tokentype != NUMBER)
2273				pr_err("vlan id expected");
2274			emitop(OP_OFFSET_ZERO);
2275			ethertype_match(ETHERTYPE_VLAN);
2276			emitop(OP_BRFL);
2277			m = chain(0);
2278			compare_value_mask(VLAN_ID_OFFSET, 2, tokenval,
2279			    VLAN_ID_MASK);
2280			resolve_chain(m);
2281			emitop(OP_OFFSET_POP);
2282			opstack++;
2283			next();
2284			break;
2285		}
2286
2287		if (EQ("apple")) {
2288			/*
2289			 * Appletalk also appears in 802.2
2290			 * packets, so check for the ethertypes
2291			 * at offset 12 and 20 in the MAC header.
2292			 */
2293			ethertype_match(ETHERTYPE_AT);
2294			emitop(OP_BRTR);
2295			m = chain(0);
2296			ethertype_match(ETHERTYPE_AARP);
2297			emitop(OP_BRTR);
2298			m = chain(m);
2299			compare_value(20, 2, ETHERTYPE_AT); /* 802.2 */
2300			emitop(OP_BRTR);
2301			m = chain(m);
2302			compare_value(20, 2, ETHERTYPE_AARP); /* 802.2 */
2303			resolve_chain(m);
2304			opstack++;
2305			next();
2306			break;
2307		}
2308
2309		if (EQ("vlan")) {
2310			ethertype_match(ETHERTYPE_VLAN);
2311			compare_value_mask(VLAN_ID_OFFSET, 2, 0, VLAN_ID_MASK);
2312			emitop(OP_NOT);
2313			emitop(OP_AND);
2314			opstack++;
2315			next();
2316			break;
2317		}
2318
2319		if (EQ("bootp") || EQ("dhcp")) {
2320			ethertype_match(interface->network_type_ip);
2321			emitop(OP_BRFL);
2322			m = chain(0);
2323			emitop(OP_OFFSET_LINK);
2324			compare_value(9, 1, IPPROTO_UDP);
2325			emitop(OP_OFFSET_POP);
2326			emitop(OP_BRFL);
2327			m = chain(m);
2328			emitop(OP_OFFSET_IP);
2329			compare_value(0, 4,
2330			    (IPPORT_BOOTPS << 16) | IPPORT_BOOTPC);
2331			emitop(OP_BRTR);
2332			m2 = chain(0);
2333			compare_value(0, 4,
2334			    (IPPORT_BOOTPC << 16) | IPPORT_BOOTPS);
2335			resolve_chain(m2);
2336			emitop(OP_OFFSET_POP);
2337			resolve_chain(m);
2338			opstack++;
2339			dir = ANY;
2340			next();
2341			break;
2342		}
2343
2344		if (EQ("dhcp6")) {
2345			ethertype_match(interface->network_type_ipv6);
2346			emitop(OP_BRFL);
2347			m = chain(0);
2348			emitop(OP_OFFSET_LINK);
2349			compare_value(6, 1, IPPROTO_UDP);
2350			emitop(OP_OFFSET_POP);
2351			emitop(OP_BRFL);
2352			m = chain(m);
2353			emitop(OP_OFFSET_IP);
2354			compare_value(2, 2, IPPORT_DHCPV6S);
2355			emitop(OP_BRTR);
2356			m2 = chain(0);
2357			compare_value(2, 2, IPPORT_DHCPV6C);
2358			resolve_chain(m2);
2359			emitop(OP_OFFSET_POP);
2360			resolve_chain(m);
2361			opstack++;
2362			dir = ANY;
2363			next();
2364			break;
2365		}
2366
2367		if (EQ("ethertype")) {
2368			next();
2369			if (tokentype != NUMBER)
2370				pr_err("ether type expected");
2371			ethertype_match(tokenval);
2372			opstack++;
2373			next();
2374			break;
2375		}
2376
2377		if (EQ("pppoe")) {
2378			ethertype_match(ETHERTYPE_PPPOED);
2379			ethertype_match(ETHERTYPE_PPPOES);
2380			emitop(OP_OR);
2381			opstack++;
2382			next();
2383			break;
2384		}
2385
2386		if (EQ("inet")) {
2387			next();
2388			if (EQ("host"))
2389				next();
2390			if (tokentype != ALPHA && tokentype != ADDR_IP)
2391				pr_err("host/IPv4 addr expected after inet");
2392			ipaddr_match(dir, token, IPV4_ONLY);
2393			opstack++;
2394			next();
2395			break;
2396		}
2397
2398		if (EQ("inet6")) {
2399			next();
2400			if (EQ("host"))
2401				next();
2402			if (tokentype != ALPHA && tokentype != ADDR_IP6)
2403				pr_err("host/IPv6 addr expected after inet6");
2404			ipaddr_match(dir, token, IPV6_ONLY);
2405			opstack++;
2406			next();
2407			break;
2408		}
2409
2410		if (EQ("length")) {
2411			emitop(OP_LOAD_LENGTH);
2412			opstack++;
2413			next();
2414			break;
2415		}
2416
2417		if (EQ("less")) {
2418			next();
2419			if (tokentype != NUMBER)
2420				pr_err("packet length expected");
2421			emitop(OP_LOAD_LENGTH);
2422			load_const(tokenval);
2423			emitop(OP_LT);
2424			opstack++;
2425			next();
2426			break;
2427		}
2428
2429		if (EQ("greater")) {
2430			next();
2431			if (tokentype != NUMBER)
2432				pr_err("packet length expected");
2433			emitop(OP_LOAD_LENGTH);
2434			load_const(tokenval);
2435			emitop(OP_GT);
2436			opstack++;
2437			next();
2438			break;
2439		}
2440
2441		if (EQ("nofrag")) {
2442			emitop(OP_OFFSET_LINK);
2443			compare_value_mask(6, 2, 0, 0x1fff);
2444			emitop(OP_OFFSET_POP);
2445			emitop(OP_BRFL);
2446			m = chain(0);
2447			ethertype_match(interface->network_type_ip);
2448			resolve_chain(m);
2449			opstack++;
2450			next();
2451			break;
2452		}
2453
2454		if (EQ("net") || EQ("dstnet") || EQ("srcnet")) {
2455			if (EQ("dstnet"))
2456				dir = TO;
2457			else if (EQ("srcnet"))
2458				dir = FROM;
2459			next();
2460			netaddr_match(dir, token);
2461			dir = ANY;
2462			opstack++;
2463			next();
2464			break;
2465		}
2466
2467		if (EQ("port") || EQ("srcport") || EQ("dstport")) {
2468			if (EQ("dstport"))
2469				dir = TO;
2470			else if (EQ("srcport"))
2471				dir = FROM;
2472			next();
2473			port_match(dir, token);
2474			dir = ANY;
2475			opstack++;
2476			next();
2477			break;
2478		}
2479
2480		if (EQ("rpc")) {
2481			uint_t vers, proc;
2482			char savetoken[32];
2483
2484			vers = proc = -1;
2485			next();
2486			(void) strlcpy(savetoken, token, sizeof (savetoken));
2487			next();
2488			if (*token == ',') {
2489				next();
2490				if (tokentype != NUMBER)
2491					pr_err("version number expected");
2492				vers = tokenval;
2493				next();
2494			}
2495			if (*token == ',') {
2496				next();
2497				if (tokentype != NUMBER)
2498					pr_err("proc number expected");
2499				proc = tokenval;
2500				next();
2501			}
2502			rpc_match_prog(dir, savetoken, vers, proc);
2503			dir = ANY;
2504			opstack++;
2505			break;
2506		}
2507
2508		if (EQ("slp")) {
2509			/* filter out TCP handshakes */
2510			emitop(OP_OFFSET_LINK);
2511			compare_value(9, 1, IPPROTO_TCP);
2512			emitop(OP_LOAD_CONST);
2513			emitval(52);
2514			emitop(OP_LOAD_CONST);
2515			emitval(2);
2516			emitop(OP_LOAD_SHORT);
2517			emitop(OP_GE);
2518			emitop(OP_AND);	/* proto == TCP && len < 52 */
2519			emitop(OP_NOT);
2520			emitop(OP_BRFL); /* pkt too short to be a SLP call */
2521			m = chain(0);
2522
2523			emitop(OP_OFFSET_POP);
2524			emitop(OP_OFFSET_SLP);
2525			resolve_chain(m);
2526			opstack++;
2527			next();
2528			break;
2529		}
2530
2531		if (EQ("ldap")) {
2532			dir = ANY;
2533			port_match(dir, "ldap");
2534			opstack++;
2535			next();
2536			break;
2537		}
2538
2539		if (EQ("and") || EQ("or")) {
2540			break;
2541		}
2542
2543		if (EQ("zone")) {
2544			next();
2545			if (tokentype != NUMBER)
2546				pr_err("zoneid expected");
2547			zone_match(dir, BE_32((uint32_t)(tokenval)));
2548			opstack++;
2549			next();
2550			break;
2551		}
2552
2553		if (EQ("gateway")) {
2554			next();
2555			if (eaddr || tokentype != ALPHA)
2556				pr_err("hostname required: %s", token);
2557			etheraddr_match(dir, token);
2558			dir = ANY;
2559			emitop(OP_BRFL);
2560			m = chain(0);
2561			ipaddr_match(dir, token, IPV4_AND_IPV6);
2562			emitop(OP_NOT);
2563			resolve_chain(m);
2564			opstack++;
2565			next();
2566		}
2567
2568		if (EQ("host") || EQ("between") ||
2569		    tokentype == ALPHA ||	/* assume its a hostname */
2570		    tokentype == ADDR_IP ||
2571		    tokentype == ADDR_IP6 ||
2572		    tokentype == ADDR_AT ||
2573		    tokentype == ADDR_ETHER) {
2574			if (EQ("host") || EQ("between"))
2575				next();
2576			if (eaddr || tokentype == ADDR_ETHER) {
2577				etheraddr_match(dir, token);
2578			} else if (tokentype == ALPHA) {
2579				ipaddr_match(dir, token, IPV4_AND_IPV6);
2580			} else if (tokentype == ADDR_AT) {
2581				ataddr_match(dir, token);
2582			} else if (tokentype == ADDR_IP) {
2583				ipaddr_match(dir, token, IPV4_ONLY);
2584			} else {
2585				ipaddr_match(dir, token, IPV6_ONLY);
2586			}
2587			dir = ANY;
2588			eaddr = 0;
2589			opstack++;
2590			next();
2591			break;
2592		}
2593
2594		if (tokentype == NUMBER) {
2595			load_const(tokenval);
2596			opstack++;
2597			next();
2598			break;
2599		}
2600
2601		break;	/* unknown token */
2602	}
2603}
2604
2605struct optable {
2606	char *op_tok;
2607	enum optype op_type;
2608};
2609
2610static struct optable
2611mulops[] = {
2612	"*",	OP_MUL,
2613	"/",	OP_DIV,
2614	"%",	OP_REM,
2615	"&",	OP_AND,
2616	"",	OP_STOP,
2617};
2618
2619static struct optable
2620addops[] = {
2621	"+",	OP_ADD,
2622	"-",	OP_SUB,
2623	"|",	OP_OR,
2624	"^",	OP_XOR,
2625	"",	OP_STOP,
2626};
2627
2628static struct optable
2629compareops[] = {
2630	"==",	OP_EQ,
2631	"=",	OP_EQ,
2632	"!=",	OP_NE,
2633	">",	OP_GT,
2634	">=",	OP_GE,
2635	"<",	OP_LT,
2636	"<=",	OP_LE,
2637	"",	OP_STOP,
2638};
2639
2640/*
2641 * Using the table, find the operator
2642 * that corresponds to the token.
2643 * Return 0 if not found.
2644 */
2645static int
2646find_op(char *tok, struct optable *table)
2647{
2648	struct optable *op;
2649
2650	for (op = table; *op->op_tok; op++) {
2651		if (strcmp(tok, op->op_tok) == 0)
2652			return (op->op_type);
2653	}
2654
2655	return (0);
2656}
2657
2658static void
2659expr_mul()
2660{
2661	int op;
2662	int s = opstack;
2663
2664	primary();
2665	while (op = find_op(token, mulops)) {
2666		next();
2667		primary();
2668		checkstack(s + 2);
2669		emitop(op);
2670		opstack--;
2671	}
2672}
2673
2674static void
2675expr_add()
2676{
2677	int op, s = opstack;
2678
2679	expr_mul();
2680	while (op = find_op(token, addops)) {
2681		next();
2682		expr_mul();
2683		checkstack(s + 2);
2684		emitop(op);
2685		opstack--;
2686	}
2687}
2688
2689static void
2690expr_compare()
2691{
2692	int op, s = opstack;
2693
2694	expr_add();
2695	while (op = find_op(token, compareops)) {
2696		next();
2697		expr_add();
2698		checkstack(s + 2);
2699		emitop(op);
2700		opstack--;
2701	}
2702}
2703
2704/*
2705 * Alternation ("and") is difficult because
2706 * an implied "and" is acknowledge between
2707 * two adjacent primaries.  Just keep calling
2708 * the lower-level expression routine until
2709 * no value is added to the opstack.
2710 */
2711static void
2712alternation()
2713{
2714	int m = 0;
2715	int s = opstack;
2716
2717	expr_compare();
2718	checkstack(s + 1);
2719	for (;;) {
2720		if (EQ("and"))
2721			next();
2722		emitop(OP_BRFL);
2723		m = chain(m);
2724		expr_compare();
2725		if (opstack != s + 2)
2726			break;
2727		opstack--;
2728	}
2729	unemit(2);
2730	resolve_chain(m);
2731}
2732
2733static void
2734expression()
2735{
2736	int m = 0;
2737	int s = opstack;
2738
2739	alternation();
2740	while (EQ("or") || EQ(",")) {
2741		emitop(OP_BRTR);
2742		m = chain(m);
2743		next();
2744		alternation();
2745		checkstack(s + 2);
2746		opstack--;
2747	}
2748	resolve_chain(m);
2749}
2750
2751/*
2752 * Take n args from the argv list
2753 * and concatenate them into a single string.
2754 */
2755char *
2756concat_args(char **argv, int argc)
2757{
2758	int i, len;
2759	char *str, *p;
2760
2761	/* First add the lengths of all the strings */
2762	len = 0;
2763	for (i = 0; i < argc; i++)
2764		len += strlen(argv[i]) + 1;
2765
2766	/* allocate the big string */
2767	str = (char *)malloc(len);
2768	if (str == NULL)
2769		pr_err("no mem");
2770
2771	p = str;
2772
2773	/*
2774	 * Concat the strings into the big
2775	 * string using a space as separator
2776	 */
2777	for (i = 0; i < argc; i++) {
2778		strcpy(p, argv[i]);
2779		p += strlen(p);
2780		*p++ = ' ';
2781	}
2782	*--p = '\0';
2783
2784	return (str);
2785}
2786
2787/*
2788 * Take the expression in the string "expr"
2789 * and compile it into the code array.
2790 * Print the generated code if the print
2791 * arg is set.
2792 */
2793void
2794compile(char *expr, int print)
2795{
2796	expr = strdup(expr);
2797	if (expr == NULL)
2798		pr_err("no mem");
2799	curr_op = oplist;
2800	tkp = expr;
2801	dir = ANY;
2802
2803	next();
2804	if (tokentype != EOL)
2805		expression();
2806	emitop(OP_STOP);
2807	if (tokentype != EOL)
2808		pr_err("invalid expression");
2809	optimize(oplist);
2810	if (print)
2811		codeprint();
2812}
2813
2814/*
2815 * Lookup hostname in the arp cache.
2816 */
2817boolean_t
2818arp_for_ether(char *hostname, struct ether_addr *ep)
2819{
2820	struct arpreq ar;
2821	struct hostent *hp;
2822	struct sockaddr_in *sin;
2823	int error_num;
2824	int s;
2825
2826	memset(&ar, 0, sizeof (ar));
2827	sin = (struct sockaddr_in *)&ar.arp_pa;
2828	sin->sin_family = AF_INET;
2829	hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
2830	if (hp == NULL) {
2831		return (B_FALSE);
2832	}
2833	memcpy(&sin->sin_addr, hp->h_addr, sizeof (sin->sin_addr));
2834	s = socket(AF_INET, SOCK_DGRAM, 0);
2835	if (s < 0) {
2836		return (B_FALSE);
2837	}
2838	if (ioctl(s, SIOCGARP, &ar) < 0) {
2839		close(s);
2840		return (B_FALSE);
2841	}
2842	close(s);
2843	memcpy(ep->ether_addr_octet, ar.arp_ha.sa_data, sizeof (*ep));
2844	return (B_TRUE);
2845}
2846