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