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