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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1991-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" /* SunOS */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <ctype.h> 32 #include <string.h> 33 #include <fcntl.h> 34 #include <string.h> 35 #include <sys/types.h> 36 #include <sys/time.h> 37 #include <stddef.h> 38 39 #include <sys/socket.h> 40 #include <sys/sockio.h> 41 #include <net/if.h> 42 #include <netinet/in_systm.h> 43 #include <netinet/in.h> 44 #include <netinet/ip.h> 45 #include <netinet/ip6.h> 46 #include <inet/ip6.h> 47 #include <inet/ip.h> 48 #include <netinet/if_ether.h> 49 #include <netinet/tcp.h> 50 #include <netinet/udp.h> 51 #include <netdb.h> 52 #include <arpa/inet.h> 53 #include <rpc/rpc.h> 54 #include <rpc/rpcent.h> 55 56 #include <sys/dlpi.h> 57 #include <snoop.h> 58 59 #define IPV4_ONLY 0 60 #define IPV6_ONLY 1 61 #define IPV4_AND_IPV6 2 62 63 /* 64 * The following constants represent the offsets in bytes from the beginning 65 * of the IP(v6) header of the source and destination IP(v6) addresses. 66 * These are useful when generating filter code. 67 */ 68 #define IPV4_SRCADDR_OFFSET 12 69 #define IPV4_DSTADDR_OFFSET 16 70 #define IPV6_SRCADDR_OFFSET 8 71 #define IPV6_DSTADDR_OFFSET 24 72 #define IP_VERS(p) (((*(uchar_t *)p) & 0xf0) >> 4) 73 #define MASKED_IPV4_VERS 0x40 74 #define MASKED_IPV6_VERS 0x60 75 #define IP_HDR_LEN(p) (((*(uchar_t *)p) & 0xf) * 4) 76 #define TCP_HDR_LEN(p) ((((*((uchar_t *)p+12)) >> 4) & 0xf) * 4) 77 /* 78 * Coding the constant below is tacky, but the compiler won't let us 79 * be more clever. E.g., &((struct ip *)0)->ip_xxx 80 */ 81 #define IP_PROTO_OF(p) (((uchar_t *)p)[9]) 82 83 /* 84 * AppleTalk uses 802.2 Ethernet encapsulation with LLC/SNAP headers, 85 * for 8 octets of overhead, and the common AppleTalk DDP Ethernet 86 * header is another 4 octets. 87 * 88 * The following constants represents the offsets in bytes from the beginning 89 * of the Ethernet payload to various parts of the DDP header. 90 */ 91 92 #define AT_DST_NET_OFFSET 12 93 #define AT_SRC_NET_OFFSET 14 94 #define AT_DST_NODE_OFFSET 16 95 #define AT_SRC_NODE_OFFSET 17 96 97 int eaddr; /* need ethernet addr */ 98 99 int opstack; /* operand stack depth */ 100 101 /* 102 * These are the operators of the user-level filter. 103 * STOP ends execution of the filter expression and 104 * returns the truth value at the top of the stack. 105 * OP_LOAD_OCTET, OP_LOAD_SHORT and OP_LOAD_LONG pop 106 * an offset value from the stack and load a value of 107 * an appropriate size from the packet (octet, short or 108 * long). The offset is computed from a base value that 109 * may be set via the OP_OFFSET operators. 110 * OP_EQ, OP_NE, OP_GT, OP_GE, OP_LT, OP_LE pop two values 111 * from the stack and return the result of their comparison. 112 * OP_AND, OP_OR, OP_XOR pop two values from the stack and 113 * do perform a bitwise operation on them - returning a result 114 * to the stack. OP_NOT inverts the bits of the value on the 115 * stack. 116 * OP_BRFL and OP_BRTR branch to an offset in the code array 117 * depending on the value at the top of the stack: true (not 0) 118 * or false (0). 119 * OP_ADD, OP_SUB, OP_MUL, OP_DIV and OP_REM pop two values 120 * from the stack and perform arithmetic. 121 * The OP_OFFSET operators change the base from which the 122 * OP_LOAD operators compute their offsets. 123 * OP_OFFSET_ZERO sets the offset to zero - beginning of packet. 124 * OP_OFFSET_LINK sets the base to the first octet after 125 * the link (DLC) header. OP_OFFSET_IP, OP_OFFSET_TCP, 126 * and OP_OFFSET_UDP do the same for those headers - they 127 * set the offset base to the *end* of the header - not the 128 * beginning. The OP_OFFSET_RPC operator is a bit unusual. 129 * It points the base at the cached RPC header. For the 130 * purposes of selection, RPC reply headers look like call 131 * headers except for the direction value. 132 * OP_OFFSET_POP restores the offset base to the value prior 133 * to the most recent OP_OFFSET call. 134 */ 135 enum optype { 136 OP_STOP = 0, 137 OP_LOAD_OCTET, 138 OP_LOAD_SHORT, 139 OP_LOAD_LONG, 140 OP_LOAD_CONST, 141 OP_LOAD_LENGTH, 142 OP_EQ, 143 OP_NE, 144 OP_GT, 145 OP_GE, 146 OP_LT, 147 OP_LE, 148 OP_AND, 149 OP_OR, 150 OP_XOR, 151 OP_NOT, 152 OP_BRFL, 153 OP_BRTR, 154 OP_ADD, 155 OP_SUB, 156 OP_MUL, 157 OP_DIV, 158 OP_REM, 159 OP_OFFSET_POP, 160 OP_OFFSET_ZERO, 161 OP_OFFSET_LINK, 162 OP_OFFSET_IP, 163 OP_OFFSET_TCP, 164 OP_OFFSET_UDP, 165 OP_OFFSET_RPC, 166 OP_OFFSET_SLP, 167 OP_LAST 168 }; 169 170 static char *opnames[] = { 171 "STOP", 172 "LOAD_OCTET", 173 "LOAD_SHORT", 174 "LOAD_LONG", 175 "LOAD_CONST", 176 "LOAD_LENGTH", 177 "EQ", 178 "NE", 179 "GT", 180 "GE", 181 "LT", 182 "LE", 183 "AND", 184 "OR", 185 "XOR", 186 "NOT", 187 "BRFL", 188 "BRTR", 189 "ADD", 190 "SUB", 191 "MUL", 192 "DIV", 193 "REM", 194 "OFFSET_POP", 195 "OFFSET_ZERO", 196 "OFFSET_ETHER", 197 "OFFSET_IP", 198 "OFFSET_TCP", 199 "OFFSET_UDP", 200 "OFFSET_RPC", 201 "OP_OFFSET_SLP", 202 "" 203 }; 204 205 #define MAXOPS 1024 206 #define MAXSS 64 207 static uint_t oplist[MAXOPS]; /* array of operators */ 208 static uint_t *curr_op; /* last op generated */ 209 210 extern int valid_slp(uchar_t *, int); /* decides if a SLP msg is valid */ 211 extern struct hostent *lgetipnodebyname(const char *, int, int, int *); 212 213 static void alternation(); 214 static uint_t chain(); 215 static void codeprint(); 216 static void emitop(); 217 static void emitval(); 218 static void expression(); 219 static struct xid_entry *find_rpc(); 220 static void optimize(); 221 static void ethertype_match(); 222 223 224 /* 225 * Returns the ULP for an IPv4 or IPv6 packet 226 * Assumes that the packet has already been checked to verify 227 * that it's either IPv4 or IPv6 228 * 229 * XXX Will need to be updated for AH and ESP 230 * XXX when IPsec is supported for v6. 231 */ 232 static uchar_t 233 ip_proto_of(uchar_t *ip) 234 { 235 uchar_t nxt; 236 boolean_t not_done = B_TRUE; 237 uchar_t *ptr = ip; 238 239 switch (IP_VERS(ip)) { 240 case IPV4_VERSION: 241 return (IP_PROTO_OF(ip)); 242 case IPV6_VERSION: 243 244 nxt = ip[6]; 245 ptr += 40; /* size of ip6 header */ 246 do { 247 switch (nxt) { 248 /* 249 * XXX Add IPsec headers here when supported for v6 250 * XXX (the AH will have a different size...) 251 */ 252 case IPPROTO_HOPOPTS: 253 case IPPROTO_ROUTING: 254 case IPPROTO_FRAGMENT: 255 case IPPROTO_DSTOPTS: 256 ptr += (8 * (ptr[1] + 1)); 257 nxt = *ptr; 258 break; 259 260 default: 261 not_done = B_FALSE; 262 break; 263 } 264 } while (not_done); 265 return (nxt); 266 default: 267 break; /* shouldn't get here... */ 268 } 269 return (0); 270 } 271 272 /* 273 * Returns the total IP header length. 274 * For v4, this includes any options present. 275 * For v6, this is the length of the IPv6 header plus 276 * any extension headers present. 277 * 278 * XXX Will need to be updated for AH and ESP 279 * XXX when IPsec is supported for v6. 280 */ 281 static int 282 ip_hdr_len(uchar_t *ip) 283 { 284 uchar_t nxt; 285 int hdr_len; 286 boolean_t not_done = B_TRUE; 287 int len = 40; /* IPv6 header size */ 288 uchar_t *ptr = ip; 289 290 switch (IP_VERS(ip)) { 291 case IPV4_VERSION: 292 return (IP_HDR_LEN(ip)); 293 case IPV6_VERSION: 294 nxt = ip[6]; 295 ptr += len; 296 do { 297 switch (nxt) { 298 /* 299 * XXX Add IPsec headers here when supported for v6 300 * XXX (the AH will have a different size...) 301 */ 302 case IPPROTO_HOPOPTS: 303 case IPPROTO_ROUTING: 304 case IPPROTO_FRAGMENT: 305 case IPPROTO_DSTOPTS: 306 hdr_len = (8 * (ptr[1] + 1)); 307 len += hdr_len; 308 ptr += hdr_len; 309 nxt = *ptr; 310 break; 311 312 default: 313 not_done = B_FALSE; 314 break; 315 } 316 } while (not_done); 317 return (len); 318 default: 319 break; 320 } 321 return (0); /* not IP */ 322 } 323 324 static void 325 codeprint() 326 { 327 uint_t *op; 328 329 printf("User filter:\n"); 330 331 for (op = oplist; *op; op++) { 332 if (*op <= OP_LAST) 333 printf("\t%2d: %s\n", op - oplist, opnames[*op]); 334 else 335 printf("\t%2d: (%d)\n", op - oplist, *op); 336 337 switch (*op) { 338 case OP_LOAD_CONST: 339 case OP_BRTR: 340 case OP_BRFL: 341 op++; 342 if ((int)*op < 0) 343 printf("\t%2d: 0x%08x (%d)\n", 344 op - oplist, *op, *op); 345 else 346 printf("\t%2d: %d (0x%08x)\n", 347 op - oplist, *op, *op); 348 } 349 } 350 printf("\t%2d: STOP\n", op - oplist); 351 printf("\n"); 352 } 353 354 355 /* 356 * Take a pass through the generated code and optimize 357 * branches. A branch true (BRTR) that has another BRTR 358 * at its destination can use the address of the destination 359 * BRTR. A BRTR that points to a BRFL (branch false) should 360 * point to the address following the BRFL. 361 * A similar optimization applies to BRFL operators. 362 */ 363 static void 364 optimize(uint_t *oplistp) 365 { 366 uint_t *op; 367 368 for (op = oplistp; *op; op++) { 369 switch (*op) { 370 case OP_LOAD_CONST: 371 op++; 372 break; 373 case OP_BRTR: 374 op++; 375 optimize(&oplist[*op]); 376 if (oplist[*op] == OP_BRFL) 377 *op += 2; 378 else if (oplist[*op] == OP_BRTR) 379 *op = oplist[*op + 1]; 380 break; 381 case OP_BRFL: 382 op++; 383 optimize(&oplist[*op]); 384 if (oplist[*op] == OP_BRTR) 385 *op += 2; 386 else if (oplist[*op] == OP_BRFL) 387 *op = oplist[*op + 1]; 388 break; 389 } 390 } 391 } 392 393 /* 394 * RPC packets are tough to filter. 395 * While the call packet has all the interesting 396 * info: program number, version, procedure etc, 397 * the reply packet has none of this information. 398 * If we want to do useful filtering based on this 399 * information then we have to stash the information 400 * from the call packet, and use the XID in the reply 401 * to find the stashed info. The stashed info is 402 * kept in a circular lifo, assuming that a call packet 403 * will be followed quickly by its reply. 404 */ 405 406 struct xid_entry { 407 unsigned x_xid; /* The XID (32 bits) */ 408 unsigned x_dir; /* CALL or REPLY */ 409 unsigned x_rpcvers; /* Protocol version (2) */ 410 unsigned x_prog; /* RPC program number */ 411 unsigned x_vers; /* RPC version number */ 412 unsigned x_proc; /* RPC procedure number */ 413 }; 414 static struct xid_entry xe_table[XID_CACHE_SIZE]; 415 static struct xid_entry *xe_first = &xe_table[0]; 416 static struct xid_entry *xe = &xe_table[0]; 417 static struct xid_entry *xe_last = &xe_table[XID_CACHE_SIZE - 1]; 418 419 static struct xid_entry * 420 find_rpc(struct rpc_msg *rpc) 421 { 422 struct xid_entry *x; 423 424 for (x = xe; x >= xe_first; x--) 425 if (x->x_xid == rpc->rm_xid) 426 return (x); 427 for (x = xe_last; x > xe; x--) 428 if (x->x_xid == rpc->rm_xid) 429 return (x); 430 return (NULL); 431 } 432 433 static void 434 stash_rpc(struct rpc_msg *rpc) 435 { 436 struct xid_entry *x; 437 438 if (find_rpc(rpc)) 439 return; 440 441 x = xe++; 442 if (xe > xe_last) 443 xe = xe_first; 444 x->x_xid = rpc->rm_xid; 445 x->x_dir = htonl(REPLY); 446 x->x_prog = rpc->rm_call.cb_prog; 447 x->x_vers = rpc->rm_call.cb_vers; 448 x->x_proc = rpc->rm_call.cb_proc; 449 } 450 451 /* 452 * SLP can multicast requests, and recieve unicast replies in which 453 * neither the source nor destination port is identifiable as a SLP 454 * port. Hence, we need to do as RPC does, and keep track of packets we 455 * are interested in. For SLP, however, we use ports, not XIDs, and 456 * a smaller cache size is more efficient since every incoming packet 457 * needs to be checked. 458 */ 459 460 #define SLP_CACHE_SIZE 64 461 static uint_t slp_table[SLP_CACHE_SIZE]; 462 static int slp_index = 0; 463 464 /* 465 * Returns the index of dport in the table if found, otherwise -1. 466 */ 467 static int 468 find_slp(uint_t dport) { 469 int i; 470 471 if (!dport) 472 return (0); 473 474 for (i = slp_index; i >= 0; i--) 475 if (slp_table[i] == dport) { 476 return (i); 477 } 478 for (i = SLP_CACHE_SIZE - 1; i > slp_index; i--) 479 if (slp_table[i] == dport) { 480 return (i); 481 } 482 return (-1); 483 } 484 485 static void stash_slp(uint_t sport) { 486 if (slp_table[slp_index - 1] == sport) 487 /* avoid redundancy due to multicast retransmissions */ 488 return; 489 490 slp_table[slp_index++] = sport; 491 if (slp_index == SLP_CACHE_SIZE) 492 slp_index = 0; 493 } 494 495 /* 496 * This routine takes a packet and returns true or false 497 * according to whether the filter expression selects it 498 * or not. 499 * We assume here that offsets for short and long values 500 * are even - we may die with an alignment error if the 501 * CPU doesn't support odd addresses. Note that long 502 * values are loaded as two shorts so that 32 bit word 503 * alignment isn't important. 504 * 505 * IPv6 is a bit stickier to handle than IPv4... 506 */ 507 508 int 509 want_packet(uchar_t *pkt, int len, int origlen) 510 { 511 uint_t stack[MAXSS]; /* operand stack */ 512 uint_t *op; /* current operator */ 513 uint_t *sp; /* top of operand stack */ 514 uchar_t *base; /* base for offsets into packet */ 515 uchar_t *ip; /* addr of IP header, unaligned */ 516 uchar_t *tcp; /* addr of TCP header, unaligned */ 517 uchar_t *udp; /* addr of UDP header, unaligned */ 518 struct rpc_msg rpcmsg; /* addr of RPC header */ 519 struct rpc_msg *rpc; 520 int newrpc = 0; 521 uchar_t *slphdr; /* beginning of SLP header */ 522 uint_t slp_sport, slp_dport; 523 int off, header_size; 524 uchar_t *offstack[MAXSS]; /* offset stack */ 525 uchar_t **offp; /* current offset */ 526 uchar_t *opkt = NULL; 527 uint_t olen; 528 529 sp = stack; 530 *sp = 1; 531 base = pkt; 532 offp = offstack; 533 534 header_size = (*interface->header_len)((char *)pkt); 535 536 for (op = oplist; *op; op++) { 537 switch ((enum optype) *op) { 538 case OP_LOAD_OCTET: 539 if ((base + *sp) > (pkt + len)) 540 return (0); /* packet too short */ 541 542 *sp = *((uchar_t *)(base + *sp)); 543 break; 544 case OP_LOAD_SHORT: 545 off = *sp; 546 547 if ((base + off + sizeof (uint16_t) - 1) > (pkt + len)) 548 return (0); /* packet too short */ 549 550 /* 551 * Handle 2 possible alignments 552 */ 553 switch ((((unsigned)base)+off) % sizeof (ushort_t)) { 554 case 0: 555 *sp = ntohs(*((ushort_t *)(base + *sp))); 556 break; 557 case 1: 558 *((uchar_t *)(sp)) = 559 *((uchar_t *)(base + off)); 560 *(((uchar_t *)sp) + 1) = 561 *((uchar_t *)(base + off) + 1); 562 *sp = ntohs(*(ushort_t *)sp); 563 break; 564 } 565 break; 566 case OP_LOAD_LONG: 567 off = *sp; 568 569 if ((base + off + sizeof (uint32_t) - 1) > (pkt + len)) 570 return (0); /* packet too short */ 571 572 /* 573 * Handle 3 possible alignments 574 */ 575 switch ((((unsigned)base) + off) % sizeof (uint_t)) { 576 case 0: 577 *sp = *(uint_t *)(base + off); 578 break; 579 580 case 2: 581 *((ushort_t *)(sp)) = 582 *((ushort_t *)(base + off)); 583 *(((ushort_t *)sp) + 1) = 584 *((ushort_t *)(base + off) + 1); 585 break; 586 587 case 1: 588 case 3: 589 *((uchar_t *)(sp)) = 590 *((uchar_t *)(base + off)); 591 *(((uchar_t *)sp) + 1) = 592 *((uchar_t *)(base + off) + 1); 593 *(((uchar_t *)sp) + 2) = 594 *((uchar_t *)(base + off) + 2); 595 *(((uchar_t *)sp) + 3) = 596 *((uchar_t *)(base + off) + 3); 597 break; 598 } 599 *sp = ntohl(*sp); 600 break; 601 case OP_LOAD_CONST: 602 if (sp >= &stack[MAXSS]) 603 return (0); 604 *(++sp) = *(++op); 605 break; 606 case OP_LOAD_LENGTH: 607 if (sp >= &stack[MAXSS]) 608 return (0); 609 *(++sp) = origlen; 610 break; 611 case OP_EQ: 612 if (sp < &stack[1]) 613 return (0); 614 sp--; 615 *sp = *sp == *(sp + 1); 616 break; 617 case OP_NE: 618 if (sp < &stack[1]) 619 return (0); 620 sp--; 621 *sp = *sp != *(sp + 1); 622 break; 623 case OP_GT: 624 if (sp < &stack[1]) 625 return (0); 626 sp--; 627 *sp = *sp > *(sp + 1); 628 break; 629 case OP_GE: 630 if (sp < &stack[1]) 631 return (0); 632 sp--; 633 *sp = *sp >= *(sp + 1); 634 break; 635 case OP_LT: 636 if (sp < &stack[1]) 637 return (0); 638 sp--; 639 *sp = *sp < *(sp + 1); 640 break; 641 case OP_LE: 642 if (sp < &stack[1]) 643 return (0); 644 sp--; 645 *sp = *sp <= *(sp + 1); 646 break; 647 case OP_AND: 648 if (sp < &stack[1]) 649 return (0); 650 sp--; 651 *sp &= *(sp + 1); 652 break; 653 case OP_OR: 654 if (sp < &stack[1]) 655 return (0); 656 sp--; 657 *sp |= *(sp + 1); 658 break; 659 case OP_XOR: 660 if (sp < &stack[1]) 661 return (0); 662 sp--; 663 *sp ^= *(sp + 1); 664 break; 665 case OP_NOT: 666 *sp = !*sp; 667 break; 668 case OP_BRFL: 669 op++; 670 if (!*sp) 671 op = &oplist[*op] - 1; 672 break; 673 case OP_BRTR: 674 op++; 675 if (*sp) 676 op = &oplist[*op] - 1; 677 break; 678 case OP_ADD: 679 if (sp < &stack[1]) 680 return (0); 681 sp--; 682 *sp += *(sp + 1); 683 break; 684 case OP_SUB: 685 if (sp < &stack[1]) 686 return (0); 687 sp--; 688 *sp -= *(sp + 1); 689 break; 690 case OP_MUL: 691 if (sp < &stack[1]) 692 return (0); 693 sp--; 694 *sp *= *(sp + 1); 695 break; 696 case OP_DIV: 697 if (sp < &stack[1]) 698 return (0); 699 sp--; 700 *sp /= *(sp + 1); 701 break; 702 case OP_REM: 703 if (sp < &stack[1]) 704 return (0); 705 sp--; 706 *sp %= *(sp + 1); 707 break; 708 case OP_OFFSET_POP: 709 if (offp < &offstack[0]) 710 return (0); 711 base = *offp--; 712 if (opkt != NULL) { 713 pkt = opkt; 714 len = olen; 715 opkt = NULL; 716 } 717 break; 718 case OP_OFFSET_ZERO: 719 if (offp >= &offstack[MAXSS]) 720 return (0); 721 *++offp = base; 722 base = pkt; 723 break; 724 case OP_OFFSET_LINK: 725 if (offp >= &offstack[MAXSS]) 726 return (0); 727 *++offp = base; 728 base = pkt + header_size; 729 /* 730 * If the offset exceeds the packet length, 731 * we should not be interested in this packet... 732 * Just return 0. 733 */ 734 if (base > pkt + len) { 735 return (0); 736 } 737 break; 738 case OP_OFFSET_IP: 739 if (offp >= &offstack[MAXSS]) 740 return (0); 741 *++offp = base; 742 ip = pkt + header_size; 743 base = ip + ip_hdr_len(ip); 744 if (base == ip) { 745 return (0); /* not IP */ 746 } 747 if (base > pkt + len) { 748 return (0); /* bad pkt */ 749 } 750 break; 751 case OP_OFFSET_TCP: 752 if (offp >= &offstack[MAXSS]) 753 return (0); 754 *++offp = base; 755 ip = pkt + header_size; 756 tcp = ip + ip_hdr_len(ip); 757 if (tcp == ip) { 758 return (0); /* not IP */ 759 } 760 base = tcp + TCP_HDR_LEN(tcp); 761 if (base > pkt + len) { 762 return (0); 763 } 764 break; 765 case OP_OFFSET_UDP: 766 if (offp >= &offstack[MAXSS]) 767 return (0); 768 *++offp = base; 769 ip = pkt + header_size; 770 udp = ip + ip_hdr_len(ip); 771 if (udp == ip) { 772 return (0); /* not IP */ 773 } 774 base = udp + sizeof (struct udphdr); 775 if (base > pkt + len) { 776 return (0); 777 } 778 break; 779 case OP_OFFSET_RPC: 780 if (offp >= &offstack[MAXSS]) 781 return (0); 782 *++offp = base; 783 ip = pkt + header_size; 784 rpc = NULL; 785 786 if (IP_VERS(ip) != IPV4_VERSION && 787 IP_VERS(ip) != IPV6_VERSION) { 788 if (sp >= &stack[MAXSS]) 789 return (0); 790 *(++sp) = 0; 791 break; 792 } 793 794 switch (ip_proto_of(ip)) { 795 case IPPROTO_UDP: 796 udp = ip + ip_hdr_len(ip); 797 rpc = (struct rpc_msg *)(udp + 798 sizeof (struct udphdr)); 799 break; 800 case IPPROTO_TCP: 801 tcp = ip + ip_hdr_len(ip); 802 /* 803 * Need to skip an extra 4 for the xdr_rec 804 * field. 805 */ 806 rpc = (struct rpc_msg *)(tcp + 807 TCP_HDR_LEN(tcp) + 4); 808 break; 809 } 810 /* 811 * We need to have at least 24 bytes of a RPC 812 * packet to look at to determine the validity 813 * of it. 814 */ 815 if (rpc == NULL || (uchar_t *)rpc + 24 > pkt + len) { 816 if (sp >= &stack[MAXSS]) 817 return (0); 818 *(++sp) = 0; 819 break; 820 } 821 /* align */ 822 (void) memcpy(&rpcmsg, rpc, 24); 823 if (!valid_rpc(&rpcmsg, 24)) { 824 if (sp >= &stack[MAXSS]) 825 return (0); 826 *(++sp) = 0; 827 break; 828 } 829 if (ntohl(rpcmsg.rm_direction) == CALL) { 830 base = (uchar_t *)rpc; 831 newrpc = 1; 832 if (sp >= &stack[MAXSS]) 833 return (0); 834 *(++sp) = 1; 835 } else { 836 opkt = pkt; 837 olen = len; 838 839 pkt = base = (uchar_t *)find_rpc(&rpcmsg); 840 len = sizeof (struct xid_entry); 841 if (sp >= &stack[MAXSS]) 842 return (0); 843 *(++sp) = base != NULL; 844 } 845 break; 846 case OP_OFFSET_SLP: 847 slphdr = NULL; 848 ip = pkt + header_size; 849 850 if (IP_VERS(ip) != IPV4_VERSION && 851 IP_VERS(ip) != IPV6_VERSION) { 852 if (sp >= &stack[MAXSS]) 853 return (0); 854 *(++sp) = 0; 855 break; 856 } 857 858 switch (ip_proto_of(ip)) { 859 struct udphdr udp_h; 860 struct tcphdr tcp_h; 861 case IPPROTO_UDP: 862 udp = ip + ip_hdr_len(ip); 863 /* align */ 864 memcpy(&udp_h, udp, sizeof (udp_h)); 865 slp_sport = ntohs(udp_h.uh_sport); 866 slp_dport = ntohs(udp_h.uh_dport); 867 slphdr = udp + sizeof (struct udphdr); 868 break; 869 case IPPROTO_TCP: 870 tcp = ip + ip_hdr_len(ip); 871 /* align */ 872 memcpy(&tcp_h, tcp, sizeof (tcp_h)); 873 slp_sport = ntohs(tcp_h.th_sport); 874 slp_dport = ntohs(tcp_h.th_dport); 875 slphdr = tcp + TCP_HDR_LEN(tcp); 876 break; 877 } 878 if (slphdr == NULL || slphdr > pkt + len) { 879 if (sp >= &stack[MAXSS]) 880 return (0); 881 *(++sp) = 0; 882 break; 883 } 884 if (slp_sport == 427 || slp_dport == 427) { 885 if (sp >= &stack[MAXSS]) 886 return (0); 887 *(++sp) = 1; 888 if (slp_sport != 427 && slp_dport == 427) 889 stash_slp(slp_sport); 890 break; 891 } else if (find_slp(slp_dport) != -1) { 892 if (valid_slp(slphdr, len)) { 893 if (sp >= &stack[MAXSS]) 894 return (0); 895 *(++sp) = 1; 896 break; 897 } 898 /* else fallthrough to reject */ 899 } 900 if (sp >= &stack[MAXSS]) 901 return (0); 902 *(++sp) = 0; 903 break; 904 } 905 } 906 907 if (*sp && newrpc) 908 stash_rpc(&rpcmsg); 909 910 return (*sp); 911 } 912 913 static void 914 load_const(uint_t constval) 915 { 916 emitop(OP_LOAD_CONST); 917 emitval(constval); 918 } 919 920 static void 921 load_value(int offset, int len) 922 { 923 if (offset >= 0) 924 load_const(offset); 925 926 switch (len) { 927 case 1: 928 emitop(OP_LOAD_OCTET); 929 break; 930 case 2: 931 emitop(OP_LOAD_SHORT); 932 break; 933 case 4: 934 emitop(OP_LOAD_LONG); 935 break; 936 } 937 } 938 939 /* 940 * Emit code to compare a field in 941 * the packet against a constant value. 942 */ 943 static void 944 compare_value(uint_t offset, uint_t len, uint_t val) 945 { 946 load_const(val); 947 load_value(offset, len); 948 emitop(OP_EQ); 949 } 950 951 static void 952 compare_addr_v4(uint_t offset, uint_t len, uint_t val) 953 { 954 load_const(ntohl(val)); 955 load_value(offset, len); 956 emitop(OP_EQ); 957 } 958 959 static void 960 compare_addr_v6(uint_t offset, uint_t len, struct in6_addr val) 961 { 962 int i; 963 uint32_t value; 964 965 for (i = 0; i < len; i += 4) { 966 value = ntohl(*(uint32_t *)&val.s6_addr[i]); 967 load_const(value); 968 load_value(offset + i, 4); 969 emitop(OP_EQ); 970 if (i != 0) 971 emitop(OP_AND); 972 } 973 } 974 975 /* 976 * Same as above except do the comparison 977 * after and'ing a mask value. Useful 978 * for comparing IP network numbers 979 */ 980 static void 981 compare_value_mask(uint_t offset, uint_t len, uint_t val, int mask) 982 { 983 load_value(offset, len); 984 load_const(mask); 985 emitop(OP_AND); 986 load_const(val); 987 emitop(OP_EQ); 988 } 989 990 /* Emit an operator into the code array */ 991 static void 992 emitop(enum optype opcode) 993 { 994 if (curr_op >= &oplist[MAXOPS]) 995 pr_err("expression too long"); 996 *curr_op++ = opcode; 997 } 998 999 /* 1000 * Remove n operators recently emitted into 1001 * the code array. Used by alternation(). 1002 */ 1003 static void 1004 unemit(int numops) 1005 { 1006 curr_op -= numops; 1007 } 1008 1009 1010 /* 1011 * Same as emitop except that we're emitting 1012 * a value that's not an operator. 1013 */ 1014 static void 1015 emitval(uint_t val) 1016 { 1017 if (curr_op >= &oplist[MAXOPS]) 1018 pr_err("expression too long"); 1019 *curr_op++ = val; 1020 } 1021 1022 /* 1023 * Used to chain forward branches together 1024 * for later resolution by resolve_chain(). 1025 */ 1026 static uint_t 1027 chain(int p) 1028 { 1029 uint_t pos = curr_op - oplist; 1030 1031 emitval(p); 1032 return (pos); 1033 } 1034 1035 /* 1036 * Proceed backward through the code array 1037 * following a chain of forward references. 1038 * At each reference install the destination 1039 * branch offset. 1040 */ 1041 static void 1042 resolve_chain(uint_t p) 1043 { 1044 uint_t n; 1045 uint_t pos = curr_op - oplist; 1046 1047 while (p) { 1048 n = oplist[p]; 1049 oplist[p] = pos; 1050 p = n; 1051 } 1052 } 1053 1054 #define EQ(val) (strcmp(token, val) == 0) 1055 1056 char *tkp, *sav_tkp; 1057 char *token; 1058 enum { EOL, ALPHA, NUMBER, FIELD, ADDR_IP, ADDR_ETHER, SPECIAL, 1059 ADDR_IP6, ADDR_AT } tokentype; 1060 uint_t tokenval; 1061 1062 /* 1063 * This is the scanner. Each call returns the next 1064 * token in the filter expression. A token is either: 1065 * EOL: The end of the line - no more tokens. 1066 * ALPHA: A name that begins with a letter and contains 1067 * letters or digits, hyphens or underscores. 1068 * NUMBER: A number. The value can be represented as 1069 * a decimal value (1234) or an octal value 1070 * that begins with zero (066) or a hex value 1071 * that begins with 0x or 0X (0xff). 1072 * FIELD: A name followed by a left square bracket. 1073 * ADDR_IP: An IP address. Any sequence of digits 1074 * separated by dots e.g. 109.104.40.13 1075 * ADDR_ETHER: An ethernet address. Any sequence of hex 1076 * digits separated by colons e.g. 8:0:20:0:76:39 1077 * SPECIAL: A special character e.g. ">" or "(". The scanner 1078 * correctly handles digraphs - two special characters 1079 * that constitute a single token e.g. "==" or ">=". 1080 * ADDR_IP6: An IPv6 address. 1081 * 1082 * ADDR_AT: An AppleTalk Phase II address. A sequence of two numbers 1083 * separated by a dot. 1084 * 1085 * The current token is maintained in "token" and and its 1086 * type in "tokentype". If tokentype is NUMBER then the 1087 * value is held in "tokenval". 1088 */ 1089 1090 static const char *namechars = 1091 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-."; 1092 static const char *numchars = "0123456789abcdefABCDEFXx:."; 1093 1094 void 1095 next() 1096 { 1097 static int savechar; 1098 char *p; 1099 int size, size1; 1100 int base, colons, dots, alphas, double_colon; 1101 1102 colons = 0; 1103 double_colon = 0; 1104 1105 if (*tkp == '\0') { 1106 token = tkp; 1107 *tkp = savechar; 1108 } 1109 1110 sav_tkp = tkp; 1111 1112 while (isspace(*tkp)) tkp++; 1113 token = tkp; 1114 if (*token == '\0') { 1115 tokentype = EOL; 1116 return; 1117 } 1118 1119 /* A token containing ':' cannot be ALPHA type */ 1120 tkp = token + strspn(token, numchars); 1121 for (p = token; p < tkp; p++) { 1122 if (*p == ':') { 1123 colons++; 1124 if (*(p+1) == ':') 1125 double_colon++; 1126 } 1127 } 1128 1129 tkp = token; 1130 if (isalpha(*tkp) && !colons) { 1131 tokentype = ALPHA; 1132 tkp += strspn(tkp, namechars); 1133 if (*tkp == '[') { 1134 tokentype = FIELD; 1135 *tkp++ = '\0'; 1136 } 1137 } else 1138 1139 /* 1140 * RFC1123 states that host names may now start with digits. Need 1141 * to change parser to account for this. Also, need to distinguish 1142 * between 1.2.3.4 and 1.2.3.a where the first case is an IP address 1143 * and the second is a domain name. 333aaa needs to be distinguished 1144 * from 0x333aaa. The first is a host name and the second is a number. 1145 * 1146 * The (colons > 1) conditional differentiates between ethernet 1147 * and IPv6 addresses, and an expression of the form base[expr:size], 1148 * which can only contain one ':' character. 1149 */ 1150 if (isdigit(*tkp) || colons > 1) { 1151 tkp = token + strspn(token, numchars); 1152 dots = alphas = 0; 1153 for (p = token; p < tkp; p++) { 1154 if (*p == '.') 1155 dots++; 1156 else if (isalpha(*p)) 1157 alphas = 1; 1158 } 1159 if (colons > 1) { 1160 if (colons == 5 && double_colon == 0) { 1161 tokentype = ADDR_ETHER; 1162 } else { 1163 tokentype = ADDR_IP6; 1164 } 1165 } else if (dots) { 1166 size = tkp - token; 1167 size1 = strspn(token, "0123456789."); 1168 if (dots == 1 && size == size1) { 1169 tokentype = ADDR_AT; 1170 } else 1171 if (dots != 3 || size != size1) { 1172 tokentype = ALPHA; 1173 if (*tkp != '\0' && !isspace(*tkp)) { 1174 tkp += strspn(tkp, namechars); 1175 if (*tkp == '[') { 1176 tokentype = FIELD; 1177 *tkp++ = '\0'; 1178 } 1179 } 1180 } else 1181 tokentype = ADDR_IP; 1182 } else if (token + strspn(token, namechars) <= tkp) { 1183 /* 1184 * With the above check, if there are more 1185 * characters after the last digit, assume 1186 * that it is not a number. 1187 */ 1188 tokentype = NUMBER; 1189 p = tkp; 1190 tkp = token; 1191 base = 10; 1192 if (*tkp == '0') { 1193 base = 8; 1194 tkp++; 1195 if (*tkp == 'x' || *tkp == 'X') 1196 base = 16; 1197 } 1198 if ((base == 10 || base == 8) && alphas) { 1199 tokentype = ALPHA; 1200 tkp = p; 1201 } else if (base == 16) { 1202 size = 2 + strspn(token+2, 1203 "0123456789abcdefABCDEF"); 1204 size1 = p - token; 1205 if (size != size1) { 1206 tokentype = ALPHA; 1207 tkp = p; 1208 } else 1209 /* 1210 * handles the case of 0x so an error message 1211 * is not printed. Treats 0x as 0. 1212 */ 1213 if (size == 2) { 1214 tokenval = 0; 1215 tkp = token +2; 1216 } else { 1217 tokenval = strtoul(token, &tkp, base); 1218 } 1219 } else { 1220 tokenval = strtoul(token, &tkp, base); 1221 } 1222 } else { 1223 tokentype = ALPHA; 1224 tkp += strspn(tkp, namechars); 1225 if (*tkp == '[') { 1226 tokentype = FIELD; 1227 *tkp++ = '\0'; 1228 } 1229 } 1230 } else { 1231 tokentype = SPECIAL; 1232 tkp++; 1233 if ((*token == '=' && *tkp == '=') || 1234 (*token == '>' && *tkp == '=') || 1235 (*token == '<' && *tkp == '=') || 1236 (*token == '!' && *tkp == '=')) 1237 tkp++; 1238 } 1239 1240 savechar = *tkp; 1241 *tkp = '\0'; 1242 } 1243 1244 static struct match_type { 1245 char *m_name; 1246 int m_offset; 1247 int m_size; 1248 int m_value; 1249 int m_depend; 1250 enum optype m_optype; 1251 } match_types[] = { 1252 /* 1253 * Table initialized assuming Ethernet data link headers. 1254 */ 1255 "ip", 12, 2, ETHERTYPE_IP, -1, OP_OFFSET_ZERO, 1256 "ip6", 12, 2, ETHERTYPE_IPV6, -1, OP_OFFSET_ZERO, 1257 "arp", 12, 2, ETHERTYPE_ARP, -1, OP_OFFSET_ZERO, 1258 "rarp", 12, 2, ETHERTYPE_REVARP, -1, OP_OFFSET_ZERO, 1259 "pppoed", 12, 2, ETHERTYPE_PPPOED, -1, OP_OFFSET_ZERO, 1260 "pppoes", 12, 2, ETHERTYPE_PPPOES, -1, OP_OFFSET_ZERO, 1261 "tcp", 9, 1, IPPROTO_TCP, 0, OP_OFFSET_LINK, 1262 "tcp", 6, 1, IPPROTO_TCP, 1, OP_OFFSET_LINK, 1263 "udp", 9, 1, IPPROTO_UDP, 0, OP_OFFSET_LINK, 1264 "udp", 6, 1, IPPROTO_UDP, 1, OP_OFFSET_LINK, 1265 "icmp", 9, 1, IPPROTO_ICMP, 0, OP_OFFSET_LINK, 1266 "icmp6", 6, 1, IPPROTO_ICMPV6, 1, OP_OFFSET_LINK, 1267 "ip-in-ip", 9, 1, IPPROTO_ENCAP, 0, OP_OFFSET_LINK, 1268 "esp", 9, 1, IPPROTO_ESP, 0, OP_OFFSET_LINK, 1269 "esp", 6, 1, IPPROTO_ESP, 1, OP_OFFSET_LINK, 1270 "ah", 9, 1, IPPROTO_AH, 0, OP_OFFSET_LINK, 1271 "ah", 6, 1, IPPROTO_AH, 1, OP_OFFSET_LINK, 1272 "sctp", 9, 1, IPPROTO_SCTP, 0, OP_OFFSET_LINK, 1273 "sctp", 6, 1, IPPROTO_SCTP, 1, OP_OFFSET_LINK, 1274 0, 0, 0, 0, 0, 0 1275 }; 1276 1277 static void 1278 generate_check(struct match_type *mtp) 1279 { 1280 int offset; 1281 1282 /* 1283 * Note: this code assumes the above dependencies are 1284 * not cyclic. This *should* always be true. 1285 */ 1286 if (mtp->m_depend != -1) 1287 generate_check(&match_types[mtp->m_depend]); 1288 1289 offset = mtp->m_offset; 1290 if (mtp->m_optype == OP_OFFSET_ZERO) { 1291 1292 /* 1293 * The table is filled with ethernet offsets. Here we 1294 * fudge the value based on what know about the 1295 * interface. It is okay to do this because we are 1296 * checking what we believe to be an IP/ARP/RARP 1297 * packet, and we know those are carried in LLC-SNAP 1298 * headers on FDDI. We assume that it's unlikely 1299 * another kind of packet, with a shorter FDDI header 1300 * will happen to match the filter. 1301 * 1302 * Ether FDDI IPoIB 1303 * edst addr 0 1 none 1304 * esrc addr 6 7 none 1305 * ethertype 12 19 0 1306 * 1307 * XXX token ring? 1308 */ 1309 if (interface->mac_type == DL_FDDI) { 1310 if (offset < 12) 1311 offset++; 1312 else if (offset == 12) 1313 offset = 19; 1314 } else if (interface->mac_type == DL_IB) { 1315 offset = 0; 1316 } 1317 } 1318 1319 if (mtp->m_optype != OP_OFFSET_ZERO) { 1320 emitop(mtp->m_optype); 1321 load_value(offset, mtp->m_size); 1322 load_const(mtp->m_value); 1323 emitop(OP_OFFSET_POP); 1324 } else { 1325 load_value(offset, mtp->m_size); 1326 load_const(mtp->m_value); 1327 } 1328 1329 emitop(OP_EQ); 1330 1331 if (mtp->m_depend != -1) 1332 emitop(OP_AND); 1333 } 1334 1335 /* 1336 * Generate code based on the keyword argument. 1337 * This word is looked up in the match_types table 1338 * and checks a field within the packet for a given 1339 * value e.g. ether or ip type field. The match 1340 * can also have a dependency on another entry e.g. 1341 * "tcp" requires that the packet also be "ip". 1342 */ 1343 static int 1344 comparison(char *s) 1345 { 1346 unsigned int i, n_checks = 0; 1347 1348 for (i = 0; match_types[i].m_name != NULL; i++) { 1349 1350 if (strcmp(s, match_types[i].m_name) != 0) 1351 continue; 1352 1353 n_checks++; 1354 generate_check(&match_types[i]); 1355 if (n_checks > 1) 1356 emitop(OP_OR); 1357 } 1358 1359 return (n_checks > 0); 1360 } 1361 1362 enum direction { ANY, TO, FROM }; 1363 enum direction dir; 1364 1365 /* 1366 * Generate code to match an IP address. The address 1367 * may be supplied either as a hostname or in dotted format. 1368 * For source packets both the IP source address and ARP 1369 * src are checked. 1370 * Note: we don't check packet type here - whether IP or ARP. 1371 * It's possible that we'll do an improper match. 1372 */ 1373 static void 1374 ipaddr_match(enum direction which, char *hostname, int inet_type) 1375 { 1376 bool_t found_host; 1377 int m = 0, n = 0; 1378 uint_t *addr4ptr; 1379 uint_t addr4; 1380 struct in6_addr *addr6ptr; 1381 int h_addr_index; 1382 struct hostent *hp = NULL; 1383 int error_num = 0; 1384 boolean_t freehp = B_FALSE; 1385 boolean_t first = B_TRUE; 1386 1387 /* 1388 * The addr4offset and addr6offset variables simplify the code which 1389 * generates the address comparison filter. With these two variables, 1390 * duplicate code need not exist for the TO and FROM case. 1391 * A value of -1 describes the ANY case (TO and FROM). 1392 */ 1393 int addr4offset; 1394 int addr6offset; 1395 1396 found_host = 0; 1397 1398 if (tokentype == ADDR_IP) { 1399 hp = lgetipnodebyname(hostname, AF_INET, 1400 0, &error_num); 1401 if (hp == NULL) { 1402 hp = getipnodebyname(hostname, AF_INET, 1403 0, &error_num); 1404 freehp = 1; 1405 } 1406 if (hp == NULL) { 1407 if (error_num == TRY_AGAIN) { 1408 pr_err("couldn't resolve %s (try again later)", 1409 hostname); 1410 } else { 1411 pr_err("couldn't resolve %s", hostname); 1412 } 1413 } 1414 inet_type = IPV4_ONLY; 1415 } else if (tokentype == ADDR_IP6) { 1416 hp = lgetipnodebyname(hostname, AF_INET6, 1417 0, &error_num); 1418 if (hp == NULL) { 1419 hp = getipnodebyname(hostname, AF_INET6, 1420 0, &error_num); 1421 freehp = 1; 1422 } 1423 if (hp == NULL) { 1424 if (error_num == TRY_AGAIN) { 1425 pr_err("couldn't resolve %s (try again later)", 1426 hostname); 1427 } else { 1428 pr_err("couldn't resolve %s", hostname); 1429 } 1430 } 1431 inet_type = IPV6_ONLY; 1432 } else { 1433 /* Some hostname i.e. tokentype is ALPHA */ 1434 switch (inet_type) { 1435 case IPV4_ONLY: 1436 /* Only IPv4 address is needed */ 1437 hp = lgetipnodebyname(hostname, AF_INET, 1438 0, &error_num); 1439 if (hp == NULL) { 1440 hp = getipnodebyname(hostname, AF_INET, 1441 0, &error_num); 1442 freehp = 1; 1443 } 1444 if (hp != NULL) { 1445 found_host = 1; 1446 } 1447 break; 1448 case IPV6_ONLY: 1449 /* Only IPv6 address is needed */ 1450 hp = lgetipnodebyname(hostname, AF_INET6, 1451 0, &error_num); 1452 if (hp == NULL) { 1453 hp = getipnodebyname(hostname, AF_INET6, 1454 0, &error_num); 1455 freehp = 1; 1456 } 1457 if (hp != NULL) { 1458 found_host = 1; 1459 } 1460 break; 1461 case IPV4_AND_IPV6: 1462 /* Both IPv4 and IPv6 are needed */ 1463 hp = lgetipnodebyname(hostname, AF_INET6, 1464 AI_ALL | AI_V4MAPPED, &error_num); 1465 if (hp == NULL) { 1466 hp = getipnodebyname(hostname, AF_INET6, 1467 AI_ALL | AI_V4MAPPED, &error_num); 1468 freehp = 1; 1469 } 1470 if (hp != NULL) { 1471 found_host = 1; 1472 } 1473 break; 1474 default: 1475 found_host = 0; 1476 } 1477 1478 if (!found_host) { 1479 if (error_num == TRY_AGAIN) { 1480 pr_err("could not resolve %s (try again later)", 1481 hostname); 1482 } else { 1483 pr_err("could not resolve %s", hostname); 1484 } 1485 } 1486 } 1487 1488 switch (which) { 1489 case TO: 1490 addr4offset = IPV4_DSTADDR_OFFSET; 1491 addr6offset = IPV6_DSTADDR_OFFSET; 1492 break; 1493 case FROM: 1494 addr4offset = IPV4_SRCADDR_OFFSET; 1495 addr6offset = IPV6_SRCADDR_OFFSET; 1496 break; 1497 case ANY: 1498 addr4offset = -1; 1499 addr6offset = -1; 1500 break; 1501 } 1502 1503 /* 1504 * The code below generates the filter. 1505 */ 1506 if (hp != NULL && hp->h_addrtype == AF_INET) { 1507 ethertype_match(ETHERTYPE_IP); 1508 emitop(OP_BRFL); 1509 n = chain(n); 1510 emitop(OP_OFFSET_LINK); 1511 h_addr_index = 0; 1512 addr4ptr = (uint_t *)hp->h_addr_list[h_addr_index]; 1513 while (addr4ptr != NULL) { 1514 if (addr4offset == -1) { 1515 compare_addr_v4(IPV4_SRCADDR_OFFSET, 4, 1516 *addr4ptr); 1517 emitop(OP_BRTR); 1518 m = chain(m); 1519 compare_addr_v4(IPV4_DSTADDR_OFFSET, 4, 1520 *addr4ptr); 1521 } else { 1522 compare_addr_v4(addr4offset, 4, *addr4ptr); 1523 } 1524 addr4ptr = (uint_t *)hp->h_addr_list[++h_addr_index]; 1525 if (addr4ptr != NULL) { 1526 emitop(OP_BRTR); 1527 m = chain(m); 1528 } 1529 } 1530 if (m != 0) { 1531 resolve_chain(m); 1532 } 1533 emitop(OP_OFFSET_POP); 1534 resolve_chain(n); 1535 } else { 1536 /* first pass: IPv4 addresses */ 1537 h_addr_index = 0; 1538 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index]; 1539 first = B_TRUE; 1540 while (addr6ptr != NULL) { 1541 if (IN6_IS_ADDR_V4MAPPED(addr6ptr)) { 1542 if (first) { 1543 ethertype_match(ETHERTYPE_IP); 1544 emitop(OP_BRFL); 1545 n = chain(n); 1546 emitop(OP_OFFSET_LINK); 1547 first = B_FALSE; 1548 } else { 1549 emitop(OP_BRTR); 1550 m = chain(m); 1551 } 1552 IN6_V4MAPPED_TO_INADDR(addr6ptr, 1553 (struct in_addr *)&addr4); 1554 if (addr4offset == -1) { 1555 compare_addr_v4(IPV4_SRCADDR_OFFSET, 4, 1556 addr4); 1557 emitop(OP_BRTR); 1558 m = chain(m); 1559 compare_addr_v4(IPV4_DSTADDR_OFFSET, 4, 1560 addr4); 1561 } else { 1562 compare_addr_v4(addr4offset, 4, addr4); 1563 } 1564 } 1565 addr6ptr = (struct in6_addr *) 1566 hp->h_addr_list[++h_addr_index]; 1567 } 1568 /* second pass: IPv6 addresses */ 1569 h_addr_index = 0; 1570 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index]; 1571 first = B_TRUE; 1572 while (addr6ptr != NULL) { 1573 if (!IN6_IS_ADDR_V4MAPPED(addr6ptr)) { 1574 if (first) { 1575 /* 1576 * bypass check for IPv6 addresses 1577 * when we have an IPv4 packet 1578 */ 1579 if (n != 0) { 1580 emitop(OP_BRTR); 1581 m = chain(m); 1582 emitop(OP_BRFL); 1583 m = chain(m); 1584 resolve_chain(n); 1585 n = 0; 1586 } 1587 ethertype_match(ETHERTYPE_IPV6); 1588 emitop(OP_BRFL); 1589 n = chain(n); 1590 emitop(OP_OFFSET_LINK); 1591 first = B_FALSE; 1592 } else { 1593 emitop(OP_BRTR); 1594 m = chain(m); 1595 } 1596 if (addr6offset == -1) { 1597 compare_addr_v6(IPV6_SRCADDR_OFFSET, 1598 16, *addr6ptr); 1599 emitop(OP_BRTR); 1600 m = chain(m); 1601 compare_addr_v6(IPV6_DSTADDR_OFFSET, 1602 16, *addr6ptr); 1603 } else { 1604 compare_addr_v6(addr6offset, 16, 1605 *addr6ptr); 1606 } 1607 } 1608 addr6ptr = (struct in6_addr *) 1609 hp->h_addr_list[++h_addr_index]; 1610 } 1611 if (m != 0) { 1612 resolve_chain(m); 1613 } 1614 emitop(OP_OFFSET_POP); 1615 resolve_chain(n); 1616 } 1617 1618 /* only free struct hostent returned by getipnodebyname() */ 1619 if (freehp) { 1620 freehostent(hp); 1621 } 1622 } 1623 1624 /* 1625 * Generate code to match an AppleTalk address. The address 1626 * must be given as two numbers with a dot between 1627 * 1628 */ 1629 static void 1630 ataddr_match(enum direction which, char *hostname) 1631 { 1632 uint_t net; 1633 uint_t node; 1634 uint_t m, n; 1635 1636 sscanf(hostname, "%u.%u", &net, &node); 1637 1638 emitop(OP_OFFSET_LINK); 1639 switch (which) { 1640 case TO: 1641 compare_value(AT_DST_NET_OFFSET, 2, net); 1642 emitop(OP_BRFL); 1643 m = chain(0); 1644 compare_value(AT_DST_NODE_OFFSET, 1, node); 1645 resolve_chain(m); 1646 break; 1647 case FROM: 1648 compare_value(AT_SRC_NET_OFFSET, 2, net); 1649 emitop(OP_BRFL); 1650 m = chain(0); 1651 compare_value(AT_SRC_NODE_OFFSET, 1, node); 1652 resolve_chain(m); 1653 break; 1654 case ANY: 1655 compare_value(AT_DST_NET_OFFSET, 2, net); 1656 emitop(OP_BRFL); 1657 m = chain(0); 1658 compare_value(AT_DST_NODE_OFFSET, 1, node); 1659 resolve_chain(m); 1660 emitop(OP_BRTR); 1661 n = chain(0); 1662 compare_value(AT_SRC_NET_OFFSET, 2, net); 1663 emitop(OP_BRFL); 1664 m = chain(0); 1665 compare_value(AT_SRC_NODE_OFFSET, 1, node); 1666 resolve_chain(m); 1667 resolve_chain(n); 1668 break; 1669 } 1670 emitop(OP_OFFSET_POP); 1671 } 1672 1673 /* 1674 * Compare ethernet addresses. The address may 1675 * be provided either as a hostname or as a 1676 * 6 octet colon-separated address. 1677 */ 1678 static void 1679 etheraddr_match(enum direction which, char *hostname) 1680 { 1681 uint_t addr; 1682 ushort_t *addrp; 1683 int to_offset, from_offset; 1684 struct ether_addr e, *ep = NULL; 1685 int m; 1686 1687 /* 1688 * First, check the interface type for whether src/dest address 1689 * is determinable; if not, retreat early. 1690 */ 1691 switch (interface->mac_type) { 1692 case DL_ETHER: 1693 from_offset = ETHERADDRL; 1694 to_offset = 0; 1695 break; 1696 1697 case DL_IB: 1698 /* 1699 * If an ethernet address is attempted to be used 1700 * on an IPoIB interface, flag error. Link address 1701 * based filtering is unsupported on IPoIB, so there 1702 * is no ipibaddr_match() or parsing support for IPoIB 1703 * 20 byte link addresses. 1704 */ 1705 pr_err("filter option unsupported on media"); 1706 break; 1707 1708 case DL_FDDI: 1709 from_offset = 7; 1710 to_offset = 1; 1711 break; 1712 1713 default: 1714 /* 1715 * Where do we find "ether" address for FDDI & TR? 1716 * XXX can improve? ~sparker 1717 */ 1718 load_const(1); 1719 return; 1720 } 1721 1722 if (isxdigit(*hostname)) 1723 ep = ether_aton(hostname); 1724 if (ep == NULL) { 1725 if (ether_hostton(hostname, &e)) 1726 if (!arp_for_ether(hostname, &e)) 1727 pr_err("cannot obtain ether addr for %s", 1728 hostname); 1729 ep = &e; 1730 } 1731 memcpy(&addr, (ushort_t *)ep, 4); 1732 addrp = (ushort_t *)ep + 2; 1733 1734 switch (which) { 1735 case TO: 1736 compare_value(to_offset, 4, ntohl(addr)); 1737 emitop(OP_BRFL); 1738 m = chain(0); 1739 compare_value(to_offset + 4, 2, ntohs(*addrp)); 1740 resolve_chain(m); 1741 break; 1742 case FROM: 1743 compare_value(from_offset, 4, ntohl(addr)); 1744 emitop(OP_BRFL); 1745 m = chain(0); 1746 compare_value(from_offset + 4, 2, ntohs(*addrp)); 1747 resolve_chain(m); 1748 break; 1749 case ANY: 1750 compare_value(to_offset, 4, ntohl(addr)); 1751 compare_value(to_offset + 4, 2, ntohs(*addrp)); 1752 emitop(OP_AND); 1753 emitop(OP_BRTR); 1754 m = chain(0); 1755 1756 compare_value(from_offset, 4, ntohl(addr)); 1757 compare_value(from_offset + 4, 2, ntohs(*addrp)); 1758 emitop(OP_AND); 1759 resolve_chain(m); 1760 break; 1761 } 1762 } 1763 1764 static void 1765 ethertype_match(int val) 1766 { 1767 int m; 1768 int ether_offset; 1769 1770 switch (interface->mac_type) { 1771 case DL_ETHER: 1772 ether_offset = 12; 1773 break; 1774 1775 case DL_IB: 1776 ether_offset = 0; 1777 break; 1778 1779 case DL_FDDI: 1780 /* XXX Okay to assume LLC SNAP? */ 1781 ether_offset = 19; 1782 break; 1783 1784 default: 1785 load_const(1); /* Assume a match */ 1786 return; 1787 } 1788 compare_value(ether_offset, 2, val); /* XXX.sparker */ 1789 } 1790 1791 /* 1792 * Match a network address. The host part 1793 * is masked out. The network address may 1794 * be supplied either as a netname or in 1795 * IP dotted format. The mask to be used 1796 * for the comparison is assumed from the 1797 * address format (see comment below). 1798 */ 1799 static void 1800 netaddr_match(enum direction which, char *netname) 1801 { 1802 uint_t addr; 1803 uint_t mask = 0xff000000; 1804 uint_t m; 1805 struct netent *np; 1806 1807 if (isdigit(*netname)) { 1808 addr = inet_network(netname); 1809 } else { 1810 np = getnetbyname(netname); 1811 if (np == NULL) 1812 pr_err("net %s not known", netname); 1813 addr = np->n_net; 1814 } 1815 addr = ntohl(addr); 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