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