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 2007 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 <stddef.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 <sys/isa_defs.h> 37 38 #include <sys/socket.h> 39 #include <sys/sockio.h> 40 #include <sys/dlpi.h> 41 #include <sys/vlan.h> 42 #include <net/if.h> 43 #include <netinet/in_systm.h> 44 #include <netinet/in.h> 45 #include <netinet/ip.h> 46 #include <netinet/if_ether.h> 47 #include <netinet/tcp.h> 48 #include <netinet/udp.h> 49 #include <netdb.h> 50 #include <rpc/rpc.h> 51 #include <setjmp.h> 52 53 #include <sys/pfmod.h> 54 #include "snoop.h" 55 #include "snoop_vlan.h" 56 57 /* 58 * This module generates code for the kernel packet filter. 59 * The kernel packet filter is more efficient since it 60 * operates without context switching or moving data into 61 * the capture buffer. On the other hand, it is limited 62 * in its filtering ability i.e. can't cope with variable 63 * length headers, can't compare the packet size, 1 and 4 octet 64 * comparisons are awkward, code space is limited to ENMAXFILTERS 65 * halfwords, etc. 66 * The parser is the same for the user-level packet filter though 67 * more limited in the variety of expressions it can generate 68 * code for. If the pf compiler finds an expression it can't 69 * handle, it tries to set up a split filter in kernel and do the 70 * remaining filtering in userland. If that also fails, it resorts 71 * to userland filter. (See additional comment in pf_compile) 72 */ 73 74 extern struct Pf_ext_packetfilt pf; 75 static ushort_t *pfp; 76 jmp_buf env; 77 78 int eaddr; /* need ethernet addr */ 79 80 int opstack; /* operand stack depth */ 81 82 #define EQ(val) (strcmp(token, val) == 0) 83 #define IPV4_ONLY 0 84 #define IPV6_ONLY 1 85 #define IPV4_AND_IPV6 2 86 87 /* 88 * The following constants represent the offsets in bytes from the beginning 89 * of the packet of the link and IP(v6) layer source/destination/type fields, 90 * initialized for Ethernet. Media specific code can set any unavailable 91 * link layer property's offset to -1 to indicate that the property's value 92 * is not available from the frame. 93 */ 94 static int link_header_len = 14, link_type_offset = 12; 95 static int link_dest_offset = 0, link_src_offset = 6; 96 static int link_addr_len = 6; 97 98 #define IPV4_SRCADDR_OFFSET (link_header_len + 12) 99 #define IPV4_DSTADDR_OFFSET (link_header_len + 16) 100 #define IPV6_SRCADDR_OFFSET (link_header_len + 8) 101 #define IPV6_DSTADDR_OFFSET (link_header_len + 24) 102 103 static int inBrace = 0, inBraceOR = 0; 104 static int foundOR = 0; 105 char *tkp, *sav_tkp; 106 char *token; 107 enum { EOL, ALPHA, NUMBER, FIELD, ADDR_IP, ADDR_ETHER, SPECIAL, 108 ADDR_IP6 } tokentype; 109 uint_t tokenval; 110 111 enum direction { ANY, TO, FROM }; 112 enum direction dir; 113 114 extern void next(); 115 116 static void pf_expression(); 117 static void pf_check_vlan_tag(uint_t offset); 118 static void pf_clear_offset_register(); 119 static void pf_emit_load_offset(uint_t offset); 120 static void pf_match_ethertype(uint_t ethertype); 121 static void pf_check_transport_protocol(uint_t transport_protocol); 122 static void pf_compare_value_mask_generic(int offset, uint_t len, 123 uint_t val, int mask, uint_t op); 124 125 /* 126 * This pointer points to the function that last generated 127 * instructions to change the offset register. It's used 128 * for comparisons to see if we need to issue more instructions 129 * to change the register. 130 * 131 * It's initialized to pf_clear_offset_register because the offset 132 * register in pfmod is initialized to zero, similar to the state 133 * it would be in after executing the instructions issued by 134 * pf_clear_offset_register. 135 */ 136 static void *last_offset_operation = (void*)pf_clear_offset_register; 137 138 static void 139 pf_emit(x) 140 ushort_t x; 141 { 142 if (pfp > &pf.Pf_Filter[PF_MAXFILTERS - 1]) 143 longjmp(env, 1); 144 *pfp++ = x; 145 } 146 147 static void 148 pf_codeprint(code, len) 149 ushort_t *code; 150 int len; 151 { 152 ushort_t *pc; 153 ushort_t *plast = code + len; 154 int op, action; 155 156 if (len > 0) { 157 printf("Kernel Filter:\n"); 158 } 159 160 for (pc = code; pc < plast; pc++) { 161 printf("\t%3d: ", pc - code); 162 163 op = *pc & 0xfc00; /* high 10 bits */ 164 action = *pc & 0x3ff; /* low 6 bits */ 165 166 switch (action) { 167 case ENF_PUSHLIT: 168 printf("PUSHLIT "); 169 break; 170 case ENF_PUSHZERO: 171 printf("PUSHZERO "); 172 break; 173 #ifdef ENF_PUSHONE 174 case ENF_PUSHONE: 175 printf("PUSHONE "); 176 break; 177 #endif 178 #ifdef ENF_PUSHFFFF 179 case ENF_PUSHFFFF: 180 printf("PUSHFFFF "); 181 break; 182 #endif 183 #ifdef ENF_PUSHFF00 184 case ENF_PUSHFF00: 185 printf("PUSHFF00 "); 186 break; 187 #endif 188 #ifdef ENF_PUSH00FF 189 case ENF_PUSH00FF: 190 printf("PUSH00FF "); 191 break; 192 #endif 193 case ENF_LOAD_OFFSET: 194 printf("LOAD_OFFSET "); 195 break; 196 case ENF_BRTR: 197 printf("BRTR "); 198 break; 199 case ENF_BRFL: 200 printf("BRFL "); 201 break; 202 case ENF_POP: 203 printf("POP "); 204 break; 205 } 206 207 if (action >= ENF_PUSHWORD) 208 printf("PUSHWORD %d ", action - ENF_PUSHWORD); 209 210 switch (op) { 211 case ENF_EQ: 212 printf("EQ "); 213 break; 214 case ENF_LT: 215 printf("LT "); 216 break; 217 case ENF_LE: 218 printf("LE "); 219 break; 220 case ENF_GT: 221 printf("GT "); 222 break; 223 case ENF_GE: 224 printf("GE "); 225 break; 226 case ENF_AND: 227 printf("AND "); 228 break; 229 case ENF_OR: 230 printf("OR "); 231 break; 232 case ENF_XOR: 233 printf("XOR "); 234 break; 235 case ENF_COR: 236 printf("COR "); 237 break; 238 case ENF_CAND: 239 printf("CAND "); 240 break; 241 case ENF_CNOR: 242 printf("CNOR "); 243 break; 244 case ENF_CNAND: 245 printf("CNAND "); 246 break; 247 case ENF_NEQ: 248 printf("NEQ "); 249 break; 250 } 251 252 if (action == ENF_PUSHLIT || 253 action == ENF_LOAD_OFFSET || 254 action == ENF_BRTR || 255 action == ENF_BRFL) { 256 pc++; 257 printf("\n\t%3d: %d (0x%04x)", pc - code, *pc, *pc); 258 } 259 260 printf("\n"); 261 } 262 } 263 264 /* 265 * Emit packet filter code to check a 266 * field in the packet for a particular value. 267 * Need different code for each field size. 268 * Since the pf can only compare 16 bit quantities 269 * we have to use masking to compare byte values. 270 * Long word (32 bit) quantities have to be done 271 * as two 16 bit comparisons. 272 */ 273 static void 274 pf_compare_value(int offset, uint_t len, uint_t val) 275 { 276 /* 277 * If the property being filtered on is absent in the media 278 * packet, error out. 279 */ 280 if (offset == -1) 281 pr_err("filter option unsupported on media"); 282 283 switch (len) { 284 case 1: 285 pf_emit(ENF_PUSHWORD + offset / 2); 286 #if defined(_BIG_ENDIAN) 287 if (offset % 2) 288 #else 289 if (!(offset % 2)) 290 #endif 291 { 292 #ifdef ENF_PUSH00FF 293 pf_emit(ENF_PUSH00FF | ENF_AND); 294 #else 295 pf_emit(ENF_PUSHLIT | ENF_AND); 296 pf_emit(0x00FF); 297 #endif 298 pf_emit(ENF_PUSHLIT | ENF_EQ); 299 pf_emit(val); 300 } else { 301 #ifdef ENF_PUSHFF00 302 pf_emit(ENF_PUSHFF00 | ENF_AND); 303 #else 304 pf_emit(ENF_PUSHLIT | ENF_AND); 305 pf_emit(0xFF00); 306 #endif 307 pf_emit(ENF_PUSHLIT | ENF_EQ); 308 pf_emit(val << 8); 309 } 310 break; 311 312 case 2: 313 pf_emit(ENF_PUSHWORD + offset / 2); 314 pf_emit(ENF_PUSHLIT | ENF_EQ); 315 pf_emit((ushort_t)val); 316 break; 317 318 case 4: 319 pf_emit(ENF_PUSHWORD + offset / 2); 320 pf_emit(ENF_PUSHLIT | ENF_EQ); 321 #if defined(_BIG_ENDIAN) 322 pf_emit(val >> 16); 323 #elif defined(_LITTLE_ENDIAN) 324 pf_emit(val & 0xffff); 325 #else 326 #error One of _BIG_ENDIAN and _LITTLE_ENDIAN must be defined 327 #endif 328 pf_emit(ENF_PUSHWORD + (offset / 2) + 1); 329 pf_emit(ENF_PUSHLIT | ENF_EQ); 330 #if defined(_BIG_ENDIAN) 331 pf_emit(val & 0xffff); 332 #else 333 pf_emit(val >> 16); 334 #endif 335 pf_emit(ENF_AND); 336 break; 337 } 338 } 339 340 /* 341 * same as pf_compare_value, but only for emiting code to 342 * compare ipv6 addresses. 343 */ 344 static void 345 pf_compare_value_v6(int offset, uint_t len, struct in6_addr val) 346 { 347 int i; 348 349 for (i = 0; i < len; i += 2) { 350 pf_emit(ENF_PUSHWORD + offset / 2 + i / 2); 351 pf_emit(ENF_PUSHLIT | ENF_EQ); 352 pf_emit(*(uint16_t *)&val.s6_addr[i]); 353 if (i != 0) 354 pf_emit(ENF_AND); 355 } 356 } 357 358 359 /* 360 * Same as above except mask the field value 361 * before doing the comparison. The comparison checks 362 * to make sure the values are equal. 363 */ 364 static void 365 pf_compare_value_mask(int offset, uint_t len, uint_t val, int mask) 366 { 367 pf_compare_value_mask_generic(offset, len, val, mask, ENF_EQ); 368 } 369 370 /* 371 * Same as above except the values are compared to see if they are not 372 * equal. 373 */ 374 static void 375 pf_compare_value_mask_neq(int offset, uint_t len, uint_t val, int mask) 376 { 377 pf_compare_value_mask_generic(offset, len, val, mask, ENF_NEQ); 378 } 379 380 /* 381 * Similar to pf_compare_value. 382 * 383 * This is the utility function that does the actual work to compare 384 * two values using a mask. The comparison operation is passed into 385 * the function. 386 */ 387 static void 388 pf_compare_value_mask_generic(int offset, uint_t len, uint_t val, int mask, 389 uint_t op) 390 { 391 /* 392 * If the property being filtered on is absent in the media 393 * packet, error out. 394 */ 395 if (offset == -1) 396 pr_err("filter option unsupported on media"); 397 398 switch (len) { 399 case 1: 400 pf_emit(ENF_PUSHWORD + offset / 2); 401 #if defined(_BIG_ENDIAN) 402 if (offset % 2) 403 #else 404 if (!offset % 2) 405 #endif 406 { 407 pf_emit(ENF_PUSHLIT | ENF_AND); 408 pf_emit(mask & 0x00ff); 409 pf_emit(ENF_PUSHLIT | op); 410 pf_emit(val); 411 } else { 412 pf_emit(ENF_PUSHLIT | ENF_AND); 413 pf_emit((mask << 8) & 0xff00); 414 pf_emit(ENF_PUSHLIT | op); 415 pf_emit(val << 8); 416 } 417 break; 418 419 case 2: 420 pf_emit(ENF_PUSHWORD + offset / 2); 421 pf_emit(ENF_PUSHLIT | ENF_AND); 422 pf_emit(htons((ushort_t)mask)); 423 pf_emit(ENF_PUSHLIT | op); 424 pf_emit(htons((ushort_t)val)); 425 break; 426 427 case 4: 428 pf_emit(ENF_PUSHWORD + offset / 2); 429 pf_emit(ENF_PUSHLIT | ENF_AND); 430 pf_emit(htons((ushort_t)((mask >> 16) & 0xffff))); 431 pf_emit(ENF_PUSHLIT | op); 432 pf_emit(htons((ushort_t)((val >> 16) & 0xffff))); 433 434 pf_emit(ENF_PUSHWORD + (offset / 2) + 1); 435 pf_emit(ENF_PUSHLIT | ENF_AND); 436 pf_emit(htons((ushort_t)(mask & 0xffff))); 437 pf_emit(ENF_PUSHLIT | op); 438 pf_emit(htons((ushort_t)(val & 0xffff))); 439 440 pf_emit(ENF_AND); 441 break; 442 } 443 } 444 445 /* 446 * Generate pf code to match an IPv4 or IPv6 address. 447 */ 448 static void 449 pf_ipaddr_match(which, hostname, inet_type) 450 enum direction which; 451 char *hostname; 452 int inet_type; 453 { 454 bool_t found_host; 455 uint_t *addr4ptr; 456 uint_t addr4; 457 struct in6_addr *addr6ptr; 458 int h_addr_index; 459 struct hostent *hp = NULL; 460 int error_num = 0; 461 boolean_t first = B_TRUE; 462 int pass = 0; 463 464 /* 465 * The addr4offset and addr6offset variables simplify the code which 466 * generates the address comparison filter. With these two variables, 467 * duplicate code need not exist for the TO and FROM case. 468 * A value of -1 describes the ANY case (TO and FROM). 469 */ 470 int addr4offset; 471 int addr6offset; 472 473 found_host = 0; 474 475 if (tokentype == ADDR_IP) { 476 hp = getipnodebyname(hostname, AF_INET, 0, &error_num); 477 if (hp == NULL) { 478 if (error_num == TRY_AGAIN) { 479 pr_err("could not resolve %s (try again later)", 480 hostname); 481 } else { 482 pr_err("could not resolve %s", hostname); 483 } 484 } 485 inet_type = IPV4_ONLY; 486 } else if (tokentype == ADDR_IP6) { 487 hp = getipnodebyname(hostname, AF_INET6, 0, &error_num); 488 if (hp == NULL) { 489 if (error_num == TRY_AGAIN) { 490 pr_err("could not resolve %s (try again later)", 491 hostname); 492 } else { 493 pr_err("could not resolve %s", hostname); 494 } 495 } 496 inet_type = IPV6_ONLY; 497 } else if (tokentype == ALPHA) { 498 /* Some hostname i.e. tokentype is ALPHA */ 499 switch (inet_type) { 500 case IPV4_ONLY: 501 /* Only IPv4 address is needed */ 502 hp = getipnodebyname(hostname, AF_INET, 0, &error_num); 503 if (hp != NULL) { 504 found_host = 1; 505 } 506 break; 507 case IPV6_ONLY: 508 /* Only IPv6 address is needed */ 509 hp = getipnodebyname(hostname, AF_INET6, 0, &error_num); 510 if (hp != NULL) { 511 found_host = 1; 512 } 513 break; 514 case IPV4_AND_IPV6: 515 /* Both IPv4 and IPv6 are needed */ 516 hp = getipnodebyname(hostname, AF_INET6, 517 AI_ALL | AI_V4MAPPED, &error_num); 518 if (hp != NULL) { 519 found_host = 1; 520 } 521 break; 522 default: 523 found_host = 0; 524 } 525 526 if (!found_host) { 527 if (error_num == TRY_AGAIN) { 528 pr_err("could not resolve %s (try again later)", 529 hostname); 530 } else { 531 pr_err("could not resolve %s", hostname); 532 } 533 } 534 } else { 535 pr_err("unknown token type: %s", hostname); 536 } 537 538 switch (which) { 539 case TO: 540 addr4offset = IPV4_DSTADDR_OFFSET; 541 addr6offset = IPV6_DSTADDR_OFFSET; 542 break; 543 case FROM: 544 addr4offset = IPV4_SRCADDR_OFFSET; 545 addr6offset = IPV6_SRCADDR_OFFSET; 546 break; 547 case ANY: 548 addr4offset = -1; 549 addr6offset = -1; 550 break; 551 } 552 553 if (hp != NULL && hp->h_addrtype == AF_INET) { 554 pf_match_ethertype(ETHERTYPE_IP); 555 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2); 556 h_addr_index = 0; 557 addr4ptr = (uint_t *)hp->h_addr_list[h_addr_index]; 558 while (addr4ptr != NULL) { 559 if (addr4offset == -1) { 560 pf_compare_value(IPV4_SRCADDR_OFFSET, 4, 561 *addr4ptr); 562 if (h_addr_index != 0) 563 pf_emit(ENF_OR); 564 pf_compare_value(IPV4_DSTADDR_OFFSET, 4, 565 *addr4ptr); 566 pf_emit(ENF_OR); 567 } else { 568 pf_compare_value(addr4offset, 4, 569 *addr4ptr); 570 if (h_addr_index != 0) 571 pf_emit(ENF_OR); 572 } 573 addr4ptr = (uint_t *)hp->h_addr_list[++h_addr_index]; 574 } 575 pf_emit(ENF_AND); 576 } else { 577 /* first pass: IPv4 addresses */ 578 h_addr_index = 0; 579 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index]; 580 first = B_TRUE; 581 while (addr6ptr != NULL) { 582 if (IN6_IS_ADDR_V4MAPPED(addr6ptr)) { 583 if (first) { 584 pf_match_ethertype(ETHERTYPE_IP); 585 pf_check_vlan_tag( 586 ENCAP_ETHERTYPE_OFF/2); 587 pass++; 588 } 589 IN6_V4MAPPED_TO_INADDR(addr6ptr, 590 (struct in_addr *)&addr4); 591 if (addr4offset == -1) { 592 pf_compare_value(IPV4_SRCADDR_OFFSET, 4, 593 addr4); 594 if (!first) 595 pf_emit(ENF_OR); 596 pf_compare_value(IPV4_DSTADDR_OFFSET, 4, 597 addr4); 598 pf_emit(ENF_OR); 599 } else { 600 pf_compare_value(addr4offset, 4, 601 addr4); 602 if (!first) 603 pf_emit(ENF_OR); 604 } 605 if (first) 606 first = B_FALSE; 607 } 608 addr6ptr = (struct in6_addr *) 609 hp->h_addr_list[++h_addr_index]; 610 } 611 if (!first) { 612 pf_emit(ENF_AND); 613 } 614 /* second pass: IPv6 addresses */ 615 h_addr_index = 0; 616 addr6ptr = (struct in6_addr *)hp->h_addr_list[h_addr_index]; 617 first = B_TRUE; 618 while (addr6ptr != NULL) { 619 if (!IN6_IS_ADDR_V4MAPPED(addr6ptr)) { 620 if (first) { 621 pf_match_ethertype(ETHERTYPE_IPV6); 622 pf_check_vlan_tag( 623 ENCAP_ETHERTYPE_OFF/2); 624 pass++; 625 } 626 if (addr6offset == -1) { 627 pf_compare_value_v6(IPV6_SRCADDR_OFFSET, 628 16, *addr6ptr); 629 if (!first) 630 pf_emit(ENF_OR); 631 pf_compare_value_v6(IPV6_DSTADDR_OFFSET, 632 16, *addr6ptr); 633 pf_emit(ENF_OR); 634 } else { 635 pf_compare_value_v6(addr6offset, 16, 636 *addr6ptr); 637 if (!first) 638 pf_emit(ENF_OR); 639 } 640 if (first) 641 first = B_FALSE; 642 } 643 addr6ptr = (struct in6_addr *) 644 hp->h_addr_list[++h_addr_index]; 645 } 646 if (!first) { 647 pf_emit(ENF_AND); 648 } 649 if (pass == 2) { 650 pf_emit(ENF_OR); 651 } 652 } 653 654 if (hp != NULL) { 655 freehostent(hp); 656 } 657 } 658 659 660 static void 661 pf_compare_address(int offset, uint_t len, uchar_t *addr) 662 { 663 uint32_t val; 664 uint16_t sval; 665 boolean_t didone = B_FALSE; 666 667 /* 668 * If the property being filtered on is absent in the media 669 * packet, error out. 670 */ 671 if (offset == -1) 672 pr_err("filter option unsupported on media"); 673 674 while (len > 0) { 675 if (len >= 4) { 676 (void) memcpy(&val, addr, 4); 677 pf_compare_value(offset, 4, val); 678 addr += 4; 679 offset += 4; 680 len -= 4; 681 } else if (len >= 2) { 682 (void) memcpy(&sval, addr, 2); 683 pf_compare_value(offset, 2, sval); 684 addr += 2; 685 offset += 2; 686 len -= 2; 687 } else { 688 pf_compare_value(offset++, 1, *addr++); 689 len--; 690 } 691 if (didone) 692 pf_emit(ENF_AND); 693 didone = B_TRUE; 694 } 695 } 696 697 /* 698 * Compare ethernet addresses. 699 */ 700 static void 701 pf_etheraddr_match(which, hostname) 702 enum direction which; 703 char *hostname; 704 { 705 struct ether_addr e, *ep = NULL; 706 707 if (isxdigit(*hostname)) 708 ep = ether_aton(hostname); 709 if (ep == NULL) { 710 if (ether_hostton(hostname, &e)) 711 if (!arp_for_ether(hostname, &e)) 712 pr_err("cannot obtain ether addr for %s", 713 hostname); 714 ep = &e; 715 } 716 717 pf_clear_offset_register(); 718 719 switch (which) { 720 case TO: 721 pf_compare_address(link_dest_offset, link_addr_len, 722 (uchar_t *)ep); 723 break; 724 case FROM: 725 pf_compare_address(link_src_offset, link_addr_len, 726 (uchar_t *)ep); 727 break; 728 case ANY: 729 pf_compare_address(link_dest_offset, link_addr_len, 730 (uchar_t *)ep); 731 pf_compare_address(link_src_offset, link_addr_len, 732 (uchar_t *)ep); 733 pf_emit(ENF_OR); 734 break; 735 } 736 } 737 738 /* 739 * Emit code to compare the network part of 740 * an IP address. 741 */ 742 static void 743 pf_netaddr_match(which, netname) 744 enum direction which; 745 char *netname; 746 { 747 uint_t addr; 748 uint_t mask = 0xff000000; 749 struct netent *np; 750 751 if (isdigit(*netname)) { 752 addr = inet_network(netname); 753 } else { 754 np = getnetbyname(netname); 755 if (np == NULL) 756 pr_err("net %s not known", netname); 757 addr = np->n_net; 758 } 759 760 /* 761 * Left justify the address and figure 762 * out a mask based on the supplied address. 763 * Set the mask according to the number of zero 764 * low-order bytes. 765 * Note: this works only for whole octet masks. 766 */ 767 if (addr) { 768 while ((addr & ~mask) != 0) { 769 mask |= (mask >> 8); 770 } 771 } 772 773 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2); 774 775 switch (which) { 776 case TO: 777 pf_compare_value_mask(IPV4_DSTADDR_OFFSET, 4, addr, mask); 778 break; 779 case FROM: 780 pf_compare_value_mask(IPV4_SRCADDR_OFFSET, 4, addr, mask); 781 break; 782 case ANY: 783 pf_compare_value_mask(IPV4_SRCADDR_OFFSET, 4, addr, mask); 784 pf_compare_value_mask(IPV4_DSTADDR_OFFSET, 4, addr, mask); 785 pf_emit(ENF_OR); 786 break; 787 } 788 } 789 790 /* 791 * A helper function to keep the code to emit instructions 792 * to change the offset register in one place. 793 * 794 * INPUTS: offset - An value representing an offset in 16-bit 795 * words. 796 * OUTPUTS: If there is enough room in the storage for the 797 * packet filtering program, instructions to load 798 * a constant to the offset register. Otherwise, 799 * nothing. 800 */ 801 static void 802 pf_emit_load_offset(uint_t offset) 803 { 804 pf_emit(ENF_LOAD_OFFSET | ENF_NOP); 805 pf_emit(offset); 806 } 807 808 /* 809 * Clear pfmod's offset register. 810 * 811 * INPUTS: none 812 * OUTPUTS: Instructions to clear the offset register if 813 * there is enough space remaining in the packet 814 * filtering program structure's storage, and 815 * the last thing done to the offset register was 816 * not clearing the offset register. Otherwise, 817 * nothing. 818 */ 819 static void 820 pf_clear_offset_register() 821 { 822 if (last_offset_operation != (void*)pf_clear_offset_register) { 823 pf_emit_load_offset(0); 824 last_offset_operation = (void*)pf_clear_offset_register; 825 } 826 } 827 828 /* 829 * This function will issue opcodes to check if a packet 830 * is VLAN tagged, and if so, update the offset register 831 * with the appropriate offset. 832 * 833 * Note that if the packet is not VLAN tagged, then the offset 834 * register will be cleared. 835 * 836 * If the interface type is not an ethernet type, then this 837 * function returns without doing anything. 838 * 839 * If the last attempt to change the offset register occured because 840 * of a call to this function that was called with the same offset, 841 * then we don't issue packet filtering instructions. 842 * 843 * INPUTS: offset - an offset in 16 bit words. The function 844 * will set the offset register to this 845 * value if the packet is VLAN tagged. 846 * OUTPUTS: If the conditions are met, packet filtering instructions. 847 */ 848 static void 849 pf_check_vlan_tag(uint_t offset) 850 { 851 static uint_t last_offset = 0; 852 853 if ((interface->mac_type == DL_ETHER || 854 interface->mac_type == DL_CSMACD) && 855 (last_offset_operation != (void*)pf_check_vlan_tag || 856 last_offset != offset)) { 857 /* 858 * First thing is to clear the offset register. 859 * We don't know what state it is in, and if it 860 * is not zero, then we have no idea what we load 861 * when we execute ENF_PUSHWORD. 862 */ 863 pf_clear_offset_register(); 864 865 /* 866 * Check the ethertype. 867 */ 868 pf_compare_value(link_type_offset, 2, htons(ETHERTYPE_VLAN)); 869 870 /* 871 * And if it's not VLAN, don't load offset to the offset 872 * register. 873 */ 874 pf_emit(ENF_BRFL | ENF_NOP); 875 pf_emit(3); 876 877 /* 878 * Otherwise, load offset to the offset register. 879 */ 880 pf_emit_load_offset(offset); 881 882 /* 883 * Now get rid of the results of the comparison, 884 * we don't want the results of the comparison to affect 885 * other logic in the packet filtering program. 886 */ 887 pf_emit(ENF_POP | ENF_NOP); 888 889 /* 890 * Set the last operation at the end, or any time 891 * after the call to pf_clear_offset because 892 * pf_clear_offset uses it. 893 */ 894 last_offset_operation = (void*)pf_check_vlan_tag; 895 last_offset = offset; 896 } 897 } 898 899 /* 900 * Utility function used to emit packet filtering code 901 * to match an ethertype. 902 * 903 * INPUTS: ethertype - The ethertype we want to check for. 904 * Don't call htons on the ethertype before 905 * calling this function. 906 * OUTPUTS: If there is sufficient storage available, packet 907 * filtering code to check an ethertype. Otherwise, 908 * nothing. 909 */ 910 static void 911 pf_match_ethertype(uint_t ethertype) 912 { 913 /* 914 * If the user wants to filter on ethertype VLAN, 915 * then clear the offset register so that the offset 916 * for ENF_PUSHWORD points to the right place in the 917 * packet. 918 * 919 * Otherwise, call pf_check_vlan_tag to set the offset 920 * register such that the contents of the offset register 921 * plus the argument for ENF_PUSHWORD point to the right 922 * part of the packet, whether or not the packet is VLAN 923 * tagged. We call pf_check_vlan_tag with an offset of 924 * two words because if the packet is VLAN tagged, we have 925 * to move past the ethertype in the ethernet header, and 926 * past the lower two octets of the VLAN header to get to 927 * the ethertype in the VLAN header. 928 */ 929 if (ethertype == ETHERTYPE_VLAN) 930 pf_clear_offset_register(); 931 else 932 pf_check_vlan_tag(2); 933 934 pf_compare_value(link_type_offset, 2, htons(ethertype)); 935 } 936 937 typedef struct { 938 int transport_protocol; 939 int network_protocol; 940 /* 941 * offset is the offset in bytes from the beginning 942 * of the network protocol header to where the transport 943 * protocol type is. 944 */ 945 int offset; 946 } transport_protocol_table_t; 947 948 static transport_protocol_table_t mapping_table[] = { 949 {IPPROTO_TCP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 950 {IPPROTO_TCP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET}, 951 {IPPROTO_UDP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 952 {IPPROTO_UDP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET}, 953 {IPPROTO_OSPF, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 954 {IPPROTO_OSPF, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET}, 955 {IPPROTO_SCTP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 956 {IPPROTO_SCTP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET}, 957 {IPPROTO_ICMP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 958 {IPPROTO_ICMPV6, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET}, 959 {IPPROTO_ENCAP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 960 {IPPROTO_ESP, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 961 {IPPROTO_ESP, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET}, 962 {IPPROTO_AH, ETHERTYPE_IP, IPV4_TYPE_HEADER_OFFSET}, 963 {IPPROTO_AH, ETHERTYPE_IPV6, IPV6_TYPE_HEADER_OFFSET}, 964 {-1, 0, 0} /* must be the final entry */ 965 }; 966 967 /* 968 * This function uses the table above to generate a 969 * piece of a packet filtering program to check a transport 970 * protocol type. 971 * 972 * INPUTS: tranport_protocol - the transport protocol we're 973 * interested in. 974 * OUTPUTS: If there is sufficient storage, then packet filtering 975 * code to check a transport protocol type. Otherwise, 976 * nothing. 977 */ 978 static void 979 pf_check_transport_protocol(uint_t transport_protocol) 980 { 981 int i = 0; 982 uint_t number_of_matches = 0; 983 984 for (i = 0; mapping_table[i].transport_protocol != -1; i++) { 985 if (transport_protocol == 986 (uint_t)mapping_table[i].transport_protocol) { 987 number_of_matches++; 988 pf_match_ethertype(mapping_table[i].network_protocol); 989 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2); 990 pf_compare_value( 991 mapping_table[i].offset + link_header_len, 1, 992 transport_protocol); 993 pf_emit(ENF_AND); 994 if (number_of_matches > 1) { 995 /* 996 * Since we have two or more matches, in 997 * order to have a correct and complete 998 * program we need to OR the result of 999 * each block of comparisons together. 1000 */ 1001 pf_emit(ENF_OR); 1002 } 1003 } 1004 } 1005 } 1006 1007 static void 1008 pf_primary() 1009 { 1010 for (;;) { 1011 if (tokentype == FIELD) 1012 break; 1013 1014 if (EQ("ip")) { 1015 pf_match_ethertype(ETHERTYPE_IP); 1016 opstack++; 1017 next(); 1018 break; 1019 } 1020 1021 if (EQ("ip6")) { 1022 pf_match_ethertype(ETHERTYPE_IPV6); 1023 opstack++; 1024 next(); 1025 break; 1026 } 1027 1028 if (EQ("pppoe")) { 1029 pf_match_ethertype(ETHERTYPE_PPPOED); 1030 pf_match_ethertype(ETHERTYPE_PPPOES); 1031 pf_emit(ENF_OR); 1032 opstack++; 1033 next(); 1034 break; 1035 } 1036 1037 if (EQ("pppoed")) { 1038 pf_match_ethertype(ETHERTYPE_PPPOED); 1039 opstack++; 1040 next(); 1041 break; 1042 } 1043 1044 if (EQ("pppoes")) { 1045 pf_match_ethertype(ETHERTYPE_PPPOES); 1046 opstack++; 1047 next(); 1048 break; 1049 } 1050 1051 if (EQ("arp")) { 1052 pf_match_ethertype(ETHERTYPE_ARP); 1053 opstack++; 1054 next(); 1055 break; 1056 } 1057 1058 if (EQ("vlan")) { 1059 pf_match_ethertype(ETHERTYPE_VLAN); 1060 pf_compare_value_mask_neq(VLAN_ID_OFFSET, 2, 1061 0, VLAN_ID_MASK); 1062 pf_emit(ENF_AND); 1063 opstack++; 1064 next(); 1065 break; 1066 } 1067 1068 if (EQ("vlan-id")) { 1069 next(); 1070 if (tokentype != NUMBER) 1071 pr_err("VLAN ID expected"); 1072 pf_match_ethertype(ETHERTYPE_VLAN); 1073 pf_compare_value_mask(VLAN_ID_OFFSET, 2, tokenval, 1074 VLAN_ID_MASK); 1075 pf_emit(ENF_AND); 1076 opstack++; 1077 next(); 1078 break; 1079 } 1080 1081 if (EQ("rarp")) { 1082 pf_match_ethertype(ETHERTYPE_REVARP); 1083 opstack++; 1084 next(); 1085 break; 1086 } 1087 1088 if (EQ("tcp")) { 1089 pf_check_transport_protocol(IPPROTO_TCP); 1090 opstack++; 1091 next(); 1092 break; 1093 } 1094 1095 if (EQ("udp")) { 1096 pf_check_transport_protocol(IPPROTO_UDP); 1097 opstack++; 1098 next(); 1099 break; 1100 } 1101 1102 if (EQ("ospf")) { 1103 pf_check_transport_protocol(IPPROTO_OSPF); 1104 opstack++; 1105 next(); 1106 break; 1107 } 1108 1109 1110 if (EQ("sctp")) { 1111 pf_check_transport_protocol(IPPROTO_SCTP); 1112 opstack++; 1113 next(); 1114 break; 1115 } 1116 1117 if (EQ("icmp")) { 1118 pf_check_transport_protocol(IPPROTO_ICMP); 1119 opstack++; 1120 next(); 1121 break; 1122 } 1123 1124 if (EQ("icmp6")) { 1125 pf_check_transport_protocol(IPPROTO_ICMPV6); 1126 opstack++; 1127 next(); 1128 break; 1129 } 1130 1131 if (EQ("ip-in-ip")) { 1132 pf_check_transport_protocol(IPPROTO_ENCAP); 1133 opstack++; 1134 next(); 1135 break; 1136 } 1137 1138 if (EQ("esp")) { 1139 pf_check_transport_protocol(IPPROTO_ESP); 1140 opstack++; 1141 next(); 1142 break; 1143 } 1144 1145 if (EQ("ah")) { 1146 pf_check_transport_protocol(IPPROTO_AH); 1147 opstack++; 1148 next(); 1149 break; 1150 } 1151 1152 if (EQ("(")) { 1153 inBrace++; 1154 next(); 1155 pf_expression(); 1156 if (EQ(")")) { 1157 if (inBrace) 1158 inBraceOR--; 1159 inBrace--; 1160 next(); 1161 } 1162 break; 1163 } 1164 1165 if (EQ("to") || EQ("dst")) { 1166 dir = TO; 1167 next(); 1168 continue; 1169 } 1170 1171 if (EQ("from") || EQ("src")) { 1172 dir = FROM; 1173 next(); 1174 continue; 1175 } 1176 1177 if (EQ("ether")) { 1178 eaddr = 1; 1179 next(); 1180 continue; 1181 } 1182 1183 if (EQ("inet")) { 1184 next(); 1185 if (EQ("host")) 1186 next(); 1187 if (tokentype != ALPHA && tokentype != ADDR_IP) 1188 pr_err("host/IPv4 addr expected after inet"); 1189 pf_ipaddr_match(dir, token, IPV4_ONLY); 1190 opstack++; 1191 next(); 1192 break; 1193 } 1194 1195 if (EQ("inet6")) { 1196 next(); 1197 if (EQ("host")) 1198 next(); 1199 if (tokentype != ALPHA && tokentype != ADDR_IP6) 1200 pr_err("host/IPv6 addr expected after inet6"); 1201 pf_ipaddr_match(dir, token, IPV6_ONLY); 1202 opstack++; 1203 next(); 1204 break; 1205 } 1206 1207 if (EQ("proto")) { 1208 next(); 1209 if (tokentype != NUMBER) 1210 pr_err("IP proto type expected"); 1211 pf_check_vlan_tag(ENCAP_ETHERTYPE_OFF/2); 1212 pf_compare_value( 1213 IPV4_TYPE_HEADER_OFFSET + link_header_len, 1, 1214 tokenval); 1215 opstack++; 1216 next(); 1217 break; 1218 } 1219 1220 if (EQ("broadcast")) { 1221 pf_clear_offset_register(); 1222 pf_compare_value(link_dest_offset, 4, 0xffffffff); 1223 opstack++; 1224 next(); 1225 break; 1226 } 1227 1228 if (EQ("multicast")) { 1229 pf_clear_offset_register(); 1230 pf_compare_value_mask(link_dest_offset, 1, 0x01, 0x01); 1231 opstack++; 1232 next(); 1233 break; 1234 } 1235 1236 if (EQ("ethertype")) { 1237 next(); 1238 if (tokentype != NUMBER) 1239 pr_err("ether type expected"); 1240 pf_match_ethertype(tokenval); 1241 opstack++; 1242 next(); 1243 break; 1244 } 1245 1246 if (EQ("net") || EQ("dstnet") || EQ("srcnet")) { 1247 if (EQ("dstnet")) 1248 dir = TO; 1249 else if (EQ("srcnet")) 1250 dir = FROM; 1251 next(); 1252 pf_netaddr_match(dir, token); 1253 dir = ANY; 1254 opstack++; 1255 next(); 1256 break; 1257 } 1258 1259 /* 1260 * Give up on anything that's obviously 1261 * not a primary. 1262 */ 1263 if (EQ("and") || EQ("or") || 1264 EQ("not") || EQ("decnet") || EQ("apple") || 1265 EQ("length") || EQ("less") || EQ("greater") || 1266 EQ("port") || EQ("srcport") || EQ("dstport") || 1267 EQ("rpc") || EQ("gateway") || EQ("nofrag") || 1268 EQ("bootp") || EQ("dhcp") || EQ("dhcp6") || 1269 EQ("slp") || EQ("ldap")) { 1270 break; 1271 } 1272 1273 if (EQ("host") || EQ("between") || 1274 tokentype == ALPHA || /* assume its a hostname */ 1275 tokentype == ADDR_IP || 1276 tokentype == ADDR_IP6 || 1277 tokentype == ADDR_ETHER) { 1278 if (EQ("host") || EQ("between")) 1279 next(); 1280 if (eaddr || tokentype == ADDR_ETHER) { 1281 pf_etheraddr_match(dir, token); 1282 } else if (tokentype == ALPHA) { 1283 pf_ipaddr_match(dir, token, IPV4_AND_IPV6); 1284 } else if (tokentype == ADDR_IP) { 1285 pf_ipaddr_match(dir, token, IPV4_ONLY); 1286 } else { 1287 pf_ipaddr_match(dir, token, IPV6_ONLY); 1288 } 1289 dir = ANY; 1290 eaddr = 0; 1291 opstack++; 1292 next(); 1293 break; 1294 } 1295 1296 break; /* unknown token */ 1297 } 1298 } 1299 1300 static void 1301 pf_alternation() 1302 { 1303 int s = opstack; 1304 1305 pf_primary(); 1306 for (;;) { 1307 if (EQ("and")) 1308 next(); 1309 pf_primary(); 1310 if (opstack != s + 2) 1311 break; 1312 pf_emit(ENF_AND); 1313 opstack--; 1314 } 1315 } 1316 1317 static void 1318 pf_expression() 1319 { 1320 pf_alternation(); 1321 while (EQ("or") || EQ(",")) { 1322 if (inBrace) 1323 inBraceOR++; 1324 else 1325 foundOR++; 1326 next(); 1327 pf_alternation(); 1328 pf_emit(ENF_OR); 1329 opstack--; 1330 } 1331 } 1332 1333 /* 1334 * Attempt to compile the expression 1335 * in the string "e". If we can generate 1336 * pf code for it then return 1 - otherwise 1337 * return 0 and leave it up to the user-level 1338 * filter. 1339 */ 1340 int 1341 pf_compile(e, print) 1342 char *e; 1343 int print; 1344 { 1345 char *argstr; 1346 char *sav_str, *ptr, *sav_ptr; 1347 int inBr = 0, aheadOR = 0; 1348 1349 argstr = strdup(e); 1350 sav_str = e; 1351 tkp = argstr; 1352 dir = ANY; 1353 1354 pfp = &pf.Pf_Filter[0]; 1355 if (setjmp(env)) { 1356 return (0); 1357 } 1358 1359 /* 1360 * Set media specific packet offsets that this code uses. 1361 */ 1362 if (interface->mac_type == DL_IB) { 1363 link_header_len = 4; 1364 link_type_offset = 0; 1365 link_dest_offset = link_src_offset = -1; 1366 link_addr_len = 20; 1367 } 1368 1369 next(); 1370 pf_expression(); 1371 1372 if (tokentype != EOL) { 1373 /* 1374 * The idea here is to do as much filtering as possible in 1375 * the kernel. So even if we find a token we don't understand, 1376 * we try to see if we can still set up a portion of the filter 1377 * in the kernel and use the userland filter to filter the 1378 * remaining stuff. Obviously, if our filter expression is of 1379 * type A AND B, we can filter A in kernel and then apply B 1380 * to the packets that got through. The same is not true for 1381 * a filter of type A OR B. We can't apply A first and then B 1382 * on the packets filtered through A. 1383 * 1384 * (We need to keep track of the fact when we find an OR, 1385 * and the fact that we are inside brackets when we find OR. 1386 * The variable 'foundOR' tells us if there was an OR behind, 1387 * 'inBraceOR' tells us if we found an OR before we could find 1388 * the end brace i.e. ')', and variable 'aheadOR' checks if 1389 * there is an OR in the expression ahead. if either of these 1390 * cases become true, we can't split the filtering) 1391 */ 1392 1393 if (foundOR || inBraceOR) { 1394 /* FORGET IN KERNEL FILTERING */ 1395 return (0); 1396 } else { 1397 1398 /* CHECK IF NO OR AHEAD */ 1399 sav_ptr = (char *)((uintptr_t)sav_str + 1400 (uintptr_t)sav_tkp - 1401 (uintptr_t)argstr); 1402 ptr = sav_ptr; 1403 while (*ptr != '\0') { 1404 switch (*ptr) { 1405 case '(': 1406 inBr++; 1407 break; 1408 case ')': 1409 inBr--; 1410 break; 1411 case 'o': 1412 case 'O': 1413 if ((*(ptr + 1) == 'R' || 1414 *(ptr + 1) == 'r') && !inBr) 1415 aheadOR = 1; 1416 break; 1417 case ',': 1418 if (!inBr) 1419 aheadOR = 1; 1420 break; 1421 } 1422 ptr++; 1423 } 1424 if (!aheadOR) { 1425 /* NO OR AHEAD, SPLIT UP THE FILTERING */ 1426 pf.Pf_FilterLen = pfp - &pf.Pf_Filter[0]; 1427 pf.Pf_Priority = 5; 1428 if (print) { 1429 pf_codeprint(&pf.Pf_Filter[0], 1430 pf.Pf_FilterLen); 1431 } 1432 compile(sav_ptr, print); 1433 return (2); 1434 } else 1435 return (0); 1436 } 1437 } 1438 1439 pf.Pf_FilterLen = pfp - &pf.Pf_Filter[0]; 1440 pf.Pf_Priority = 5; /* unimportant, so long as > 2 */ 1441 if (print) { 1442 pf_codeprint(&pf.Pf_Filter[0], pf.Pf_FilterLen); 1443 } 1444 return (1); 1445 } 1446