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 1817 /* 1818 * Left justify the address and figure 1819 * out a mask based on the supplied address. 1820 * Set the mask according to the number of zero 1821 * low-order bytes. 1822 * Note: this works only for whole octet masks. 1823 */ 1824 if (addr) { 1825 while ((addr & ~mask) != 0) { 1826 mask |= (mask >> 8); 1827 } 1828 } 1829 1830 emitop(OP_OFFSET_LINK); 1831 switch (which) { 1832 case TO: 1833 compare_value_mask(16, 4, addr, mask); 1834 break; 1835 case FROM: 1836 compare_value_mask(12, 4, addr, mask); 1837 break; 1838 case ANY: 1839 compare_value_mask(12, 4, addr, mask); 1840 emitop(OP_BRTR); 1841 m = chain(0); 1842 compare_value_mask(16, 4, addr, mask); 1843 resolve_chain(m); 1844 break; 1845 } 1846 emitop(OP_OFFSET_POP); 1847 } 1848 1849 /* 1850 * Match either a UDP or TCP port number. 1851 * The port number may be provided either as 1852 * port name as listed in /etc/services ("nntp") or as 1853 * the port number itself (2049). 1854 */ 1855 static void 1856 port_match(enum direction which, char *portname) 1857 { 1858 struct servent *sp; 1859 uint_t m, port; 1860 1861 if (isdigit(*portname)) { 1862 port = atoi(portname); 1863 } else { 1864 sp = getservbyname(portname, NULL); 1865 if (sp == NULL) 1866 pr_err("invalid port number or name: %s", 1867 portname); 1868 port = ntohs(sp->s_port); 1869 } 1870 1871 emitop(OP_OFFSET_IP); 1872 1873 switch (which) { 1874 case TO: 1875 compare_value(2, 2, port); 1876 break; 1877 case FROM: 1878 compare_value(0, 2, port); 1879 break; 1880 case ANY: 1881 compare_value(2, 2, port); 1882 emitop(OP_BRTR); 1883 m = chain(0); 1884 compare_value(0, 2, port); 1885 resolve_chain(m); 1886 break; 1887 } 1888 emitop(OP_OFFSET_POP); 1889 } 1890 1891 /* 1892 * Generate code to match packets with a specific 1893 * RPC program number. If the progname is a name 1894 * it is converted to a number via /etc/rpc. 1895 * The program version and/or procedure may be provided 1896 * as extra qualifiers. 1897 */ 1898 static void 1899 rpc_match_prog(enum direction which, char *progname, int vers, int proc) 1900 { 1901 struct rpcent *rpc; 1902 uint_t prog; 1903 uint_t m, n; 1904 1905 if (isdigit(*progname)) { 1906 prog = atoi(progname); 1907 } else { 1908 rpc = (struct rpcent *)getrpcbyname(progname); 1909 if (rpc == NULL) 1910 pr_err("invalid program name: %s", progname); 1911 prog = rpc->r_number; 1912 } 1913 1914 emitop(OP_OFFSET_RPC); 1915 emitop(OP_BRFL); 1916 n = chain(0); 1917 1918 compare_value(12, 4, prog); 1919 emitop(OP_BRFL); 1920 m = chain(0); 1921 if (vers >= 0) { 1922 compare_value(16, 4, vers); 1923 emitop(OP_BRFL); 1924 m = chain(m); 1925 } 1926 if (proc >= 0) { 1927 compare_value(20, 4, proc); 1928 emitop(OP_BRFL); 1929 m = chain(m); 1930 } 1931 1932 switch (which) { 1933 case TO: 1934 compare_value(4, 4, CALL); 1935 emitop(OP_BRFL); 1936 m = chain(m); 1937 break; 1938 case FROM: 1939 compare_value(4, 4, REPLY); 1940 emitop(OP_BRFL); 1941 m = chain(m); 1942 break; 1943 } 1944 resolve_chain(m); 1945 resolve_chain(n); 1946 emitop(OP_OFFSET_POP); 1947 } 1948 1949 /* 1950 * Generate code to parse a field specification 1951 * and load the value of the field from the packet 1952 * onto the operand stack. 1953 * The field offset may be specified relative to the 1954 * beginning of the ether header, IP header, UDP header, 1955 * or TCP header. An optional size specification may 1956 * be provided following a colon. If no size is given 1957 * one byte is assumed e.g. 1958 * 1959 * ether[0] The first byte of the ether header 1960 * ip[2:2] The second 16 bit field of the IP header 1961 */ 1962 static void 1963 load_field() 1964 { 1965 int size = 1; 1966 int s; 1967 1968 1969 if (EQ("ether")) 1970 emitop(OP_OFFSET_ZERO); 1971 else if (EQ("ip") || EQ("ip6") || EQ("pppoed") || EQ("pppoes")) 1972 emitop(OP_OFFSET_LINK); 1973 else if (EQ("udp") || EQ("tcp") || EQ("icmp") || EQ("ip-in-ip") || 1974 EQ("ah") || EQ("esp")) 1975 emitop(OP_OFFSET_IP); 1976 else 1977 pr_err("invalid field type"); 1978 next(); 1979 s = opstack; 1980 expression(); 1981 if (opstack != s + 1) 1982 pr_err("invalid field offset"); 1983 opstack--; 1984 if (*token == ':') { 1985 next(); 1986 if (tokentype != NUMBER) 1987 pr_err("field size expected"); 1988 size = tokenval; 1989 if (size != 1 && size != 2 && size != 4) 1990 pr_err("field size invalid"); 1991 next(); 1992 } 1993 if (*token != ']') 1994 pr_err("right bracket expected"); 1995 1996 load_value(-1, size); 1997 emitop(OP_OFFSET_POP); 1998 } 1999 2000 /* 2001 * Check that the operand stack 2002 * contains n arguments 2003 */ 2004 static void 2005 checkstack(int numargs) 2006 { 2007 if (opstack != numargs) 2008 pr_err("invalid expression at \"%s\".", token); 2009 } 2010 2011 static void 2012 primary() 2013 { 2014 int m, s; 2015 2016 for (;;) { 2017 if (tokentype == FIELD) { 2018 load_field(); 2019 opstack++; 2020 next(); 2021 break; 2022 } 2023 2024 if (comparison(token)) { 2025 opstack++; 2026 next(); 2027 break; 2028 } 2029 2030 if (EQ("not") || EQ("!")) { 2031 next(); 2032 s = opstack; 2033 primary(); 2034 checkstack(s + 1); 2035 emitop(OP_NOT); 2036 break; 2037 } 2038 2039 if (EQ("(")) { 2040 next(); 2041 s = opstack; 2042 expression(); 2043 checkstack(s + 1); 2044 if (!EQ(")")) 2045 pr_err("right paren expected"); 2046 next(); 2047 } 2048 2049 if (EQ("to") || EQ("dst")) { 2050 dir = TO; 2051 next(); 2052 continue; 2053 } 2054 2055 if (EQ("from") || EQ("src")) { 2056 dir = FROM; 2057 next(); 2058 continue; 2059 } 2060 2061 if (EQ("ether")) { 2062 eaddr = 1; 2063 next(); 2064 continue; 2065 } 2066 2067 if (EQ("proto")) { /* ignore */ 2068 next(); 2069 continue; 2070 } 2071 2072 if (EQ("broadcast")) { 2073 /* 2074 * Be tricky: FDDI ether dst address begins at 2075 * byte one. Since the address is really six 2076 * bytes long, this works for FDDI & ethernet. 2077 * XXX - Token ring? 2078 */ 2079 if (interface->mac_type == DL_IB) 2080 pr_err("filter option unsupported on media"); 2081 compare_value(1, 4, 0xffffffff); 2082 opstack++; 2083 next(); 2084 break; 2085 } 2086 2087 if (EQ("multicast")) { 2088 /* XXX Token ring? */ 2089 if (interface->mac_type == DL_FDDI) { 2090 compare_value_mask(1, 1, 0x01, 0x01); 2091 } else if (interface->mac_type == DL_IB) { 2092 pr_err("filter option unsupported on media"); 2093 } else { 2094 compare_value_mask(0, 1, 0x01, 0x01); 2095 } 2096 opstack++; 2097 next(); 2098 break; 2099 } 2100 2101 if (EQ("decnet")) { 2102 /* XXX Token ring? */ 2103 if (interface->mac_type == DL_FDDI) { 2104 load_value(19, 2); /* ether type */ 2105 load_const(0x6000); 2106 emitop(OP_GE); 2107 emitop(OP_BRFL); 2108 m = chain(0); 2109 load_value(19, 2); /* ether type */ 2110 load_const(0x6009); 2111 emitop(OP_LE); 2112 resolve_chain(m); 2113 } else { 2114 load_value(12, 2); /* ether type */ 2115 load_const(0x6000); 2116 emitop(OP_GE); 2117 emitop(OP_BRFL); 2118 m = chain(0); 2119 load_value(12, 2); /* ether type */ 2120 load_const(0x6009); 2121 emitop(OP_LE); 2122 resolve_chain(m); 2123 } 2124 opstack++; 2125 next(); 2126 break; 2127 } 2128 2129 if (EQ("apple")) { 2130 /* 2131 * Appletalk also appears in 802.2 2132 * packets, so check for the ethertypes 2133 * at offset 12 and 20 in the MAC header. 2134 */ 2135 ethertype_match(ETHERTYPE_AT); 2136 emitop(OP_BRTR); 2137 m = chain(0); 2138 ethertype_match(ETHERTYPE_AARP); 2139 emitop(OP_BRTR); 2140 m = chain(m); 2141 compare_value(20, 2, ETHERTYPE_AT); /* 802.2 */ 2142 emitop(OP_BRTR); 2143 m = chain(m); 2144 compare_value(20, 2, ETHERTYPE_AARP); /* 802.2 */ 2145 resolve_chain(m); 2146 opstack++; 2147 next(); 2148 break; 2149 } 2150 2151 if (EQ("bootp") || EQ("dhcp")) { 2152 emitop(OP_OFFSET_LINK); 2153 emitop(OP_LOAD_CONST); 2154 emitval(9); 2155 emitop(OP_LOAD_OCTET); 2156 emitop(OP_LOAD_CONST); 2157 emitval(IPPROTO_UDP); 2158 emitop(OP_OFFSET_IP); 2159 compare_value(0, 4, 2160 (IPPORT_BOOTPS << 16 | IPPORT_BOOTPC)); 2161 emitop(OP_BRTR); 2162 m = chain(0); 2163 compare_value(0, 4, 2164 (IPPORT_BOOTPC << 16 | IPPORT_BOOTPS)); 2165 resolve_chain(m); 2166 opstack++; 2167 dir = ANY; 2168 next(); 2169 break; 2170 } 2171 2172 if (EQ("ethertype")) { 2173 next(); 2174 if (tokentype != NUMBER) 2175 pr_err("ether type expected"); 2176 ethertype_match(tokenval); 2177 opstack++; 2178 next(); 2179 break; 2180 } 2181 2182 if (EQ("pppoe")) { 2183 ethertype_match(ETHERTYPE_PPPOED); 2184 ethertype_match(ETHERTYPE_PPPOES); 2185 emitop(OP_OR); 2186 opstack++; 2187 next(); 2188 break; 2189 } 2190 2191 if (EQ("inet")) { 2192 next(); 2193 if (EQ("host")) 2194 next(); 2195 if (tokentype != ALPHA && tokentype != ADDR_IP) 2196 pr_err("host/IPv4 addr expected after inet"); 2197 ipaddr_match(dir, token, IPV4_ONLY); 2198 opstack++; 2199 next(); 2200 break; 2201 } 2202 2203 if (EQ("inet6")) { 2204 next(); 2205 if (EQ("host")) 2206 next(); 2207 if (tokentype != ALPHA && tokentype != ADDR_IP6) 2208 pr_err("host/IPv6 addr expected after inet6"); 2209 ipaddr_match(dir, token, IPV6_ONLY); 2210 opstack++; 2211 next(); 2212 break; 2213 } 2214 2215 if (EQ("length")) { 2216 emitop(OP_LOAD_LENGTH); 2217 opstack++; 2218 next(); 2219 break; 2220 } 2221 2222 if (EQ("less")) { 2223 next(); 2224 if (tokentype != NUMBER) 2225 pr_err("packet length expected"); 2226 emitop(OP_LOAD_LENGTH); 2227 load_const(tokenval); 2228 emitop(OP_LT); 2229 opstack++; 2230 next(); 2231 break; 2232 } 2233 2234 if (EQ("greater")) { 2235 next(); 2236 if (tokentype != NUMBER) 2237 pr_err("packet length expected"); 2238 emitop(OP_LOAD_LENGTH); 2239 load_const(tokenval); 2240 emitop(OP_GT); 2241 opstack++; 2242 next(); 2243 break; 2244 } 2245 2246 if (EQ("nofrag")) { 2247 emitop(OP_OFFSET_LINK); 2248 compare_value_mask(6, 2, 0, 0x1fff); 2249 emitop(OP_OFFSET_POP); 2250 emitop(OP_BRFL); 2251 m = chain(0); 2252 ethertype_match(ETHERTYPE_IP); 2253 resolve_chain(m); 2254 opstack++; 2255 next(); 2256 break; 2257 } 2258 2259 if (EQ("net") || EQ("dstnet") || EQ("srcnet")) { 2260 if (EQ("dstnet")) 2261 dir = TO; 2262 else if (EQ("srcnet")) 2263 dir = FROM; 2264 next(); 2265 netaddr_match(dir, token); 2266 dir = ANY; 2267 opstack++; 2268 next(); 2269 break; 2270 } 2271 2272 if (EQ("port") || EQ("srcport") || EQ("dstport")) { 2273 if (EQ("dstport")) 2274 dir = TO; 2275 else if (EQ("srcport")) 2276 dir = FROM; 2277 next(); 2278 port_match(dir, token); 2279 dir = ANY; 2280 opstack++; 2281 next(); 2282 break; 2283 } 2284 2285 if (EQ("rpc")) { 2286 uint_t vers, proc; 2287 char savetoken[32]; 2288 2289 vers = proc = -1; 2290 next(); 2291 (void) strlcpy(savetoken, token, sizeof (savetoken)); 2292 next(); 2293 if (*token == ',') { 2294 next(); 2295 if (tokentype != NUMBER) 2296 pr_err("version number expected"); 2297 vers = tokenval; 2298 next(); 2299 } 2300 if (*token == ',') { 2301 next(); 2302 if (tokentype != NUMBER) 2303 pr_err("proc number expected"); 2304 proc = tokenval; 2305 next(); 2306 } 2307 rpc_match_prog(dir, savetoken, vers, proc); 2308 dir = ANY; 2309 opstack++; 2310 break; 2311 } 2312 2313 if (EQ("slp")) { 2314 /* filter out TCP handshakes */ 2315 emitop(OP_OFFSET_LINK); 2316 compare_value(9, 1, IPPROTO_TCP); 2317 emitop(OP_LOAD_CONST); 2318 emitval(52); 2319 emitop(OP_LOAD_CONST); 2320 emitval(2); 2321 emitop(OP_LOAD_SHORT); 2322 emitop(OP_GE); 2323 emitop(OP_AND); /* proto == TCP && len < 52 */ 2324 emitop(OP_NOT); 2325 emitop(OP_BRFL); /* pkt too short to be a SLP call */ 2326 m = chain(0); 2327 2328 emitop(OP_OFFSET_POP); 2329 emitop(OP_OFFSET_SLP); 2330 resolve_chain(m); 2331 opstack++; 2332 next(); 2333 break; 2334 } 2335 2336 if (EQ("ldap")) { 2337 dir = ANY; 2338 port_match(dir, "ldap"); 2339 opstack++; 2340 next(); 2341 break; 2342 } 2343 2344 if (EQ("and") || EQ("or")) { 2345 break; 2346 } 2347 2348 if (EQ("gateway")) { 2349 next(); 2350 if (eaddr || tokentype != ALPHA) 2351 pr_err("hostname required: %s", token); 2352 etheraddr_match(dir, token); 2353 dir = ANY; 2354 emitop(OP_BRFL); 2355 m = chain(0); 2356 ipaddr_match(dir, token, IPV4_AND_IPV6); 2357 emitop(OP_NOT); 2358 resolve_chain(m); 2359 opstack++; 2360 next(); 2361 } 2362 2363 if (EQ("host") || EQ("between") || 2364 tokentype == ALPHA || /* assume its a hostname */ 2365 tokentype == ADDR_IP || 2366 tokentype == ADDR_IP6 || 2367 tokentype == ADDR_AT || 2368 tokentype == ADDR_ETHER) { 2369 if (EQ("host") || EQ("between")) 2370 next(); 2371 if (eaddr || tokentype == ADDR_ETHER) { 2372 etheraddr_match(dir, token); 2373 } else if (tokentype == ALPHA) { 2374 ipaddr_match(dir, token, IPV4_AND_IPV6); 2375 } else if (tokentype == ADDR_AT) { 2376 ataddr_match(dir, token); 2377 } else if (tokentype == ADDR_IP) { 2378 ipaddr_match(dir, token, IPV4_ONLY); 2379 } else { 2380 ipaddr_match(dir, token, IPV6_ONLY); 2381 } 2382 dir = ANY; 2383 eaddr = 0; 2384 opstack++; 2385 next(); 2386 break; 2387 } 2388 2389 if (tokentype == NUMBER) { 2390 load_const(tokenval); 2391 opstack++; 2392 next(); 2393 break; 2394 } 2395 2396 break; /* unknown token */ 2397 } 2398 } 2399 2400 struct optable { 2401 char *op_tok; 2402 enum optype op_type; 2403 }; 2404 2405 static struct optable 2406 mulops[] = { 2407 "*", OP_MUL, 2408 "/", OP_DIV, 2409 "%", OP_REM, 2410 "&", OP_AND, 2411 "", OP_STOP, 2412 }; 2413 2414 static struct optable 2415 addops[] = { 2416 "+", OP_ADD, 2417 "-", OP_SUB, 2418 "|", OP_OR, 2419 "^", OP_XOR, 2420 "", OP_STOP, 2421 }; 2422 2423 static struct optable 2424 compareops[] = { 2425 "==", OP_EQ, 2426 "=", OP_EQ, 2427 "!=", OP_NE, 2428 ">", OP_GT, 2429 ">=", OP_GE, 2430 "<", OP_LT, 2431 "<=", OP_LE, 2432 "", OP_STOP, 2433 }; 2434 2435 /* 2436 * Using the table, find the operator 2437 * that corresponds to the token. 2438 * Return 0 if not found. 2439 */ 2440 static int 2441 find_op(char *tok, struct optable *table) 2442 { 2443 struct optable *op; 2444 2445 for (op = table; *op->op_tok; op++) { 2446 if (strcmp(tok, op->op_tok) == 0) 2447 return (op->op_type); 2448 } 2449 2450 return (0); 2451 } 2452 2453 static void 2454 expr_mul() 2455 { 2456 int op; 2457 int s = opstack; 2458 2459 primary(); 2460 while (op = find_op(token, mulops)) { 2461 next(); 2462 primary(); 2463 checkstack(s + 2); 2464 emitop(op); 2465 opstack--; 2466 } 2467 } 2468 2469 static void 2470 expr_add() 2471 { 2472 int op, s = opstack; 2473 2474 expr_mul(); 2475 while (op = find_op(token, addops)) { 2476 next(); 2477 expr_mul(); 2478 checkstack(s + 2); 2479 emitop(op); 2480 opstack--; 2481 } 2482 } 2483 2484 static void 2485 expr_compare() 2486 { 2487 int op, s = opstack; 2488 2489 expr_add(); 2490 while (op = find_op(token, compareops)) { 2491 next(); 2492 expr_add(); 2493 checkstack(s + 2); 2494 emitop(op); 2495 opstack--; 2496 } 2497 } 2498 2499 /* 2500 * Alternation ("and") is difficult because 2501 * an implied "and" is acknowledge between 2502 * two adjacent primaries. Just keep calling 2503 * the lower-level expression routine until 2504 * no value is added to the opstack. 2505 */ 2506 static void 2507 alternation() 2508 { 2509 int m = 0; 2510 int s = opstack; 2511 2512 expr_compare(); 2513 checkstack(s + 1); 2514 for (;;) { 2515 if (EQ("and")) 2516 next(); 2517 emitop(OP_BRFL); 2518 m = chain(m); 2519 expr_compare(); 2520 if (opstack != s + 2) 2521 break; 2522 opstack--; 2523 } 2524 unemit(2); 2525 resolve_chain(m); 2526 } 2527 2528 static void 2529 expression() 2530 { 2531 int m = 0; 2532 int s = opstack; 2533 2534 alternation(); 2535 while (EQ("or") || EQ(",")) { 2536 emitop(OP_BRTR); 2537 m = chain(m); 2538 next(); 2539 alternation(); 2540 checkstack(s + 2); 2541 opstack--; 2542 } 2543 resolve_chain(m); 2544 } 2545 2546 /* 2547 * Take n args from the argv list 2548 * and concatenate them into a single string. 2549 */ 2550 char * 2551 concat_args(char **argv, int argc) 2552 { 2553 int i, len; 2554 char *str, *p; 2555 2556 /* First add the lengths of all the strings */ 2557 len = 0; 2558 for (i = 0; i < argc; i++) 2559 len += strlen(argv[i]) + 1; 2560 2561 /* allocate the big string */ 2562 str = (char *)malloc(len); 2563 if (str == NULL) 2564 pr_err("no mem"); 2565 2566 p = str; 2567 2568 /* 2569 * Concat the strings into the big 2570 * string using a space as separator 2571 */ 2572 for (i = 0; i < argc; i++) { 2573 strcpy(p, argv[i]); 2574 p += strlen(p); 2575 *p++ = ' '; 2576 } 2577 *--p = '\0'; 2578 2579 return (str); 2580 } 2581 2582 /* 2583 * Take the expression in the string "expr" 2584 * and compile it into the code array. 2585 * Print the generated code if the print 2586 * arg is set. 2587 */ 2588 void 2589 compile(char *expr, int print) 2590 { 2591 expr = strdup(expr); 2592 if (expr == NULL) 2593 pr_err("no mem"); 2594 curr_op = oplist; 2595 tkp = expr; 2596 dir = ANY; 2597 2598 next(); 2599 if (tokentype != EOL) 2600 expression(); 2601 emitop(OP_STOP); 2602 if (tokentype != EOL) 2603 pr_err("invalid expression"); 2604 optimize(oplist); 2605 if (print) 2606 codeprint(); 2607 } 2608 2609 /* 2610 * Lookup hostname in the arp cache. 2611 */ 2612 boolean_t 2613 arp_for_ether(char *hostname, struct ether_addr *ep) 2614 { 2615 struct arpreq ar; 2616 struct hostent *hp; 2617 struct sockaddr_in *sin; 2618 int error_num; 2619 int s; 2620 2621 memset(&ar, 0, sizeof (ar)); 2622 sin = (struct sockaddr_in *)&ar.arp_pa; 2623 sin->sin_family = AF_INET; 2624 hp = getipnodebyname(hostname, AF_INET, 0, &error_num); 2625 if (hp == NULL) { 2626 return (B_FALSE); 2627 } 2628 memcpy(&sin->sin_addr, hp->h_addr, sizeof (sin->sin_addr)); 2629 s = socket(AF_INET, SOCK_DGRAM, 0); 2630 if (s < 0) { 2631 return (B_FALSE); 2632 } 2633 if (ioctl(s, SIOCGARP, &ar) < 0) { 2634 close(s); 2635 return (B_FALSE); 2636 } 2637 close(s); 2638 memcpy(ep->ether_addr_octet, ar.arp_ha.sa_data, sizeof (*ep)); 2639 return (B_TRUE); 2640 } 2641