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