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         "dccp",         9,  1, IPPROTO_DCCP,     0,     OP_OFFSET_LINK,
1350         "dccp",         6,  1, IPPROTO_DCCP,     1,     OP_OFFSET_LINK,
1351         0,              0,  0, 0,                0,     0
1352 };
1353 
1354 static match_type_t ipnet_match_types[] = {
1355         /*
1356          * Table initialized assuming Ethernet data link headers.
1357          * m_offset is an offset beyond the offset op, which is why
1358          * the offset is zero for when snoop needs to check an ethertype.
1359          */
1360         "ip",           0,  1, IPV4_VERSION,    -1,     OP_OFFSET_ETHERTYPE,
1361         "ip6",          0,  1, IPV6_VERSION,    -1,     OP_OFFSET_ETHERTYPE,
1362         "tcp",          9,  1, IPPROTO_TCP,      0,     OP_OFFSET_LINK,
1363         "tcp",          6,  1, IPPROTO_TCP,      1,     OP_OFFSET_LINK,
1364         "udp",          9,  1, IPPROTO_UDP,      0,     OP_OFFSET_LINK,
1365         "udp",          6,  1, IPPROTO_UDP,      1,     OP_OFFSET_LINK,
1366         "icmp",         9,  1, IPPROTO_ICMP,     0,     OP_OFFSET_LINK,
1367         "icmp6",        6,  1, IPPROTO_ICMPV6,   1,     OP_OFFSET_LINK,
1368         "ospf",         9,  1, IPPROTO_OSPF,     0,     OP_OFFSET_LINK,
1369         "ospf",         6,  1, IPPROTO_OSPF,     1,     OP_OFFSET_LINK,
1370         "ip-in-ip",     9,  1, IPPROTO_ENCAP,    0,     OP_OFFSET_LINK,
1371         "esp",          9,  1, IPPROTO_ESP,      0,     OP_OFFSET_LINK,
1372         "esp",          6,  1, IPPROTO_ESP,      1,     OP_OFFSET_LINK,
1373         "ah",           9,  1, IPPROTO_AH,       0,     OP_OFFSET_LINK,
1374         "ah",           6,  1, IPPROTO_AH,       1,     OP_OFFSET_LINK,
1375         "sctp",         9,  1, IPPROTO_SCTP,     0,     OP_OFFSET_LINK,
1376         "sctp",         6,  1, IPPROTO_SCTP,     1,     OP_OFFSET_LINK,
1377         "dccp",         9,  1, IPPROTO_DCCP,     0,     OP_OFFSET_LINK,
1378         "dccp",         6,  1, IPPROTO_DCCP,     1,     OP_OFFSET_LINK,
1379         0,              0,  0, 0,                0,     0
1380 };
1381 
1382 static match_type_t iptun_match_types[] = {
1383         "ip",           0,  1, IPPROTO_ENCAP,   -1,     OP_OFFSET_ETHERTYPE,
1384         "ip6",          0,  1, IPPROTO_IPV6,    -1,     OP_OFFSET_ETHERTYPE,
1385         "tcp",          9,  1, IPPROTO_TCP,     0,      OP_OFFSET_LINK,
1386         "tcp",          6,  1, IPPROTO_TCP,     1,      OP_OFFSET_LINK,
1387         "udp",          9,  1, IPPROTO_UDP,     0,      OP_OFFSET_LINK,
1388         "udp",          6,  1, IPPROTO_UDP,     1,      OP_OFFSET_LINK,
1389         "icmp",         9,  1, IPPROTO_ICMP,    0,      OP_OFFSET_LINK,
1390         "icmp6",        6,  1, IPPROTO_ICMPV6,  1,      OP_OFFSET_LINK,
1391         "ospf",         9,  1, IPPROTO_OSPF,    0,      OP_OFFSET_LINK,
1392         "ospf",         6,  1, IPPROTO_OSPF,    1,      OP_OFFSET_LINK,
1393         "ip-in-ip",     9,  1, IPPROTO_ENCAP,   0,      OP_OFFSET_LINK,
1394         "esp",          9,  1, IPPROTO_ESP,     0,      OP_OFFSET_LINK,
1395         "esp",          6,  1, IPPROTO_ESP,     1,      OP_OFFSET_LINK,
1396         "ah",           9,  1, IPPROTO_AH,      0,      OP_OFFSET_LINK,
1397         "ah",           6,  1, IPPROTO_AH,      1,      OP_OFFSET_LINK,
1398         "sctp",         9,  1, IPPROTO_SCTP,    0,      OP_OFFSET_LINK,
1399         "sctp",         6,  1, IPPROTO_SCTP,    1,      OP_OFFSET_LINK,
1400         "dccp",         9,  1, IPPROTO_DCCP,    0,      OP_OFFSET_LINK,
1401         "dccp",         6,  1, IPPROTO_DCCP,    1,      OP_OFFSET_LINK,
1402         0,              0,  0, 0,               0,      0
1403 };
1404 
1405 static void
1406 generate_check(match_type_t match_types[], int index, int type)
1407 {
1408         match_type_t *mtp = &match_types[index];
1409         /*
1410          * Note: this code assumes the above dependencies are
1411          * not cyclic.  This *should* always be true.
1412          */
1413         if (mtp->m_depend != -1)
1414                 generate_check(match_types, mtp->m_depend, type);
1415 
1416         emitop(mtp->m_optype);
1417         load_value(mtp->m_offset, mtp->m_size);
1418         load_const(mtp->m_value);
1419         emitop(OP_OFFSET_POP);
1420 
1421         emitop(OP_EQ);
1422 
1423         if (mtp->m_depend != -1)
1424                 emitop(OP_AND);
1425 }
1426 
1427 /*
1428  * Generate code based on the keyword argument.
1429  * This word is looked up in the match_types table
1430  * and checks a field within the packet for a given
1431  * value e.g. ether or ip type field.  The match
1432  * can also have a dependency on another entry e.g.
1433  * "tcp" requires that the packet also be "ip".
1434  */
1435 static int
1436 comparison(char *s)
1437 {
1438         unsigned int    i, n_checks = 0;
1439         match_type_t    *match_types;
1440 
1441         switch (interface->mac_type) {
1442         case DL_ETHER:
1443                 match_types = ether_match_types;
1444                 break;
1445         case DL_IPNET:
1446                 match_types = ipnet_match_types;
1447                 break;
1448         case DL_IPV4:
1449         case DL_IPV6:
1450         case DL_6TO4:
1451                 match_types = iptun_match_types;
1452                 break;
1453         default:
1454                 return (0);
1455         }
1456 
1457         for (i = 0; match_types[i].m_name != NULL; i++) {
1458                 if (strcmp(s, match_types[i].m_name) != 0)
1459                         continue;
1460 
1461                 n_checks++;
1462                 generate_check(match_types, i, interface->mac_type);
1463                 if (n_checks > 1)
1464                         emitop(OP_OR);
1465         }
1466 
1467         return (n_checks > 0);
1468 }
1469 
1470 enum direction { ANY, TO, FROM };
1471 enum direction dir;
1472 
1473 /*
1474  * Generate code to match an IP address.  The address
1475  * may be supplied either as a hostname or in dotted format.
1476  * For source packets both the IP source address and ARP
1477  * src are checked.
1478  * Note: we don't check packet type here - whether IP or ARP.
1479  * It's possible that we'll do an improper match.
1480  */
1481 static void
1482 ipaddr_match(enum direction which, char *hostname, int inet_type)
1483 {
1484         bool_t found_host;
1485         int m = 0, n = 0;
1486         uint_t *addr4ptr;
1487         uint_t addr4;
1488         struct in6_addr *addr6ptr;
1489         int h_addr_index;
1490         struct hostent *hp = NULL;
1491         int error_num = 0;
1492         boolean_t freehp = B_FALSE;
1493         boolean_t first = B_TRUE;
1494 
1495         /*
1496          * The addr4offset and addr6offset variables simplify the code which
1497          * generates the address comparison filter.  With these two variables,
1498          * duplicate code need not exist for the TO and FROM case.
1499          * A value of -1 describes the ANY case (TO and FROM).
1500          */
1501         int addr4offset;
1502         int addr6offset;
1503 
1504         found_host = 0;
1505 
1506         if (tokentype == ADDR_IP) {
1507                 hp = lgetipnodebyname(hostname, AF_INET, 0, &error_num);
1508                 if (hp == NULL) {
1509                         hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
1510                         freehp = 1;
1511                 }
1512                 if (hp == NULL) {
1513                         if (error_num == TRY_AGAIN) {
1514                                 pr_err("couldn't resolve %s (try again later)",
1515                                     hostname);
1516                         } else {
1517                                 pr_err("couldn't resolve %s", hostname);
1518                         }
1519                 }
1520                 inet_type = IPV4_ONLY;
1521         } else if (tokentype == ADDR_IP6) {
1522                 hp = lgetipnodebyname(hostname, AF_INET6, 0, &error_num);
1523                 if (hp == NULL) {
1524                         hp = getipnodebyname(hostname, AF_INET6, 0, &error_num);
1525                         freehp = 1;
1526                 }
1527                 if (hp == NULL) {
1528                         if (error_num == TRY_AGAIN) {
1529                                 pr_err("couldn't resolve %s (try again later)",
1530                                     hostname);
1531                         } else {
1532                                 pr_err("couldn't resolve %s", hostname);
1533                         }
1534                 }
1535                 inet_type = IPV6_ONLY;
1536         } else {
1537                 /* Some hostname i.e. tokentype is ALPHA */
1538                 switch (inet_type) {
1539                 case IPV4_ONLY:
1540                         /* Only IPv4 address is needed */
1541                         hp = lgetipnodebyname(hostname, AF_INET, 0, &error_num);
1542                         if (hp == NULL) {
1543                                 hp = getipnodebyname(hostname, AF_INET, 0,
1544                                     &error_num);
1545                                 freehp = 1;
1546                         }
1547                         if (hp != NULL) {
1548                                 found_host = 1;
1549                         }
1550                         break;
1551                 case IPV6_ONLY:
1552                         /* Only IPv6 address is needed */
1553                         hp = lgetipnodebyname(hostname, AF_INET6, 0,
1554                             &error_num);
1555                         if (hp == NULL) {
1556                                 hp = getipnodebyname(hostname, AF_INET6, 0,
1557                                     &error_num);
1558                                 freehp = 1;
1559                         }
1560                         if (hp != NULL) {
1561                                 found_host = 1;
1562                         }
1563                         break;
1564                 case IPV4_AND_IPV6:
1565                         /* Both IPv4 and IPv6 are needed */
1566                         hp = lgetipnodebyname(hostname, AF_INET6,
1567                             AI_ALL | AI_V4MAPPED, &error_num);
1568                         if (hp == NULL) {
1569                                 hp = getipnodebyname(hostname, AF_INET6,
1570                                     AI_ALL | AI_V4MAPPED, &error_num);
1571                                 freehp = 1;
1572                         }
1573                         if (hp != NULL) {
1574                                 found_host = 1;
1575                         }
1576                         break;
1577                 default:
1578                         found_host = 0;
1579                 }
1580 
1581                 if (!found_host) {
1582                         if (error_num == TRY_AGAIN) {
1583                                 pr_err("could not resolve %s (try again later)",
1584                                     hostname);
1585                         } else {
1586                                 pr_err("could not resolve %s", hostname);
1587                         }
1588                 }
1589         }
1590 
1591         switch (which) {
1592         case TO:
1593                 addr4offset = IPV4_DSTADDR_OFFSET;
1594                 addr6offset = IPV6_DSTADDR_OFFSET;
1595                 break;
1596         case FROM:
1597                 addr4offset = IPV4_SRCADDR_OFFSET;
1598                 addr6offset = IPV6_SRCADDR_OFFSET;
1599                 break;
1600         case ANY:
1601                 addr4offset = -1;
1602                 addr6offset = -1;
1603                 break;
1604         }
1605 
1606         /*
1607          * The code below generates the filter.
1608          */
1609         if (hp != NULL && hp->h_addrtype == AF_INET) {
1610                 ethertype_match(interface->network_type_ip);
1611                 emitop(OP_BRFL);
1612                 n = chain(n);
1613                 emitop(OP_OFFSET_LINK);
1614                 h_addr_index = 0;
1615                 addr4ptr = (uint_t *)hp->h_addr_list[h_addr_index];
1616                 while (addr4ptr != NULL) {
1617                         if (addr4offset == -1) {
1618                                 compare_addr_v4(IPV4_SRCADDR_OFFSET, 4,
1619                                     *addr4ptr);
1620                                 emitop(OP_BRTR);
1621                                 m = chain(m);
1622                                 compare_addr_v4(IPV4_DSTADDR_OFFSET, 4,
1623                                     *addr4ptr);
1624                         } else {
1625                                 compare_addr_v4(addr4offset, 4, *addr4ptr);
1626                         }
1627                         addr4ptr = (uint_t *)hp->h_addr_list[++h_addr_index];
1628                         if (addr4ptr != NULL) {
1629                                 emitop(OP_BRTR);
1630                                 m = chain(m);
1631                         }
1632                 }
1633                 if (m != 0) {
1634                         resolve_chain(m);
1635                 }
1636                 emitop(OP_OFFSET_POP);
1637                 resolve_chain(n);
1638         } else {
1639                 /* first pass: IPv4 addresses */
1640                 h_addr_index = 0;
1641                 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
1642                 first = B_TRUE;
1643                 while (addr6ptr != NULL) {
1644                         if (IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
1645                                 if (first) {
1646                                         ethertype_match(
1647                                             interface->network_type_ip);
1648                                         emitop(OP_BRFL);
1649                                         n = chain(n);
1650                                         emitop(OP_OFFSET_LINK);
1651                                         first = B_FALSE;
1652                                 } else {
1653                                         emitop(OP_BRTR);
1654                                         m = chain(m);
1655                                 }
1656                                 IN6_V4MAPPED_TO_INADDR(addr6ptr,
1657                                     (struct in_addr *)&addr4);
1658                                 if (addr4offset == -1) {
1659                                         compare_addr_v4(IPV4_SRCADDR_OFFSET, 4,
1660                                             addr4);
1661                                         emitop(OP_BRTR);
1662                                         m = chain(m);
1663                                         compare_addr_v4(IPV4_DSTADDR_OFFSET, 4,
1664                                             addr4);
1665                                 } else {
1666                                         compare_addr_v4(addr4offset, 4, addr4);
1667                                 }
1668                         }
1669                         addr6ptr = (struct in6_addr *)
1670                             hp->h_addr_list[++h_addr_index];
1671                 }
1672                 /* second pass: IPv6 addresses */
1673                 h_addr_index = 0;
1674                 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index];
1675                 first = B_TRUE;
1676                 while (addr6ptr != NULL) {
1677                         if (!IN6_IS_ADDR_V4MAPPED(addr6ptr)) {
1678                                 if (first) {
1679                                         /*
1680                                          * bypass check for IPv6 addresses
1681                                          * when we have an IPv4 packet
1682                                          */
1683                                         if (n != 0) {
1684                                                 emitop(OP_BRTR);
1685                                                 m = chain(m);
1686                                                 emitop(OP_BRFL);
1687                                                 m = chain(m);
1688                                                 resolve_chain(n);
1689                                                 n = 0;
1690                                         }
1691                                         ethertype_match(
1692                                             interface->network_type_ipv6);
1693                                         emitop(OP_BRFL);
1694                                         n = chain(n);
1695                                         emitop(OP_OFFSET_LINK);
1696                                         first = B_FALSE;
1697                                 } else {
1698                                         emitop(OP_BRTR);
1699                                         m = chain(m);
1700                                 }
1701                                 if (addr6offset == -1) {
1702                                         compare_addr_v6(IPV6_SRCADDR_OFFSET,
1703                                             16, *addr6ptr);
1704                                         emitop(OP_BRTR);
1705                                         m = chain(m);
1706                                         compare_addr_v6(IPV6_DSTADDR_OFFSET,
1707                                             16, *addr6ptr);
1708                                 } else {
1709                                         compare_addr_v6(addr6offset, 16,
1710                                             *addr6ptr);
1711                                 }
1712                         }
1713                         addr6ptr = (struct in6_addr *)
1714                             hp->h_addr_list[++h_addr_index];
1715                 }
1716                 if (m != 0) {
1717                         resolve_chain(m);
1718                 }
1719                 emitop(OP_OFFSET_POP);
1720                 resolve_chain(n);
1721         }
1722 
1723         /* only free struct hostent returned by getipnodebyname() */
1724         if (freehp) {
1725                 freehostent(hp);
1726         }
1727 }
1728 
1729 /*
1730  * Match on zoneid. The arg zone passed in is in network byte order.
1731  */
1732 static void
1733 zone_match(enum direction which, uint32_t zone)
1734 {
1735 
1736         switch (which) {
1737         case TO:
1738                 compare_value_zone(IPNET_DSTZONE_OFFSET, zone);
1739                 break;
1740         case FROM:
1741                 compare_value_zone(IPNET_SRCZONE_OFFSET, zone);
1742                 break;
1743         case ANY:
1744                 compare_value_zone(IPNET_SRCZONE_OFFSET, zone);
1745                 compare_value_zone(IPNET_DSTZONE_OFFSET, zone);
1746                 emitop(OP_OR);
1747         }
1748 }
1749 
1750 /*
1751  * Generate code to match an AppleTalk address.  The address
1752  * must be given as two numbers with a dot between
1753  *
1754  */
1755 static void
1756 ataddr_match(enum direction which, char *hostname)
1757 {
1758         uint_t net;
1759         uint_t node;
1760         uint_t m, n;
1761 
1762         sscanf(hostname, "%u.%u", &net, &node);
1763 
1764         emitop(OP_OFFSET_LINK);
1765         switch (which) {
1766         case TO:
1767                 compare_value(AT_DST_NET_OFFSET, 2, net);
1768                 emitop(OP_BRFL);
1769                 m = chain(0);
1770                 compare_value(AT_DST_NODE_OFFSET, 1, node);
1771                 resolve_chain(m);
1772                 break;
1773         case FROM:
1774                 compare_value(AT_SRC_NET_OFFSET, 2, net);
1775                 emitop(OP_BRFL);
1776                 m = chain(0);
1777                 compare_value(AT_SRC_NODE_OFFSET, 1, node);
1778                 resolve_chain(m);
1779                 break;
1780         case ANY:
1781                 compare_value(AT_DST_NET_OFFSET, 2, net);
1782                 emitop(OP_BRFL);
1783                 m = chain(0);
1784                 compare_value(AT_DST_NODE_OFFSET, 1, node);
1785                 resolve_chain(m);
1786                 emitop(OP_BRTR);
1787                 n = chain(0);
1788                 compare_value(AT_SRC_NET_OFFSET, 2, net);
1789                 emitop(OP_BRFL);
1790                 m = chain(0);
1791                 compare_value(AT_SRC_NODE_OFFSET, 1, node);
1792                 resolve_chain(m);
1793                 resolve_chain(n);
1794                 break;
1795         }
1796         emitop(OP_OFFSET_POP);
1797 }
1798 
1799 /*
1800  * Compare ethernet addresses. The address may
1801  * be provided either as a hostname or as a
1802  * 6 octet colon-separated address.
1803  */
1804 static void
1805 etheraddr_match(enum direction which, char *hostname)
1806 {
1807         uint_t addr;
1808         ushort_t *addrp;
1809         int to_offset, from_offset;
1810         struct ether_addr e, *ep = NULL;
1811         int m;
1812 
1813         /*
1814          * First, check the interface type for whether src/dest address
1815          * is determinable; if not, retreat early.
1816          */
1817         switch (interface->mac_type) {
1818         case DL_ETHER:
1819                 from_offset = ETHERADDRL;
1820                 to_offset = 0;
1821                 break;
1822 
1823         case DL_IB:
1824                 /*
1825                  * If an ethernet address is attempted to be used
1826                  * on an IPoIB interface, flag error. Link address
1827                  * based filtering is unsupported on IPoIB, so there
1828                  * is no ipibaddr_match() or parsing support for IPoIB
1829                  * 20 byte link addresses.
1830                  */
1831                 pr_err("filter option unsupported on media");
1832                 break;
1833 
1834         case DL_FDDI:
1835                 from_offset = 7;
1836                 to_offset = 1;
1837                 break;
1838 
1839         default:
1840                 /*
1841                  * Where do we find "ether" address for FDDI & TR?
1842                  * XXX can improve?  ~sparker
1843                  */
1844                 load_const(1);
1845                 return;
1846         }
1847 
1848         if (isxdigit(*hostname))
1849                 ep = ether_aton(hostname);
1850         if (ep == NULL) {
1851                 if (ether_hostton(hostname, &e))
1852                         if (!arp_for_ether(hostname, &e))
1853                                 pr_err("cannot obtain ether addr for %s",
1854                                     hostname);
1855                 ep = &e;
1856         }
1857         memcpy(&addr, (ushort_t *)ep, 4);
1858         addrp = (ushort_t *)ep + 2;
1859 
1860         emitop(OP_OFFSET_ZERO);
1861         switch (which) {
1862         case TO:
1863                 compare_value(to_offset, 4, ntohl(addr));
1864                 emitop(OP_BRFL);
1865                 m = chain(0);
1866                 compare_value(to_offset + 4, 2, ntohs(*addrp));
1867                 resolve_chain(m);
1868                 break;
1869         case FROM:
1870                 compare_value(from_offset, 4, ntohl(addr));
1871                 emitop(OP_BRFL);
1872                 m = chain(0);
1873                 compare_value(from_offset + 4, 2, ntohs(*addrp));
1874                 resolve_chain(m);
1875                 break;
1876         case ANY:
1877                 compare_value(to_offset, 4, ntohl(addr));
1878                 compare_value(to_offset + 4, 2, ntohs(*addrp));
1879                 emitop(OP_AND);
1880                 emitop(OP_BRTR);
1881                 m = chain(0);
1882 
1883                 compare_value(from_offset, 4, ntohl(addr));
1884                 compare_value(from_offset + 4, 2, ntohs(*addrp));
1885                 emitop(OP_AND);
1886                 resolve_chain(m);
1887                 break;
1888         }
1889         emitop(OP_OFFSET_POP);
1890 }
1891 
1892 static void
1893 ethertype_match(int val)
1894 {
1895         int ether_offset = interface->network_type_offset;
1896 
1897         /*
1898          * If the user is interested in ethertype VLAN,
1899          * then we need to set the offset to the beginning of the packet.
1900          * But if the user is interested in another ethertype,
1901          * such as IPv4, then we need to take into consideration
1902          * the fact that the packet might be VLAN tagged.
1903          */
1904         if (interface->mac_type == DL_ETHER ||
1905             interface->mac_type == DL_CSMACD) {
1906                 if (val != ETHERTYPE_VLAN) {
1907                         /*
1908                          * OP_OFFSET_ETHERTYPE puts us at the ethertype
1909                          * field whether or not there is a VLAN tag,
1910                          * so ether_offset goes to zero if we get here.
1911                          */
1912                         emitop(OP_OFFSET_ETHERTYPE);
1913                         ether_offset = 0;
1914                 } else {
1915                         emitop(OP_OFFSET_ZERO);
1916                 }
1917         }
1918         compare_value(ether_offset, interface->network_type_len, val);
1919         if (interface->mac_type == DL_ETHER ||
1920             interface->mac_type == DL_CSMACD) {
1921                 emitop(OP_OFFSET_POP);
1922         }
1923 }
1924 
1925 /*
1926  * Match a network address.  The host part
1927  * is masked out.  The network address may
1928  * be supplied either as a netname or in
1929  * IP dotted format.  The mask to be used
1930  * for the comparison is assumed from the
1931  * address format (see comment below).
1932  */
1933 static void
1934 netaddr_match(enum direction which, char *netname)
1935 {
1936         uint_t addr;
1937         uint_t mask = 0xff000000;
1938         uint_t m;
1939         struct netent *np;
1940 
1941         if (isdigit(*netname)) {
1942                 addr = inet_network(netname);
1943         } else {
1944                 np = getnetbyname(netname);
1945                 if (np == NULL)
1946                         pr_err("net %s not known", netname);
1947                 addr = np->n_net;
1948         }
1949 
1950         /*
1951          * Left justify the address and figure
1952          * out a mask based on the supplied address.
1953          * Set the mask according to the number of zero
1954          * low-order bytes.
1955          * Note: this works only for whole octet masks.
1956          */
1957         if (addr) {
1958                 while ((addr & ~mask) != 0) {
1959                         mask |= (mask >> 8);
1960                 }
1961         }
1962 
1963         emitop(OP_OFFSET_LINK);
1964         switch (which) {
1965         case TO:
1966                 compare_value_mask(16, 4, addr, mask);
1967                 break;
1968         case FROM:
1969                 compare_value_mask(12, 4, addr, mask);
1970                 break;
1971         case ANY:
1972                 compare_value_mask(12, 4, addr, mask);
1973                 emitop(OP_BRTR);
1974                 m = chain(0);
1975                 compare_value_mask(16, 4, addr, mask);
1976                 resolve_chain(m);
1977                 break;
1978         }
1979         emitop(OP_OFFSET_POP);
1980 }
1981 
1982 /*
1983  * Match either a UDP or TCP port number.
1984  * The port number may be provided either as
1985  * port name as listed in /etc/services ("nntp") or as
1986  * the port number itself (2049).
1987  */
1988 static void
1989 port_match(enum direction which, char *portname)
1990 {
1991         struct servent *sp;
1992         uint_t m, port;
1993 
1994         if (isdigit(*portname)) {
1995                 port = atoi(portname);
1996         } else {
1997                 sp = getservbyname(portname, NULL);
1998                 if (sp == NULL)
1999                         pr_err("invalid port number or name: %s", portname);
2000                 port = ntohs(sp->s_port);
2001         }
2002 
2003         emitop(OP_OFFSET_IP);
2004 
2005         switch (which) {
2006         case TO:
2007                 compare_value(2, 2, port);
2008                 break;
2009         case FROM:
2010                 compare_value(0, 2, port);
2011                 break;
2012         case ANY:
2013                 compare_value(2, 2, port);
2014                 emitop(OP_BRTR);
2015                 m = chain(0);
2016                 compare_value(0, 2, port);
2017                 resolve_chain(m);
2018                 break;
2019         }
2020         emitop(OP_OFFSET_POP);
2021 }
2022 
2023 /*
2024  * Generate code to match packets with a specific
2025  * RPC program number.  If the progname is a name
2026  * it is converted to a number via /etc/rpc.
2027  * The program version and/or procedure may be provided
2028  * as extra qualifiers.
2029  */
2030 static void
2031 rpc_match_prog(enum direction which, char *progname, int vers, int proc)
2032 {
2033         struct rpcent *rpc;
2034         uint_t prog;
2035         uint_t m, n;
2036 
2037         if (isdigit(*progname)) {
2038                 prog = atoi(progname);
2039         } else {
2040                 rpc = (struct rpcent *)getrpcbyname(progname);
2041                 if (rpc == NULL)
2042                         pr_err("invalid program name: %s", progname);
2043                 prog = rpc->r_number;
2044         }
2045 
2046         emitop(OP_OFFSET_RPC);
2047         emitop(OP_BRFL);
2048         n = chain(0);
2049 
2050         compare_value(12, 4, prog);
2051         emitop(OP_BRFL);
2052         m = chain(0);
2053         if (vers >= 0) {
2054                 compare_value(16, 4, vers);
2055                 emitop(OP_BRFL);
2056                 m = chain(m);
2057         }
2058         if (proc >= 0) {
2059                 compare_value(20, 4, proc);
2060                 emitop(OP_BRFL);
2061                 m = chain(m);
2062         }
2063 
2064         switch (which) {
2065         case TO:
2066                 compare_value(4, 4, CALL);
2067                 emitop(OP_BRFL);
2068                 m = chain(m);
2069                 break;
2070         case FROM:
2071                 compare_value(4, 4, REPLY);
2072                 emitop(OP_BRFL);
2073                 m = chain(m);
2074                 break;
2075         }
2076         resolve_chain(m);
2077         resolve_chain(n);
2078         emitop(OP_OFFSET_POP);
2079 }
2080 
2081 /*
2082  * Generate code to parse a field specification
2083  * and load the value of the field from the packet
2084  * onto the operand stack.
2085  * The field offset may be specified relative to the
2086  * beginning of the ether header, IP header, UDP header,
2087  * or TCP header.  An optional size specification may
2088  * be provided following a colon.  If no size is given
2089  * one byte is assumed e.g.
2090  *
2091  *      ether[0]        The first byte of the ether header
2092  *      ip[2:2]         The second 16 bit field of the IP header
2093  */
2094 static void
2095 load_field()
2096 {
2097         int size = 1;
2098         int s;
2099 
2100 
2101         if (EQ("ether"))
2102                 emitop(OP_OFFSET_ZERO);
2103         else if (EQ("ip") || EQ("ip6") || EQ("pppoed") || EQ("pppoes"))
2104                 emitop(OP_OFFSET_LINK);
2105         else if (EQ("udp") || EQ("tcp") || EQ("icmp") || EQ("ip-in-ip") ||
2106             EQ("ah") || EQ("esp"))
2107                 emitop(OP_OFFSET_IP);
2108         else
2109                 pr_err("invalid field type");
2110         next();
2111         s = opstack;
2112         expression();
2113         if (opstack != s + 1)
2114                 pr_err("invalid field offset");
2115         opstack--;
2116         if (*token == ':') {
2117                 next();
2118                 if (tokentype != NUMBER)
2119                         pr_err("field size expected");
2120                 size = tokenval;
2121                 if (size != 1 && size != 2 && size != 4)
2122                         pr_err("field size invalid");
2123                 next();
2124         }
2125         if (*token != ']')
2126                 pr_err("right bracket expected");
2127 
2128         load_value(-1, size);
2129         emitop(OP_OFFSET_POP);
2130 }
2131 
2132 /*
2133  * Check that the operand stack
2134  * contains n arguments
2135  */
2136 static void
2137 checkstack(int numargs)
2138 {
2139         if (opstack != numargs)
2140                 pr_err("invalid expression at \"%s\".", token);
2141 }
2142 
2143 static void
2144 primary()
2145 {
2146         int m, m2, s;
2147 
2148         for (;;) {
2149                 if (tokentype == FIELD) {
2150                         load_field();
2151                         opstack++;
2152                         next();
2153                         break;
2154                 }
2155 
2156                 if (comparison(token)) {
2157                         opstack++;
2158                         next();
2159                         break;
2160                 }
2161 
2162                 if (EQ("not") || EQ("!")) {
2163                         next();
2164                         s = opstack;
2165                         primary();
2166                         checkstack(s + 1);
2167                         emitop(OP_NOT);
2168                         break;
2169                 }
2170 
2171                 if (EQ("(")) {
2172                         next();
2173                         s = opstack;
2174                         expression();
2175                         checkstack(s + 1);
2176                         if (!EQ(")"))
2177                                 pr_err("right paren expected");
2178                         next();
2179                 }
2180 
2181                 if (EQ("to") || EQ("dst")) {
2182                         dir = TO;
2183                         next();
2184                         continue;
2185                 }
2186 
2187                 if (EQ("from") || EQ("src")) {
2188                         dir = FROM;
2189                         next();
2190                         continue;
2191                 }
2192 
2193                 if (EQ("ether")) {
2194                         eaddr = 1;
2195                         next();
2196                         continue;
2197                 }
2198 
2199                 if (EQ("proto")) {
2200                         next();
2201                         if (tokentype != NUMBER)
2202                                 pr_err("IP proto type expected");
2203                         emitop(OP_OFFSET_LINK);
2204                         compare_value(IPV4_TYPE_HEADER_OFFSET, 1, tokenval);
2205                         emitop(OP_OFFSET_POP);
2206                         opstack++;
2207                         next();
2208                         continue;
2209                 }
2210 
2211                 if (EQ("broadcast")) {
2212                         /*
2213                          * Be tricky: FDDI ether dst address begins at
2214                          * byte one.  Since the address is really six
2215                          * bytes long, this works for FDDI & ethernet.
2216                          * XXX - Token ring?
2217                          */
2218                         emitop(OP_OFFSET_ZERO);
2219                         if (interface->mac_type == DL_IB)
2220                                 pr_err("filter option unsupported on media");
2221                         compare_value(1, 4, 0xffffffff);
2222                         emitop(OP_OFFSET_POP);
2223                         opstack++;
2224                         next();
2225                         break;
2226                 }
2227 
2228                 if (EQ("multicast")) {
2229                         /* XXX Token ring? */
2230                         emitop(OP_OFFSET_ZERO);
2231                         if (interface->mac_type == DL_FDDI) {
2232                                 compare_value_mask(1, 1, 0x01, 0x01);
2233                         } else if (interface->mac_type == DL_IB) {
2234                                 pr_err("filter option unsupported on media");
2235                         } else {
2236                                 compare_value_mask(0, 1, 0x01, 0x01);
2237                         }
2238                         emitop(OP_OFFSET_POP);
2239                         opstack++;
2240                         next();
2241                         break;
2242                 }
2243 
2244                 if (EQ("decnet")) {
2245                         /* XXX Token ring? */
2246                         if (interface->mac_type == DL_FDDI) {
2247                                 load_value(19, 2);      /* ether type */
2248                                 load_const(0x6000);
2249                                 emitop(OP_GE);
2250                                 emitop(OP_BRFL);
2251                                 m = chain(0);
2252                                 load_value(19, 2);      /* ether type */
2253                                 load_const(0x6009);
2254                                 emitop(OP_LE);
2255                                 resolve_chain(m);
2256                         } else {
2257                                 emitop(OP_OFFSET_ETHERTYPE);
2258                                 load_value(0, 2);       /* ether type */
2259                                 load_const(0x6000);
2260                                 emitop(OP_GE);
2261                                 emitop(OP_BRFL);
2262                                 m = chain(0);
2263                                 load_value(0, 2);       /* ether type */
2264                                 load_const(0x6009);
2265                                 emitop(OP_LE);
2266                                 resolve_chain(m);
2267                                 emitop(OP_OFFSET_POP);
2268                         }
2269                         opstack++;
2270                         next();
2271                         break;
2272                 }
2273 
2274                 if (EQ("vlan-id")) {
2275                         next();
2276                         if (tokentype != NUMBER)
2277                                 pr_err("vlan id expected");
2278                         emitop(OP_OFFSET_ZERO);
2279                         ethertype_match(ETHERTYPE_VLAN);
2280                         emitop(OP_BRFL);
2281                         m = chain(0);
2282                         compare_value_mask(VLAN_ID_OFFSET, 2, tokenval,
2283                             VLAN_ID_MASK);
2284                         resolve_chain(m);
2285                         emitop(OP_OFFSET_POP);
2286                         opstack++;
2287                         next();
2288                         break;
2289                 }
2290 
2291                 if (EQ("apple")) {
2292                         /*
2293                          * Appletalk also appears in 802.2
2294                          * packets, so check for the ethertypes
2295                          * at offset 12 and 20 in the MAC header.
2296                          */
2297                         ethertype_match(ETHERTYPE_AT);
2298                         emitop(OP_BRTR);
2299                         m = chain(0);
2300                         ethertype_match(ETHERTYPE_AARP);
2301                         emitop(OP_BRTR);
2302                         m = chain(m);
2303                         compare_value(20, 2, ETHERTYPE_AT); /* 802.2 */
2304                         emitop(OP_BRTR);
2305                         m = chain(m);
2306                         compare_value(20, 2, ETHERTYPE_AARP); /* 802.2 */
2307                         resolve_chain(m);
2308                         opstack++;
2309                         next();
2310                         break;
2311                 }
2312 
2313                 if (EQ("vlan")) {
2314                         ethertype_match(ETHERTYPE_VLAN);
2315                         compare_value_mask(VLAN_ID_OFFSET, 2, 0, VLAN_ID_MASK);
2316                         emitop(OP_NOT);
2317                         emitop(OP_AND);
2318                         opstack++;
2319                         next();
2320                         break;
2321                 }
2322 
2323                 if (EQ("bootp") || EQ("dhcp")) {
2324                         ethertype_match(interface->network_type_ip);
2325                         emitop(OP_BRFL);
2326                         m = chain(0);
2327                         emitop(OP_OFFSET_LINK);
2328                         compare_value(9, 1, IPPROTO_UDP);
2329                         emitop(OP_OFFSET_POP);
2330                         emitop(OP_BRFL);
2331                         m = chain(m);
2332                         emitop(OP_OFFSET_IP);
2333                         compare_value(0, 4,
2334                             (IPPORT_BOOTPS << 16) | IPPORT_BOOTPC);
2335                         emitop(OP_BRTR);
2336                         m2 = chain(0);
2337                         compare_value(0, 4,
2338                             (IPPORT_BOOTPC << 16) | IPPORT_BOOTPS);
2339                         resolve_chain(m2);
2340                         emitop(OP_OFFSET_POP);
2341                         resolve_chain(m);
2342                         opstack++;
2343                         dir = ANY;
2344                         next();
2345                         break;
2346                 }
2347 
2348                 if (EQ("dhcp6")) {
2349                         ethertype_match(interface->network_type_ipv6);
2350                         emitop(OP_BRFL);
2351                         m = chain(0);
2352                         emitop(OP_OFFSET_LINK);
2353                         compare_value(6, 1, IPPROTO_UDP);
2354                         emitop(OP_OFFSET_POP);
2355                         emitop(OP_BRFL);
2356                         m = chain(m);
2357                         emitop(OP_OFFSET_IP);
2358                         compare_value(2, 2, IPPORT_DHCPV6S);
2359                         emitop(OP_BRTR);
2360                         m2 = chain(0);
2361                         compare_value(2, 2, IPPORT_DHCPV6C);
2362                         resolve_chain(m2);
2363                         emitop(OP_OFFSET_POP);
2364                         resolve_chain(m);
2365                         opstack++;
2366                         dir = ANY;
2367                         next();
2368                         break;
2369                 }
2370 
2371                 if (EQ("ethertype")) {
2372                         next();
2373                         if (tokentype != NUMBER)
2374                                 pr_err("ether type expected");
2375                         ethertype_match(tokenval);
2376                         opstack++;
2377                         next();
2378                         break;
2379                 }
2380 
2381                 if (EQ("pppoe")) {
2382                         ethertype_match(ETHERTYPE_PPPOED);
2383                         ethertype_match(ETHERTYPE_PPPOES);
2384                         emitop(OP_OR);
2385                         opstack++;
2386                         next();
2387                         break;
2388                 }
2389 
2390                 if (EQ("inet")) {
2391                         next();
2392                         if (EQ("host"))
2393                                 next();
2394                         if (tokentype != ALPHA && tokentype != ADDR_IP)
2395                                 pr_err("host/IPv4 addr expected after inet");
2396                         ipaddr_match(dir, token, IPV4_ONLY);
2397                         opstack++;
2398                         next();
2399                         break;
2400                 }
2401 
2402                 if (EQ("inet6")) {
2403                         next();
2404                         if (EQ("host"))
2405                                 next();
2406                         if (tokentype != ALPHA && tokentype != ADDR_IP6)
2407                                 pr_err("host/IPv6 addr expected after inet6");
2408                         ipaddr_match(dir, token, IPV6_ONLY);
2409                         opstack++;
2410                         next();
2411                         break;
2412                 }
2413 
2414                 if (EQ("length")) {
2415                         emitop(OP_LOAD_LENGTH);
2416                         opstack++;
2417                         next();
2418                         break;
2419                 }
2420 
2421                 if (EQ("less")) {
2422                         next();
2423                         if (tokentype != NUMBER)
2424                                 pr_err("packet length expected");
2425                         emitop(OP_LOAD_LENGTH);
2426                         load_const(tokenval);
2427                         emitop(OP_LT);
2428                         opstack++;
2429                         next();
2430                         break;
2431                 }
2432 
2433                 if (EQ("greater")) {
2434                         next();
2435                         if (tokentype != NUMBER)
2436                                 pr_err("packet length expected");
2437                         emitop(OP_LOAD_LENGTH);
2438                         load_const(tokenval);
2439                         emitop(OP_GT);
2440                         opstack++;
2441                         next();
2442                         break;
2443                 }
2444 
2445                 if (EQ("nofrag")) {
2446                         emitop(OP_OFFSET_LINK);
2447                         compare_value_mask(6, 2, 0, 0x1fff);
2448                         emitop(OP_OFFSET_POP);
2449                         emitop(OP_BRFL);
2450                         m = chain(0);
2451                         ethertype_match(interface->network_type_ip);
2452                         resolve_chain(m);
2453                         opstack++;
2454                         next();
2455                         break;
2456                 }
2457 
2458                 if (EQ("net") || EQ("dstnet") || EQ("srcnet")) {
2459                         if (EQ("dstnet"))
2460                                 dir = TO;
2461                         else if (EQ("srcnet"))
2462                                 dir = FROM;
2463                         next();
2464                         netaddr_match(dir, token);
2465                         dir = ANY;
2466                         opstack++;
2467                         next();
2468                         break;
2469                 }
2470 
2471                 if (EQ("port") || EQ("srcport") || EQ("dstport")) {
2472                         if (EQ("dstport"))
2473                                 dir = TO;
2474                         else if (EQ("srcport"))
2475                                 dir = FROM;
2476                         next();
2477                         port_match(dir, token);
2478                         dir = ANY;
2479                         opstack++;
2480                         next();
2481                         break;
2482                 }
2483 
2484                 if (EQ("rpc")) {
2485                         uint_t vers, proc;
2486                         char savetoken[32];
2487 
2488                         vers = proc = -1;
2489                         next();
2490                         (void) strlcpy(savetoken, token, sizeof (savetoken));
2491                         next();
2492                         if (*token == ',') {
2493                                 next();
2494                                 if (tokentype != NUMBER)
2495                                         pr_err("version number expected");
2496                                 vers = tokenval;
2497                                 next();
2498                         }
2499                         if (*token == ',') {
2500                                 next();
2501                                 if (tokentype != NUMBER)
2502                                         pr_err("proc number expected");
2503                                 proc = tokenval;
2504                                 next();
2505                         }
2506                         rpc_match_prog(dir, savetoken, vers, proc);
2507                         dir = ANY;
2508                         opstack++;
2509                         break;
2510                 }
2511 
2512                 if (EQ("slp")) {
2513                         /* filter out TCP handshakes */
2514                         emitop(OP_OFFSET_LINK);
2515                         compare_value(9, 1, IPPROTO_TCP);
2516                         emitop(OP_LOAD_CONST);
2517                         emitval(52);
2518                         emitop(OP_LOAD_CONST);
2519                         emitval(2);
2520                         emitop(OP_LOAD_SHORT);
2521                         emitop(OP_GE);
2522                         emitop(OP_AND); /* proto == TCP && len < 52 */
2523                         emitop(OP_NOT);
2524                         emitop(OP_BRFL); /* pkt too short to be a SLP call */
2525                         m = chain(0);
2526 
2527                         emitop(OP_OFFSET_POP);
2528                         emitop(OP_OFFSET_SLP);
2529                         resolve_chain(m);
2530                         opstack++;
2531                         next();
2532                         break;
2533                 }
2534 
2535                 if (EQ("ldap")) {
2536                         dir = ANY;
2537                         port_match(dir, "ldap");
2538                         opstack++;
2539                         next();
2540                         break;
2541                 }
2542 
2543                 if (EQ("and") || EQ("or")) {
2544                         break;
2545                 }
2546 
2547                 if (EQ("zone")) {
2548                         next();
2549                         if (tokentype != NUMBER)
2550                                 pr_err("zoneid expected");
2551                         zone_match(dir, BE_32((uint32_t)(tokenval)));
2552                         opstack++;
2553                         next();
2554                         break;
2555                 }
2556 
2557                 if (EQ("gateway")) {
2558                         next();
2559                         if (eaddr || tokentype != ALPHA)
2560                                 pr_err("hostname required: %s", token);
2561                         etheraddr_match(dir, token);
2562                         dir = ANY;
2563                         emitop(OP_BRFL);
2564                         m = chain(0);
2565                         ipaddr_match(dir, token, IPV4_AND_IPV6);
2566                         emitop(OP_NOT);
2567                         resolve_chain(m);
2568                         opstack++;
2569                         next();
2570                 }
2571 
2572                 if (EQ("host") || EQ("between") ||
2573                     tokentype == ALPHA ||       /* assume its a hostname */
2574                     tokentype == ADDR_IP ||
2575                     tokentype == ADDR_IP6 ||
2576                     tokentype == ADDR_AT ||
2577                     tokentype == ADDR_ETHER) {
2578                         if (EQ("host") || EQ("between"))
2579                                 next();
2580                         if (eaddr || tokentype == ADDR_ETHER) {
2581                                 etheraddr_match(dir, token);
2582                         } else if (tokentype == ALPHA) {
2583                                 ipaddr_match(dir, token, IPV4_AND_IPV6);
2584                         } else if (tokentype == ADDR_AT) {
2585                                 ataddr_match(dir, token);
2586                         } else if (tokentype == ADDR_IP) {
2587                                 ipaddr_match(dir, token, IPV4_ONLY);
2588                         } else {
2589                                 ipaddr_match(dir, token, IPV6_ONLY);
2590                         }
2591                         dir = ANY;
2592                         eaddr = 0;
2593                         opstack++;
2594                         next();
2595                         break;
2596                 }
2597 
2598                 if (tokentype == NUMBER) {
2599                         load_const(tokenval);
2600                         opstack++;
2601                         next();
2602                         break;
2603                 }
2604 
2605                 break;  /* unknown token */
2606         }
2607 }
2608 
2609 struct optable {
2610         char *op_tok;
2611         enum optype op_type;
2612 };
2613 
2614 static struct optable
2615 mulops[] = {
2616         "*",    OP_MUL,
2617         "/",    OP_DIV,
2618         "%",    OP_REM,
2619         "&",        OP_AND,
2620         "",     OP_STOP,
2621 };
2622 
2623 static struct optable
2624 addops[] = {
2625         "+",    OP_ADD,
2626         "-",    OP_SUB,
2627         "|",    OP_OR,
2628         "^",    OP_XOR,
2629         "",     OP_STOP,
2630 };
2631 
2632 static struct optable
2633 compareops[] = {
2634         "==",   OP_EQ,
2635         "=",    OP_EQ,
2636         "!=",   OP_NE,
2637         ">", OP_GT,
2638         ">=",        OP_GE,
2639         "<", OP_LT,
2640         "<=",        OP_LE,
2641         "",     OP_STOP,
2642 };
2643 
2644 /*
2645  * Using the table, find the operator
2646  * that corresponds to the token.
2647  * Return 0 if not found.
2648  */
2649 static int
2650 find_op(char *tok, struct optable *table)
2651 {
2652         struct optable *op;
2653 
2654         for (op = table; *op->op_tok; op++) {
2655                 if (strcmp(tok, op->op_tok) == 0)
2656                         return (op->op_type);
2657         }
2658 
2659         return (0);
2660 }
2661 
2662 static void
2663 expr_mul()
2664 {
2665         int op;
2666         int s = opstack;
2667 
2668         primary();
2669         while (op = find_op(token, mulops)) {
2670                 next();
2671                 primary();
2672                 checkstack(s + 2);
2673                 emitop(op);
2674                 opstack--;
2675         }
2676 }
2677 
2678 static void
2679 expr_add()
2680 {
2681         int op, s = opstack;
2682 
2683         expr_mul();
2684         while (op = find_op(token, addops)) {
2685                 next();
2686                 expr_mul();
2687                 checkstack(s + 2);
2688                 emitop(op);
2689                 opstack--;
2690         }
2691 }
2692 
2693 static void
2694 expr_compare()
2695 {
2696         int op, s = opstack;
2697 
2698         expr_add();
2699         while (op = find_op(token, compareops)) {
2700                 next();
2701                 expr_add();
2702                 checkstack(s + 2);
2703                 emitop(op);
2704                 opstack--;
2705         }
2706 }
2707 
2708 /*
2709  * Alternation ("and") is difficult because
2710  * an implied "and" is acknowledge between
2711  * two adjacent primaries.  Just keep calling
2712  * the lower-level expression routine until
2713  * no value is added to the opstack.
2714  */
2715 static void
2716 alternation()
2717 {
2718         int m = 0;
2719         int s = opstack;
2720 
2721         expr_compare();
2722         checkstack(s + 1);
2723         for (;;) {
2724                 if (EQ("and"))
2725                         next();
2726                 emitop(OP_BRFL);
2727                 m = chain(m);
2728                 expr_compare();
2729                 if (opstack != s + 2)
2730                         break;
2731                 opstack--;
2732         }
2733         unemit(2);
2734         resolve_chain(m);
2735 }
2736 
2737 static void
2738 expression()
2739 {
2740         int m = 0;
2741         int s = opstack;
2742 
2743         alternation();
2744         while (EQ("or") || EQ(",")) {
2745                 emitop(OP_BRTR);
2746                 m = chain(m);
2747                 next();
2748                 alternation();
2749                 checkstack(s + 2);
2750                 opstack--;
2751         }
2752         resolve_chain(m);
2753 }
2754 
2755 /*
2756  * Take n args from the argv list
2757  * and concatenate them into a single string.
2758  */
2759 char *
2760 concat_args(char **argv, int argc)
2761 {
2762         int i, len;
2763         char *str, *p;
2764 
2765         /* First add the lengths of all the strings */
2766         len = 0;
2767         for (i = 0; i < argc; i++)
2768                 len += strlen(argv[i]) + 1;
2769 
2770         /* allocate the big string */
2771         str = (char *)malloc(len);
2772         if (str == NULL)
2773                 pr_err("no mem");
2774 
2775         p = str;
2776 
2777         /*
2778          * Concat the strings into the big
2779          * string using a space as separator
2780          */
2781         for (i = 0; i < argc; i++) {
2782                 strcpy(p, argv[i]);
2783                 p += strlen(p);
2784                 *p++ = ' ';
2785         }
2786         *--p = '\0';
2787 
2788         return (str);
2789 }
2790 
2791 /*
2792  * Take the expression in the string "expr"
2793  * and compile it into the code array.
2794  * Print the generated code if the print
2795  * arg is set.
2796  */
2797 void
2798 compile(char *expr, int print)
2799 {
2800         expr = strdup(expr);
2801         if (expr == NULL)
2802                 pr_err("no mem");
2803         curr_op = oplist;
2804         tkp = expr;
2805         dir = ANY;
2806 
2807         next();
2808         if (tokentype != EOL)
2809                 expression();
2810         emitop(OP_STOP);
2811         if (tokentype != EOL)
2812                 pr_err("invalid expression");
2813         optimize(oplist);
2814         if (print)
2815                 codeprint();
2816 }
2817 
2818 /*
2819  * Lookup hostname in the arp cache.
2820  */
2821 boolean_t
2822 arp_for_ether(char *hostname, struct ether_addr *ep)
2823 {
2824         struct arpreq ar;
2825         struct hostent *hp;
2826         struct sockaddr_in *sin;
2827         int error_num;
2828         int s;
2829 
2830         memset(&ar, 0, sizeof (ar));
2831         sin = (struct sockaddr_in *)&ar.arp_pa;
2832         sin->sin_family = AF_INET;
2833         hp = getipnodebyname(hostname, AF_INET, 0, &error_num);
2834         if (hp == NULL) {
2835                 return (B_FALSE);
2836         }
2837         memcpy(&sin->sin_addr, hp->h_addr, sizeof (sin->sin_addr));
2838         s = socket(AF_INET, SOCK_DGRAM, 0);
2839         if (s < 0) {
2840                 return (B_FALSE);
2841         }
2842         if (ioctl(s, SIOCGARP, &ar) < 0) {
2843                 close(s);
2844                 return (B_FALSE);
2845         }
2846         close(s);
2847         memcpy(ep->ether_addr_octet, ar.arp_ha.sa_data, sizeof (*ep));
2848         return (B_TRUE);
2849 }