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