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