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