1 2 /* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 * 7 * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) 8 */ 9 #include <stdio.h> 10 #include <string.h> 11 #include <fcntl.h> 12 #include <errno.h> 13 #include <sys/types.h> 14 #if !defined(__SVR4) 15 #include <strings.h> 16 #else 17 #include <sys/byteorder.h> 18 #endif 19 #include <sys/time.h> 20 #include <sys/param.h> 21 #include <stdlib.h> 22 #include <unistd.h> 23 #include <stddef.h> 24 #include <sys/file.h> 25 #define _KERNEL 26 #include <sys/uio.h> 27 #undef _KERNEL 28 #include <sys/socket.h> 29 #include <sys/ioctl.h> 30 #if defined(sun) && defined(__SVR4) 31 # include <sys/ioccom.h> 32 # include <sys/sysmacros.h> 33 #endif 34 #include <netinet/in.h> 35 #include <netinet/in_systm.h> 36 #include <netinet/ip.h> 37 #include <netinet/tcp.h> 38 #include <net/if.h> 39 #include <netdb.h> 40 #include <arpa/nameser.h> 41 #include <arpa/inet.h> 42 #include <resolv.h> 43 #include <ctype.h> 44 # include <nlist.h> 45 #include "ipf.h" 46 #include "netinet/ipl.h" 47 #include "kmem.h" 48 49 50 # define STRERROR(x) strerror(x) 51 52 53 54 #if SOLARIS 55 #define bzero(a,b) memset(a,0,b) 56 #endif 57 int use_inet6 = 0; 58 59 extern char *optarg; 60 61 void dostats(int, natstat_t *, int, int, int *); 62 void dotable(natstat_t *, int, int, int, char *); 63 void flushtable(int, int, int *); 64 void usage(char *); 65 int main(int, char*[]); 66 void showhostmap(natstat_t *nsp); 67 void natstat_dead(natstat_t *, char *); 68 void dostats_live(int, natstat_t *, int, int *); 69 void showhostmap_dead(natstat_t *); 70 void showhostmap_live(int, natstat_t *); 71 void dostats_dead(natstat_t *, int, int *); 72 int nat_matcharray(nat_t *, int *); 73 74 int opts; 75 int nohdrfields = 0; 76 wordtab_t *nat_fields = NULL; 77 78 void 79 usage(char *name) 80 { 81 fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name); 82 exit(1); 83 } 84 85 86 int 87 main(int argc, char *argv[]) 88 { 89 int fd, c, mode, *natfilter; 90 char *file, *core, *kernel; 91 natstat_t ns, *nsp; 92 ipfobj_t obj; 93 94 fd = -1; 95 opts = 0; 96 nsp = &ns; 97 file = NULL; 98 core = NULL; 99 kernel = NULL; 100 mode = O_RDWR; 101 natfilter = NULL; 102 103 assigndefined(getenv("IPNAT_PREDEFINED")); 104 105 while ((c = getopt(argc, argv, "CdFf:hlm:M:N:nO:prRsv")) != -1) 106 switch (c) 107 { 108 case 'C' : 109 opts |= OPT_CLEAR; 110 break; 111 case 'd' : 112 opts |= OPT_DEBUG; 113 break; 114 case 'f' : 115 file = optarg; 116 break; 117 case 'F' : 118 opts |= OPT_FLUSH; 119 break; 120 case 'h' : 121 opts |=OPT_HITS; 122 break; 123 case 'l' : 124 opts |= OPT_LIST; 125 mode = O_RDONLY; 126 break; 127 case 'm' : 128 natfilter = parseipfexpr(optarg, NULL); 129 break; 130 case 'M' : 131 core = optarg; 132 break; 133 case 'N' : 134 kernel = optarg; 135 break; 136 case 'n' : 137 opts |= OPT_DONOTHING|OPT_DONTOPEN; 138 mode = O_RDONLY; 139 break; 140 case 'O' : 141 nat_fields = parsefields(natfields, optarg); 142 break; 143 case 'p' : 144 opts |= OPT_PURGE; 145 break; 146 case 'R' : 147 opts |= OPT_NORESOLVE; 148 break; 149 case 'r' : 150 opts |= OPT_REMOVE; 151 break; 152 case 's' : 153 opts |= OPT_STAT; 154 mode = O_RDONLY; 155 break; 156 case 'v' : 157 opts |= OPT_VERBOSE; 158 break; 159 default : 160 usage(argv[0]); 161 } 162 163 if (((opts & OPT_PURGE) != 0) && ((opts & OPT_REMOVE) == 0)) { 164 (void) fprintf(stderr, "%s: -p must be used with -r\n", 165 argv[0]); 166 exit(1); 167 } 168 169 initparse(); 170 171 if ((kernel != NULL) || (core != NULL)) { 172 (void) setgid(getgid()); 173 (void) setuid(getuid()); 174 } 175 176 if (!(opts & OPT_DONOTHING)) { 177 if (((fd = open(IPNAT_NAME, mode)) == -1) && 178 ((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) { 179 (void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME, 180 STRERROR(errno)); 181 exit(1); 182 } 183 } 184 185 bzero((char *)&ns, sizeof(ns)); 186 187 if ((opts & OPT_DONOTHING) == 0) { 188 if (checkrev(IPL_NAME) == -1) { 189 fprintf(stderr, "User/kernel version check failed\n"); 190 exit(1); 191 } 192 } 193 194 if (!(opts & OPT_DONOTHING) && (kernel == NULL) && (core == NULL)) { 195 bzero((char *)&obj, sizeof(obj)); 196 obj.ipfo_rev = IPFILTER_VERSION; 197 obj.ipfo_type = IPFOBJ_NATSTAT; 198 obj.ipfo_size = sizeof(*nsp); 199 obj.ipfo_ptr = (void *)nsp; 200 if (ioctl(fd, SIOCGNATS, &obj) == -1) { 201 ipferror(fd, "ioctl(SIOCGNATS)"); 202 exit(1); 203 } 204 (void) setgid(getgid()); 205 (void) setuid(getuid()); 206 } else if ((kernel != NULL) || (core != NULL)) { 207 if (openkmem(kernel, core) == -1) 208 exit(1); 209 210 natstat_dead(nsp, kernel); 211 if (opts & (OPT_LIST|OPT_STAT)) 212 dostats(fd, nsp, opts, 0, natfilter); 213 exit(0); 214 } 215 216 if (opts & (OPT_FLUSH|OPT_CLEAR)) 217 flushtable(fd, opts, natfilter); 218 if (file) { 219 return (ipnat_parsefile(fd, ipnat_addrule, ioctl, file)); 220 } 221 if (opts & (OPT_LIST|OPT_STAT)) 222 dostats(fd, nsp, opts, 1, natfilter); 223 return (0); 224 } 225 226 227 /* 228 * Read NAT statistic information in using a symbol table and memory file 229 * rather than doing ioctl's. 230 */ 231 void 232 natstat_dead(natstat_t *nsp, char *kernel) 233 { 234 struct nlist nat_nlist[10] = { 235 { "nat_table" }, /* 0 */ 236 { "nat_list" }, 237 { "maptable" }, 238 { "ipf_nattable_sz" }, 239 { "ipf_natrules_sz" }, 240 { "ipf_rdrrules_sz" }, /* 5 */ 241 { "ipf_hostmap_sz" }, 242 { "nat_instances" }, 243 { NULL } 244 }; 245 void *tables[2]; 246 247 if (nlist(kernel, nat_nlist) == -1) { 248 fprintf(stderr, "nlist error\n"); 249 return; 250 } 251 252 /* 253 * Normally the ioctl copies all of these values into the structure 254 * for us, before returning it to userland, so here we must copy each 255 * one in individually. 256 */ 257 kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables)); 258 nsp->ns_side[0].ns_table = tables[0]; 259 nsp->ns_side[1].ns_table = tables[1]; 260 261 kmemcpy((char *)&nsp->ns_list, nat_nlist[1].n_value, 262 sizeof(nsp->ns_list)); 263 kmemcpy((char *)&nsp->ns_maptable, nat_nlist[2].n_value, 264 sizeof(nsp->ns_maptable)); 265 kmemcpy((char *)&nsp->ns_nattab_sz, nat_nlist[3].n_value, 266 sizeof(nsp->ns_nattab_sz)); 267 kmemcpy((char *)&nsp->ns_rultab_sz, nat_nlist[4].n_value, 268 sizeof(nsp->ns_rultab_sz)); 269 kmemcpy((char *)&nsp->ns_rdrtab_sz, nat_nlist[5].n_value, 270 sizeof(nsp->ns_rdrtab_sz)); 271 kmemcpy((char *)&nsp->ns_hostmap_sz, nat_nlist[6].n_value, 272 sizeof(nsp->ns_hostmap_sz)); 273 kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value, 274 sizeof(nsp->ns_instances)); 275 } 276 277 278 /* 279 * Issue an ioctl to flush either the NAT rules table or the active mapping 280 * table or both. 281 */ 282 void 283 flushtable(int fd, int opts, int *match) 284 { 285 int n = 0; 286 287 if (opts & OPT_FLUSH) { 288 n = 0; 289 if (!(opts & OPT_DONOTHING)) { 290 if (match != NULL) { 291 ipfobj_t obj; 292 293 obj.ipfo_rev = IPFILTER_VERSION; 294 obj.ipfo_size = match[0] * sizeof(int); 295 obj.ipfo_type = IPFOBJ_IPFEXPR; 296 obj.ipfo_ptr = match; 297 if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) { 298 ipferror(fd, "ioctl(SIOCMATCHFLUSH)"); 299 n = -1; 300 } else { 301 n = obj.ipfo_retval; 302 } 303 } else if (ioctl(fd, SIOCIPFFL, &n) == -1) { 304 ipferror(fd, "ioctl(SIOCIPFFL)"); 305 n = -1; 306 } 307 } 308 if (n >= 0) 309 printf("%d entries flushed from NAT table\n", n); 310 } 311 312 if (opts & OPT_CLEAR) { 313 n = 1; 314 if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) 315 ipferror(fd, "ioctl(SIOCCNATL)"); 316 else 317 printf("%d entries flushed from NAT list\n", n); 318 } 319 } 320 321 322 /* 323 * Display NAT statistics. 324 */ 325 void 326 dostats_dead(natstat_t *nsp, int opts, int *filter) 327 { 328 nat_t *np, nat; 329 ipnat_t ipn; 330 int i; 331 332 if (nat_fields == NULL) { 333 printf("List of active MAP/Redirect filters:\n"); 334 while (nsp->ns_list) { 335 if (kmemcpy((char *)&ipn, (long)nsp->ns_list, 336 sizeof(ipn))) { 337 perror("kmemcpy"); 338 break; 339 } 340 if (opts & OPT_HITS) 341 printf("%lu ", ipn.in_hits); 342 printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); 343 nsp->ns_list = ipn.in_next; 344 } 345 } 346 347 if (nat_fields == NULL) { 348 printf("\nList of active sessions:\n"); 349 350 } else if (nohdrfields == 0) { 351 for (i = 0; nat_fields[i].w_value != 0; i++) { 352 printfieldhdr(natfields, nat_fields + i); 353 if (nat_fields[i + 1].w_value != 0) 354 printf("\t"); 355 } 356 printf("\n"); 357 } 358 359 for (np = nsp->ns_instances; np; np = nat.nat_next) { 360 if (kmemcpy((char *)&nat, (long)np, sizeof(nat))) 361 break; 362 if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0)) 363 continue; 364 if (nat_fields != NULL) { 365 for (i = 0; nat_fields[i].w_value != 0; i++) { 366 printnatfield(&nat, nat_fields[i].w_value); 367 if (nat_fields[i + 1].w_value != 0) 368 printf("\t"); 369 } 370 printf("\n"); 371 } else { 372 printactivenat(&nat, opts, nsp->ns_ticks); 373 if (nat.nat_aps) { 374 int proto; 375 376 if (nat.nat_dir & NAT_OUTBOUND) 377 proto = nat.nat_pr[1]; 378 else 379 proto = nat.nat_pr[0]; 380 printaps(nat.nat_aps, opts, proto); 381 } 382 } 383 } 384 385 if (opts & OPT_VERBOSE) 386 showhostmap_dead(nsp); 387 } 388 389 390 void 391 dotable(natstat_t *nsp, int fd, int alive, int which, char *side) 392 { 393 int sz, i, used, maxlen, minlen, totallen; 394 ipftable_t table; 395 u_int *buckets; 396 ipfobj_t obj; 397 398 sz = sizeof(*buckets) * nsp->ns_nattab_sz; 399 buckets = (u_int *)malloc(sz); 400 if (buckets == NULL) { 401 fprintf(stderr, 402 "cannot allocate memory (%d) for buckets\n", sz); 403 return; 404 } 405 406 obj.ipfo_rev = IPFILTER_VERSION; 407 obj.ipfo_type = IPFOBJ_GTABLE; 408 obj.ipfo_size = sizeof(table); 409 obj.ipfo_ptr = &table; 410 411 if (which == 0) { 412 table.ita_type = IPFTABLE_BUCKETS_NATIN; 413 } else if (which == 1) { 414 table.ita_type = IPFTABLE_BUCKETS_NATOUT; 415 } 416 table.ita_table = buckets; 417 418 if (alive) { 419 if (ioctl(fd, SIOCGTABL, &obj) != 0) { 420 ipferror(fd, "SIOCFTABL"); 421 free(buckets); 422 return; 423 } 424 } else { 425 if (kmemcpy((char *)buckets, (u_long)nsp->ns_nattab_sz, sz)) { 426 free(buckets); 427 return; 428 } 429 } 430 431 minlen = nsp->ns_side[which].ns_inuse; 432 totallen = 0; 433 maxlen = 0; 434 used = 0; 435 436 for (i = 0; i < nsp->ns_nattab_sz; i++) { 437 if (buckets[i] > maxlen) 438 maxlen = buckets[i]; 439 if (buckets[i] < minlen) 440 minlen = buckets[i]; 441 if (buckets[i] != 0) 442 used++; 443 totallen += buckets[i]; 444 } 445 446 printf("%d%%\thash efficiency %s\n", 447 totallen ? used * 100 / totallen : 0, side); 448 printf("%2.2f%%\tbucket usage %s\n", 449 ((float)used / nsp->ns_nattab_sz) * 100.0, side); 450 printf("%d\tminimal length %s\n", minlen, side); 451 printf("%d\tmaximal length %s\n", maxlen, side); 452 printf("%.3f\taverage length %s\n", 453 used ? ((float)totallen / used) : 0.0, side); 454 455 free(buckets); 456 } 457 458 459 void 460 dostats(int fd, natstat_t *nsp, int opts, int alive, int *filter) 461 { 462 /* 463 * Show statistics ? 464 */ 465 if (opts & OPT_STAT) { 466 printnatside("in", &nsp->ns_side[0]); 467 dotable(nsp, fd, alive, 0, "in"); 468 469 printnatside("out", &nsp->ns_side[1]); 470 dotable(nsp, fd, alive, 1, "out"); 471 472 printf("%lu\tlog successes\n", nsp->ns_side[0].ns_log); 473 printf("%lu\tlog failures\n", nsp->ns_side[1].ns_log); 474 printf("%lu\tadded in\n%lu\tadded out\n", 475 nsp->ns_side[0].ns_added, 476 nsp->ns_side[1].ns_added); 477 printf("%u\tactive\n", nsp->ns_active); 478 printf("%lu\ttransparent adds\n", nsp->ns_addtrpnt); 479 printf("%lu\tdivert build\n", nsp->ns_divert_build); 480 printf("%lu\texpired\n", nsp->ns_expire); 481 printf("%lu\tflush all\n", nsp->ns_flush_all); 482 printf("%lu\tflush closing\n", nsp->ns_flush_closing); 483 printf("%lu\tflush queue\n", nsp->ns_flush_queue); 484 printf("%lu\tflush state\n", nsp->ns_flush_state); 485 printf("%lu\tflush timeout\n", nsp->ns_flush_timeout); 486 printf("%lu\thostmap new\n", nsp->ns_hm_new); 487 printf("%lu\thostmap fails\n", nsp->ns_hm_newfail); 488 printf("%lu\thostmap add\n", nsp->ns_hm_addref); 489 printf("%lu\thostmap NULL rule\n", nsp->ns_hm_nullnp); 490 printf("%lu\tlog ok\n", nsp->ns_log_ok); 491 printf("%lu\tlog fail\n", nsp->ns_log_fail); 492 printf("%u\torphan count\n", nsp->ns_orphans); 493 printf("%u\trule count\n", nsp->ns_rules); 494 printf("%u\tmap rules\n", nsp->ns_rules_map); 495 printf("%u\trdr rules\n", nsp->ns_rules_rdr); 496 printf("%u\twilds\n", nsp->ns_wilds); 497 if (opts & OPT_VERBOSE) 498 printf("list %p\n", nsp->ns_list); 499 } 500 501 if (opts & OPT_LIST) { 502 if (alive) 503 dostats_live(fd, nsp, opts, filter); 504 else 505 dostats_dead(nsp, opts, filter); 506 } 507 } 508 509 510 /* 511 * Display NAT statistics. 512 */ 513 void 514 dostats_live(int fd, natstat_t *nsp, int opts, int *filter) 515 { 516 ipfgeniter_t iter; 517 char buffer[2000]; 518 ipfobj_t obj; 519 ipnat_t *ipn; 520 nat_t nat; 521 int i; 522 523 bzero((char *)&obj, sizeof(obj)); 524 obj.ipfo_rev = IPFILTER_VERSION; 525 obj.ipfo_type = IPFOBJ_GENITER; 526 obj.ipfo_size = sizeof(iter); 527 obj.ipfo_ptr = &iter; 528 529 iter.igi_type = IPFGENITER_IPNAT; 530 iter.igi_nitems = 1; 531 iter.igi_data = buffer; 532 ipn = (ipnat_t *)buffer; 533 534 /* 535 * Show list of NAT rules and NAT sessions ? 536 */ 537 if (nat_fields == NULL) { 538 printf("List of active MAP/Redirect filters:\n"); 539 while (nsp->ns_list) { 540 if (ioctl(fd, SIOCGENITER, &obj) == -1) 541 break; 542 if (opts & OPT_HITS) 543 printf("%lu ", ipn->in_hits); 544 printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); 545 nsp->ns_list = ipn->in_next; 546 } 547 } 548 549 if (nat_fields == NULL) { 550 printf("\nList of active sessions:\n"); 551 552 } else if (nohdrfields == 0) { 553 for (i = 0; nat_fields[i].w_value != 0; i++) { 554 printfieldhdr(natfields, nat_fields + i); 555 if (nat_fields[i + 1].w_value != 0) 556 printf("\t"); 557 } 558 printf("\n"); 559 } 560 561 i = IPFGENITER_IPNAT; 562 (void) ioctl(fd,SIOCIPFDELTOK, &i); 563 564 565 iter.igi_type = IPFGENITER_NAT; 566 iter.igi_nitems = 1; 567 iter.igi_data = &nat; 568 569 while (nsp->ns_instances != NULL) { 570 if (ioctl(fd, SIOCGENITER, &obj) == -1) 571 break; 572 if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0)) 573 continue; 574 if (nat_fields != NULL) { 575 for (i = 0; nat_fields[i].w_value != 0; i++) { 576 printnatfield(&nat, nat_fields[i].w_value); 577 if (nat_fields[i + 1].w_value != 0) 578 printf("\t"); 579 } 580 printf("\n"); 581 } else { 582 printactivenat(&nat, opts, nsp->ns_ticks); 583 if (nat.nat_aps) { 584 int proto; 585 586 if (nat.nat_dir & NAT_OUTBOUND) 587 proto = nat.nat_pr[1]; 588 else 589 proto = nat.nat_pr[0]; 590 printaps(nat.nat_aps, opts, proto); 591 } 592 } 593 nsp->ns_instances = nat.nat_next; 594 } 595 596 if (opts & OPT_VERBOSE) 597 showhostmap_live(fd, nsp); 598 599 i = IPFGENITER_NAT; 600 (void) ioctl(fd,SIOCIPFDELTOK, &i); 601 } 602 603 604 /* 605 * Display the active host mapping table. 606 */ 607 void 608 showhostmap_dead(natstat_t *nsp) 609 { 610 hostmap_t hm, *hmp, **maptable; 611 u_int hv; 612 613 printf("\nList of active host mappings:\n"); 614 615 maptable = (hostmap_t **)malloc(sizeof(hostmap_t *) * 616 nsp->ns_hostmap_sz); 617 if (kmemcpy((char *)maptable, (u_long)nsp->ns_maptable, 618 sizeof(hostmap_t *) * nsp->ns_hostmap_sz)) { 619 perror("kmemcpy (maptable)"); 620 return; 621 } 622 623 for (hv = 0; hv < nsp->ns_hostmap_sz; hv++) { 624 hmp = maptable[hv]; 625 626 while (hmp) { 627 if (kmemcpy((char *)&hm, (u_long)hmp, sizeof(hm))) { 628 perror("kmemcpy (hostmap)"); 629 return; 630 } 631 632 printhostmap(&hm, hv); 633 hmp = hm.hm_next; 634 } 635 } 636 free(maptable); 637 } 638 639 640 /* 641 * Display the active host mapping table. 642 */ 643 void 644 showhostmap_live(int fd, natstat_t *nsp) 645 { 646 ipfgeniter_t iter; 647 hostmap_t hm; 648 ipfobj_t obj; 649 int i; 650 651 bzero((char *)&obj, sizeof(obj)); 652 obj.ipfo_rev = IPFILTER_VERSION; 653 obj.ipfo_type = IPFOBJ_GENITER; 654 obj.ipfo_size = sizeof(iter); 655 obj.ipfo_ptr = &iter; 656 657 iter.igi_type = IPFGENITER_HOSTMAP; 658 iter.igi_nitems = 1; 659 iter.igi_data = &hm; 660 661 printf("\nList of active host mappings:\n"); 662 663 while (nsp->ns_maplist != NULL) { 664 if (ioctl(fd, SIOCGENITER, &obj) == -1) 665 break; 666 printhostmap(&hm, hm.hm_hv); 667 nsp->ns_maplist = hm.hm_next; 668 } 669 670 i = IPFGENITER_HOSTMAP; 671 (void) ioctl(fd,SIOCIPFDELTOK, &i); 672 } 673 674 675 int 676 nat_matcharray(nat_t *nat, int *array) 677 { 678 int i, n, *x, rv, p; 679 ipfexp_t *e; 680 681 rv = 0; 682 n = array[0]; 683 x = array + 1; 684 685 for (; n > 0; x += 3 + x[3], rv = 0) { 686 e = (ipfexp_t *)x; 687 if (e->ipfe_cmd == IPF_EXP_END) 688 break; 689 n -= e->ipfe_size; 690 691 p = e->ipfe_cmd >> 16; 692 if ((p != 0) && (p != nat->nat_pr[1])) 693 break; 694 695 switch (e->ipfe_cmd) 696 { 697 case IPF_EXP_IP_PR : 698 for (i = 0; !rv && i < e->ipfe_narg; i++) { 699 rv |= (nat->nat_pr[1] == e->ipfe_arg0[i]); 700 } 701 break; 702 703 case IPF_EXP_IP_SRCADDR : 704 if (nat->nat_v[0] != 4) 705 break; 706 for (i = 0; !rv && i < e->ipfe_narg; i++) { 707 rv |= ((nat->nat_osrcaddr & 708 e->ipfe_arg0[i * 2 + 1]) == 709 e->ipfe_arg0[i * 2]) || 710 ((nat->nat_nsrcaddr & 711 e->ipfe_arg0[i * 2 + 1]) == 712 e->ipfe_arg0[i * 2]); 713 } 714 break; 715 716 case IPF_EXP_IP_DSTADDR : 717 if (nat->nat_v[0] != 4) 718 break; 719 for (i = 0; !rv && i < e->ipfe_narg; i++) { 720 rv |= ((nat->nat_odstaddr & 721 e->ipfe_arg0[i * 2 + 1]) == 722 e->ipfe_arg0[i * 2]) || 723 ((nat->nat_ndstaddr & 724 e->ipfe_arg0[i * 2 + 1]) == 725 e->ipfe_arg0[i * 2]); 726 } 727 break; 728 729 case IPF_EXP_IP_ADDR : 730 if (nat->nat_v[0] != 4) 731 break; 732 for (i = 0; !rv && i < e->ipfe_narg; i++) { 733 rv |= ((nat->nat_osrcaddr & 734 e->ipfe_arg0[i * 2 + 1]) == 735 e->ipfe_arg0[i * 2]) || 736 ((nat->nat_nsrcaddr & 737 e->ipfe_arg0[i * 2 + 1]) == 738 e->ipfe_arg0[i * 2]) || 739 ((nat->nat_odstaddr & 740 e->ipfe_arg0[i * 2 + 1]) == 741 e->ipfe_arg0[i * 2]) || 742 ((nat->nat_ndstaddr & 743 e->ipfe_arg0[i * 2 + 1]) == 744 e->ipfe_arg0[i * 2]); 745 } 746 break; 747 748 #ifdef USE_INET6 749 case IPF_EXP_IP6_SRCADDR : 750 if (nat->nat_v[0] != 6) 751 break; 752 for (i = 0; !rv && i < e->ipfe_narg; i++) { 753 rv |= IP6_MASKEQ(&nat->nat_osrc6, 754 &e->ipfe_arg0[i * 8 + 4], 755 &e->ipfe_arg0[i * 8]) || 756 IP6_MASKEQ(&nat->nat_nsrc6, 757 &e->ipfe_arg0[i * 8 + 4], 758 &e->ipfe_arg0[i * 8]); 759 } 760 break; 761 762 case IPF_EXP_IP6_DSTADDR : 763 if (nat->nat_v[0] != 6) 764 break; 765 for (i = 0; !rv && i < e->ipfe_narg; i++) { 766 rv |= IP6_MASKEQ(&nat->nat_odst6, 767 &e->ipfe_arg0[i * 8 + 4], 768 &e->ipfe_arg0[i * 8]) || 769 IP6_MASKEQ(&nat->nat_ndst6, 770 &e->ipfe_arg0[i * 8 + 4], 771 &e->ipfe_arg0[i * 8]); 772 } 773 break; 774 775 case IPF_EXP_IP6_ADDR : 776 if (nat->nat_v[0] != 6) 777 break; 778 for (i = 0; !rv && i < e->ipfe_narg; i++) { 779 rv |= IP6_MASKEQ(&nat->nat_osrc6, 780 &e->ipfe_arg0[i * 8 + 4], 781 &e->ipfe_arg0[i * 8]) || 782 IP6_MASKEQ(&nat->nat_nsrc6, 783 &e->ipfe_arg0[i * 8 + 4], 784 &e->ipfe_arg0[i * 8]) || 785 IP6_MASKEQ(&nat->nat_odst6, 786 &e->ipfe_arg0[i * 8 + 4], 787 &e->ipfe_arg0[i * 8]) || 788 IP6_MASKEQ(&nat->nat_ndst6, 789 &e->ipfe_arg0[i * 8 + 4], 790 &e->ipfe_arg0[i * 8]); 791 } 792 break; 793 #endif 794 795 case IPF_EXP_UDP_PORT : 796 case IPF_EXP_TCP_PORT : 797 for (i = 0; !rv && i < e->ipfe_narg; i++) { 798 rv |= (nat->nat_osport == e->ipfe_arg0[i]) || 799 (nat->nat_nsport == e->ipfe_arg0[i]) || 800 (nat->nat_odport == e->ipfe_arg0[i]) || 801 (nat->nat_ndport == e->ipfe_arg0[i]); 802 } 803 break; 804 805 case IPF_EXP_UDP_SPORT : 806 case IPF_EXP_TCP_SPORT : 807 for (i = 0; !rv && i < e->ipfe_narg; i++) { 808 rv |= (nat->nat_osport == e->ipfe_arg0[i]) || 809 (nat->nat_nsport == e->ipfe_arg0[i]); 810 } 811 break; 812 813 case IPF_EXP_UDP_DPORT : 814 case IPF_EXP_TCP_DPORT : 815 for (i = 0; !rv && i < e->ipfe_narg; i++) { 816 rv |= (nat->nat_odport == e->ipfe_arg0[i]) || 817 (nat->nat_ndport == e->ipfe_arg0[i]); 818 } 819 break; 820 } 821 rv ^= e->ipfe_not; 822 823 if (rv == 0) 824 break; 825 } 826 827 return (rv); 828 } 829