1 2 /* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 */ 7 #include "ipf.h" 8 #include "ipt.h" 9 #include <sys/ioctl.h> 10 #include <sys/file.h> 11 12 13 extern char *optarg; 14 extern struct ipread pcap, iptext, iphex; 15 extern struct ifnet *get_unit(char *, int); 16 extern void init_ifp(void); 17 extern ipnat_t *natparse(char *, int); 18 extern hostmap_t **ipf_hm_maptable; 19 extern hostmap_t *ipf_hm_maplist; 20 21 ipfmutex_t ipl_mutex, ipf_auth_mx, ipf_rw, ipf_stinsert; 22 ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; 23 ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw, ipf_frcache; 24 ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_authlk; 25 ipfrwlock_t ipf_tokens; 26 int opts = OPT_DONTOPEN; 27 int use_inet6 = 0; 28 int docksum = 0; 29 int pfil_delayed_copy = 0; 30 int main(int, char *[]); 31 int loadrules(char *, int); 32 int kmemcpy(char *, long, int); 33 int kstrncpy(char *, long, int n); 34 int blockreason; 35 void dumpnat(void *); 36 void dumpgroups(ipf_main_softc_t *); 37 void dumprules(frentry_t *); 38 void drain_log(char *); 39 void fixv4sums(mb_t *, ip_t *); 40 41 int ipftestioctl(int, ioctlcmd_t, ...); 42 int ipnattestioctl(int, ioctlcmd_t, ...); 43 int ipstatetestioctl(int, ioctlcmd_t, ...); 44 int ipauthtestioctl(int, ioctlcmd_t, ...); 45 int ipscantestioctl(int, ioctlcmd_t, ...); 46 int ipsynctestioctl(int, ioctlcmd_t, ...); 47 int ipooltestioctl(int, ioctlcmd_t, ...); 48 49 static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ipftestioctl, 50 ipnattestioctl, 51 ipstatetestioctl, 52 ipauthtestioctl, 53 ipsynctestioctl, 54 ipscantestioctl, 55 ipooltestioctl, 56 NULL }; 57 static ipf_main_softc_t *softc = NULL; 58 59 60 int 61 main(int argc, char *argv[]) 62 { 63 char *datain, *iface, *ifname, *logout; 64 int fd, i, dir, c, loaded, dump, hlen; 65 struct in_addr sip; 66 struct ifnet *ifp; 67 struct ipread *r; 68 mb_t mb, *m, *n; 69 ip_t *ip; 70 71 m = &mb; 72 dir = 0; 73 dump = 0; 74 hlen = 0; 75 loaded = 0; 76 r = &iptext; 77 iface = NULL; 78 logout = NULL; 79 datain = NULL; 80 sip.s_addr = 0; 81 ifname = "anon0"; 82 83 initparse(); 84 85 ipf_load_all(); 86 87 softc = ipf_create_all(NULL); 88 if (softc == NULL) 89 exit(1); 90 91 if (ipf_init_all(softc) == -1) 92 exit(1); 93 94 i = 1; 95 if (ipftestioctl(IPL_LOGIPF, SIOCFRENB, &i) != 0) 96 exit(1); 97 98 while ((c = getopt(argc, argv, "6bCdDF:i:I:l:N:P:or:RS:T:vxX")) != -1) 99 switch (c) 100 { 101 case '6' : 102 #ifdef USE_INET6 103 use_inet6 = 1; 104 #else 105 fprintf(stderr, "IPv6 not supported\n"); 106 exit(1); 107 #endif 108 break; 109 case 'b' : 110 opts |= OPT_BRIEF; 111 break; 112 case 'd' : 113 opts |= OPT_DEBUG; 114 break; 115 case 'C' : 116 docksum = 1; 117 break; 118 case 'D' : 119 dump = 1; 120 break; 121 case 'F' : 122 if (strcasecmp(optarg, "pcap") == 0) 123 r = &pcap; 124 else if (strcasecmp(optarg, "hex") == 0) 125 r = &iphex; 126 else if (strcasecmp(optarg, "text") == 0) 127 r = &iptext; 128 break; 129 case 'i' : 130 datain = optarg; 131 break; 132 case 'I' : 133 ifname = optarg; 134 break; 135 case 'l' : 136 logout = optarg; 137 break; 138 case 'N' : 139 if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl, 140 optarg) == -1) 141 return (-1); 142 loaded = 1; 143 opts |= OPT_NAT; 144 break; 145 case 'o' : 146 opts |= OPT_SAVEOUT; 147 break; 148 case 'P' : 149 if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1) 150 return (-1); 151 loaded = 1; 152 break; 153 case 'r' : 154 if (ipf_parsefile(-1, ipf_addrule, iocfunctions, 155 optarg) == -1) 156 return (-1); 157 loaded = 1; 158 break; 159 case 'S' : 160 sip.s_addr = inet_addr(optarg); 161 break; 162 case 'R' : 163 opts |= OPT_NORESOLVE; 164 break; 165 case 'T' : 166 ipf_dotuning(-1, optarg, ipftestioctl); 167 break; 168 case 'v' : 169 opts |= OPT_VERBOSE; 170 break; 171 case 'x' : 172 opts |= OPT_HEX; 173 break; 174 } 175 176 if (loaded == 0) { 177 (void)fprintf(stderr,"no rules loaded\n"); 178 exit(-1); 179 } 180 181 if (opts & OPT_SAVEOUT) 182 init_ifp(); 183 184 if (datain) 185 fd = (*r->r_open)(datain); 186 else 187 fd = (*r->r_open)("-"); 188 189 if (fd < 0) { 190 perror("error opening input"); 191 exit(-1); 192 } 193 194 m->m_data = (char *)m->mb_buf; 195 while ((i = (*r->r_readip)(m, &iface, &dir)) > 0) { 196 197 if ((iface == NULL) || (*iface == '\0')) 198 iface = ifname; 199 200 ip = MTOD(m, ip_t *); 201 ifp = get_unit(iface, IP_V(ip)); 202 203 if (IP_V(ip) == 4) { 204 if ((r->r_flags & R_DO_CKSUM) || docksum) 205 fixv4sums(m, ip); 206 hlen = IP_HL(ip) << 2; 207 if (sip.s_addr) 208 dir = !(sip.s_addr == ip->ip_src.s_addr); 209 } 210 #ifdef USE_INET6 211 else 212 hlen = sizeof(ip6_t); 213 #endif 214 /* ipfr_slowtimer(); */ 215 blockreason = 0; 216 m = &mb; 217 m->mb_ifp = ifp; 218 m->mb_len = i; 219 i = ipf_check(softc, ip, hlen, ifp, dir, &m); 220 if ((opts & OPT_NAT) == 0) 221 switch (i) 222 { 223 case -4 : 224 (void)printf("preauth"); 225 break; 226 case -3 : 227 (void)printf("account"); 228 break; 229 case -2 : 230 (void)printf("auth"); 231 break; 232 case -1 : 233 (void)printf("block"); 234 break; 235 case 0 : 236 (void)printf("pass"); 237 break; 238 case 1 : 239 if (m == NULL) 240 (void)printf("bad-packet"); 241 else 242 (void)printf("nomatch"); 243 break; 244 case 3 : 245 (void)printf("block return-rst"); 246 break; 247 case 4 : 248 (void)printf("block return-icmp"); 249 break; 250 case 5 : 251 (void)printf("block return-icmp-as-dest"); 252 break; 253 default : 254 (void)printf("recognised( return %#x\n", i)); 255 break; 256 } 257 258 if (!(opts & OPT_BRIEF)) { 259 putchar(' '); 260 if (m != NULL) 261 printpacket(dir, m); 262 else 263 printpacket(dir, &mb); 264 printf("--------------"); 265 } else if ((opts & (OPT_BRIEF|OPT_NAT)) == 266 (OPT_NAT|OPT_BRIEF)) { 267 if (m != NULL) 268 printpacket(dir, m); 269 else 270 PRINTF("%d\n", blockreason); 271 } 272 273 ipf_state_flush(softc, 1, 0); 274 275 if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL)) 276 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 277 278 while ((m != NULL) && (m != &mb)) { 279 n = m->mb_next; 280 freembt(m); 281 m = n; 282 } 283 284 if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF)) 285 putchar('\n'); 286 dir = 0; 287 if (iface != ifname) { 288 free(iface); 289 iface = ifname; 290 } 291 m = &mb; 292 m->mb_data = (char *)m->mb_buf; 293 } 294 295 if (i != 0) 296 fprintf(stderr, "readip failed: %d\n", i); 297 (*r->r_close)(); 298 299 if (logout != NULL) { 300 drain_log(logout); 301 } 302 303 if (dump == 1) { 304 dumpnat(softc->ipf_nat_soft); 305 ipf_state_dump(softc, softc->ipf_state_soft); 306 ipf_lookup_dump(softc, softc->ipf_state_soft); 307 dumpgroups(softc); 308 } 309 310 ipf_fini_all(softc); 311 312 ipf_destroy_all(softc); 313 314 ipf_unload_all(); 315 316 ipf_mutex_clean(); 317 ipf_rwlock_clean(); 318 319 if (getenv("FINDLEAKS")) { 320 fflush(stdout); 321 abort(); 322 } 323 return (0); 324 } 325 326 327 int ipftestioctl(int dev, ioctlcmd_t cmd, ...) 328 { 329 caddr_t data; 330 va_list ap; 331 int i; 332 333 dev = dev; /* gcc -Wextra */ 334 va_start(ap, cmd); 335 data = va_arg(ap, caddr_t); 336 va_end(ap); 337 338 i = ipfioctl(softc, IPL_LOGIPF, cmd, data, FWRITE|FREAD); 339 if (opts & OPT_DEBUG) 340 fprintf(stderr, "ipfioctl(IPF,%#x,%p) = %d (%d)\n", 341 (u_int)cmd, data, i, softc->ipf_interror); 342 if (i != 0) { 343 errno = i; 344 return (-1); 345 } 346 return (0); 347 } 348 349 350 int 351 ipnattestioctl(int dev, ioctlcmd_t cmd, ...) 352 { 353 caddr_t data; 354 va_list ap; 355 int i; 356 357 dev = dev; /* gcc -Wextra */ 358 va_start(ap, cmd); 359 data = va_arg(ap, caddr_t); 360 va_end(ap); 361 362 i = ipfioctl(softc, IPL_LOGNAT, cmd, data, FWRITE|FREAD); 363 if (opts & OPT_DEBUG) 364 fprintf(stderr, "ipfioctl(NAT,%#x,%p) = %d\n", 365 (u_int)cmd, data, i); 366 if (i != 0) { 367 errno = i; 368 return (-1); 369 } 370 return (0); 371 } 372 373 374 int 375 ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) 376 { 377 caddr_t data; 378 va_list ap; 379 int i; 380 381 dev = dev; /* gcc -Wextra */ 382 va_start(ap, cmd); 383 data = va_arg(ap, caddr_t); 384 va_end(ap); 385 386 i = ipfioctl(softc, IPL_LOGSTATE, cmd, data, FWRITE|FREAD); 387 if ((opts & OPT_DEBUG) || (i != 0)) 388 fprintf(stderr, "ipfioctl(STATE,%#x,%p) = %d\n", 389 (u_int)cmd, data, i); 390 if (i != 0) { 391 errno = i; 392 return (-1); 393 } 394 return (0); 395 } 396 397 398 int 399 ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) 400 { 401 caddr_t data; 402 va_list ap; 403 int i; 404 405 dev = dev; /* gcc -Wextra */ 406 va_start(ap, cmd); 407 data = va_arg(ap, caddr_t); 408 va_end(ap); 409 410 i = ipfioctl(softc, IPL_LOGAUTH, cmd, data, FWRITE|FREAD); 411 if ((opts & OPT_DEBUG) || (i != 0)) 412 fprintf(stderr, "ipfioctl(AUTH,%#x,%p) = %d\n", 413 (u_int)cmd, data, i); 414 if (i != 0) { 415 errno = i; 416 return (-1); 417 } 418 return (0); 419 } 420 421 422 int 423 ipscantestioctl(int dev, ioctlcmd_t cmd, ...) 424 { 425 caddr_t data; 426 va_list ap; 427 int i; 428 429 dev = dev; /* gcc -Wextra */ 430 va_start(ap, cmd); 431 data = va_arg(ap, caddr_t); 432 va_end(ap); 433 434 i = ipfioctl(softc, IPL_LOGSCAN, cmd, data, FWRITE|FREAD); 435 if ((opts & OPT_DEBUG) || (i != 0)) 436 fprintf(stderr, "ipfioctl(SCAN,%#x,%p) = %d\n", 437 (u_int)cmd, data, i); 438 if (i != 0) { 439 errno = i; 440 return (-1); 441 } 442 return (0); 443 } 444 445 446 int 447 ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) 448 { 449 caddr_t data; 450 va_list ap; 451 int i; 452 453 dev = dev; /* gcc -Wextra */ 454 va_start(ap, cmd); 455 data = va_arg(ap, caddr_t); 456 va_end(ap); 457 458 i = ipfioctl(softc, IPL_LOGSYNC, cmd, data, FWRITE|FREAD); 459 if ((opts & OPT_DEBUG) || (i != 0)) 460 fprintf(stderr, "ipfioctl(SYNC,%#x,%p) = %d\n", 461 (u_int)cmd, data, i); 462 if (i != 0) { 463 errno = i; 464 return (-1); 465 } 466 return (0); 467 } 468 469 470 int 471 ipooltestioctl(int dev, ioctlcmd_t cmd, ...) 472 { 473 caddr_t data; 474 va_list ap; 475 int i; 476 477 dev = dev; /* gcc -Wextra */ 478 va_start(ap, cmd); 479 data = va_arg(ap, caddr_t); 480 va_end(ap); 481 482 i = ipfioctl(softc, IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); 483 if ((opts & OPT_DEBUG) || (i != 0)) 484 fprintf(stderr, "ipfioctl(POOL,%#x,%p) = %d (%d)\n", 485 (u_int)cmd, data, i, softc->ipf_interror); 486 if (i != 0) { 487 errno = i; 488 return (-1); 489 } 490 return (0); 491 } 492 493 494 int 495 kmemcpy(char *addr, long offset, int size) 496 { 497 bcopy((char *)offset, addr, size); 498 return (0); 499 } 500 501 502 int 503 kstrncpy(char *buf, long pos, int n) 504 { 505 char *ptr; 506 507 ptr = (char *)pos; 508 509 while ((n > 0) && (*buf++ = *ptr++)) 510 ; 511 return (0); 512 } 513 514 515 /* 516 * Display the built up NAT table rules and mapping entries. 517 */ 518 void 519 dumpnat(void *arg) 520 { 521 ipf_nat_softc_t *softn = arg; 522 hostmap_t *hm; 523 ipnat_t *ipn; 524 nat_t *nat; 525 526 printf("List of active MAP/Redirect filters:\n"); 527 for (ipn = softn->ipf_nat_list; ipn != NULL; ipn = ipn->in_next) 528 printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); 529 printf("\nList of active sessions:\n"); 530 for (nat = softn->ipf_nat_instances; nat; nat = nat->nat_next) { 531 printactivenat(nat, opts, 0); 532 if (nat->nat_aps) 533 printf("\tproxy active\n"); 534 } 535 536 printf("\nHostmap table:\n"); 537 for (hm = softn->ipf_hm_maplist; hm != NULL; hm = hm->hm_next) 538 printhostmap(hm, hm->hm_hv); 539 } 540 541 542 void 543 dumpgroups(ipf_main_softc_t *softc) 544 { 545 frgroup_t *fg; 546 int i; 547 548 printf("List of groups configured (set 0)\n"); 549 for (i = 0; i < IPL_LOGSIZE; i++) 550 for (fg = softc->ipf_groups[i][0]; fg != NULL; 551 fg = fg->fg_next) { 552 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 553 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 554 dumprules(fg->fg_start); 555 } 556 557 printf("List of groups configured (set 1)\n"); 558 for (i = 0; i < IPL_LOGSIZE; i++) 559 for (fg = softc->ipf_groups[i][1]; fg != NULL; 560 fg = fg->fg_next) { 561 printf("Dev.%d. Group %s Ref %d Flags %#x\n", 562 i, fg->fg_name, fg->fg_ref, fg->fg_flags); 563 dumprules(fg->fg_start); 564 } 565 566 printf("Rules configured (set 0, in)\n"); 567 dumprules(softc->ipf_rules[0][0]); 568 printf("Rules configured (set 0, out)\n"); 569 dumprules(softc->ipf_rules[1][0]); 570 printf("Rules configured (set 1, in)\n"); 571 dumprules(softc->ipf_rules[0][1]); 572 printf("Rules configured (set 1, out)\n"); 573 dumprules(softc->ipf_rules[1][1]); 574 575 printf("Accounting rules configured (set 0, in)\n"); 576 dumprules(softc->ipf_acct[0][0]); 577 printf("Accounting rules configured (set 0, out)\n"); 578 dumprules(softc->ipf_acct[0][1]); 579 printf("Accounting rules configured (set 1, in)\n"); 580 dumprules(softc->ipf_acct[1][0]); 581 printf("Accounting rules configured (set 1, out)\n"); 582 dumprules(softc->ipf_acct[1][1]); 583 } 584 585 void 586 dumprules(frentry_t *rulehead) 587 { 588 frentry_t *fr; 589 590 for (fr = rulehead; fr != NULL; fr = fr->fr_next) { 591 #ifdef USE_QUAD_T 592 printf("%"PRIu64" ",(unsigned long long)fr->fr_hits); 593 #else 594 printf("%ld ", fr->fr_hits); 595 #endif 596 printfr(fr, ipftestioctl); 597 } 598 } 599 600 601 void 602 drain_log(char *filename) 603 { 604 char buffer[DEFAULT_IPFLOGSIZE]; 605 struct iovec iov; 606 struct uio uio; 607 size_t resid; 608 int fd, i; 609 610 fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); 611 if (fd == -1) { 612 perror("drain_log:open"); 613 return; 614 } 615 616 for (i = 0; i <= IPL_LOGMAX; i++) 617 while (1) { 618 bzero((char *)&iov, sizeof(iov)); 619 iov.iov_base = buffer; 620 iov.iov_len = sizeof(buffer); 621 622 bzero((char *)&uio, sizeof(uio)); 623 uio.uio_iov = &iov; 624 uio.uio_iovcnt = 1; 625 uio.uio_resid = iov.iov_len; 626 resid = uio.uio_resid; 627 628 if (ipf_log_read(softc, i, &uio) == 0) { 629 /* 630 * If nothing was read then break out. 631 */ 632 if (uio.uio_resid == resid) 633 break; 634 write(fd, buffer, resid - uio.uio_resid); 635 } else 636 break; 637 } 638 639 close(fd); 640 } 641 642 643 void 644 fixv4sums(mb_t *m, ip_t *ip) 645 { 646 u_char *csump, *hdr, p; 647 fr_info_t tmp; 648 int len; 649 650 p = 0; 651 len = 0; 652 bzero((char *)&tmp, sizeof(tmp)); 653 654 csump = (u_char *)ip; 655 if (IP_V(ip) == 4) { 656 ip->ip_sum = 0; 657 ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); 658 tmp.fin_hlen = IP_HL(ip) << 2; 659 csump += IP_HL(ip) << 2; 660 p = ip->ip_p; 661 len = ntohs(ip->ip_len); 662 #ifdef USE_INET6 663 } else if (IP_V(ip) == 6) { 664 tmp.fin_hlen = sizeof(ip6_t); 665 csump += sizeof(ip6_t); 666 p = ((ip6_t *)ip)->ip6_nxt; 667 len = ntohs(((ip6_t *)ip)->ip6_plen); 668 len += sizeof(ip6_t); 669 #endif 670 } 671 tmp.fin_plen = len; 672 tmp.fin_dlen = len - tmp.fin_hlen; 673 674 switch (p) 675 { 676 case IPPROTO_TCP : 677 hdr = csump; 678 csump += offsetof(tcphdr_t, th_sum); 679 break; 680 case IPPROTO_UDP : 681 hdr = csump; 682 csump += offsetof(udphdr_t, uh_sum); 683 break; 684 case IPPROTO_ICMP : 685 hdr = csump; 686 csump += offsetof(icmphdr_t, icmp_cksum); 687 break; 688 default : 689 csump = NULL; 690 hdr = NULL; 691 break; 692 } 693 if (hdr != NULL) { 694 tmp.fin_m = m; 695 tmp.fin_mp = &m; 696 tmp.fin_dp = hdr; 697 tmp.fin_ip = ip; 698 tmp.fin_plen = len; 699 *csump = 0; 700 *(u_short *)csump = fr_cksum(&tmp, ip, p, hdr); 701 } 702 } 703 704 void 705 ip_fillid(struct ip *ip) 706 { 707 static uint16_t ip_id; 708 709 ip->ip_id = ip_id++; 710 } 711