1/* $FreeBSD$ */ 2 3/* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * $Id$ 9 */ 10#if !defined(lint) 11static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 12static const char rcsid[] = "@(#)$Id$"; 13#endif 14 15#include "ipf.h" 16#include "md5.h" 17#include "ipt.h" 18 19ipf_main_softc_t ipfmain; 20 21static struct ifnet **ifneta = NULL; 22static int nifs = 0; 23 24struct rtentry; 25 26static void ipf_setifpaddr(struct ifnet *, char *); 27void init_ifp(void); 28static int no_output(struct ifnet *, struct mbuf *, 29 struct sockaddr *, struct rtentry *); 30static int write_output(struct ifnet *, struct mbuf *, 31 struct sockaddr *, struct rtentry *); 32 33struct ifaddr { 34 struct sockaddr_storage ifa_addr; 35}; 36 37int 38ipfattach(softc) 39 ipf_main_softc_t *softc; 40{ 41 return 0; 42} 43 44 45int 46ipfdetach(softc) 47 ipf_main_softc_t *softc; 48{ 49 return 0; 50} 51 52 53/* 54 * Filter ioctl interface. 55 */ 56int 57ipfioctl(softc, dev, cmd, data, mode) 58 ipf_main_softc_t *softc; 59 int dev; 60 ioctlcmd_t cmd; 61 caddr_t data; 62 int mode; 63{ 64 int error = 0, unit = 0, uid; 65 66 uid = getuid(); 67 unit = dev; 68 69 SPL_NET(s); 70 71 error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL); 72 if (error != -1) { 73 SPL_X(s); 74 return error; 75 } 76 SPL_X(s); 77 return error; 78} 79 80 81void 82ipf_forgetifp(softc, ifp) 83 ipf_main_softc_t *softc; 84 void *ifp; 85{ 86 register frentry_t *f; 87 88 WRITE_ENTER(&softc->ipf_mutex); 89 for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL); 90 f = f->fr_next) 91 if (f->fr_ifa == ifp) 92 f->fr_ifa = (void *)-1; 93 for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL); 94 f = f->fr_next) 95 if (f->fr_ifa == ifp) 96 f->fr_ifa = (void *)-1; 97 for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL); 98 f = f->fr_next) 99 if (f->fr_ifa == ifp) 100 f->fr_ifa = (void *)-1; 101 for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL); 102 f = f->fr_next) 103 if (f->fr_ifa == ifp) 104 f->fr_ifa = (void *)-1; 105 RWLOCK_EXIT(&softc->ipf_mutex); 106 ipf_nat_sync(softc, ifp); 107 ipf_lookup_sync(softc, ifp); 108} 109 110 111static int 112no_output(ifp, m, s, rt) 113 struct rtentry *rt; 114 struct ifnet *ifp; 115 struct mbuf *m; 116 struct sockaddr *s; 117{ 118 return 0; 119} 120 121 122static int 123write_output(ifp, m, s, rt) 124 struct rtentry *rt; 125 struct ifnet *ifp; 126 struct mbuf *m; 127 struct sockaddr *s; 128{ 129 char fname[32]; 130 mb_t *mb; 131 ip_t *ip; 132 int fd; 133 134 mb = (mb_t *)m; 135 ip = MTOD(mb, ip_t *); 136 137#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 138 defined(__FreeBSD__) 139 sprintf(fname, "/tmp/%s", ifp->if_xname); 140#else 141 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 142#endif 143 fd = open(fname, O_WRONLY|O_APPEND); 144 if (fd == -1) { 145 perror("open"); 146 return -1; 147 } 148 write(fd, (char *)ip, ntohs(ip->ip_len)); 149 close(fd); 150 return 0; 151} 152 153 154static void 155ipf_setifpaddr(ifp, addr) 156 struct ifnet *ifp; 157 char *addr; 158{ 159 struct ifaddr *ifa; 160 161#if defined(__NetBSD__) || defined(__FreeBSD__) 162 if (ifp->if_addrlist.tqh_first != NULL) 163#else 164 if (ifp->if_addrlist != NULL) 165#endif 166 return; 167 168 ifa = (struct ifaddr *)malloc(sizeof(*ifa)); 169#if defined(__NetBSD__) || defined(__FreeBSD__) 170 ifp->if_addrlist.tqh_first = ifa; 171#else 172 ifp->if_addrlist = ifa; 173#endif 174 175 if (ifa != NULL) { 176 struct sockaddr_in *sin; 177 178 sin = (struct sockaddr_in *)&ifa->ifa_addr; 179#ifdef USE_INET6 180 if (index(addr, ':') != NULL) { 181 struct sockaddr_in6 *sin6; 182 183 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; 184 sin6->sin6_family = AF_INET6; 185 /* Abort if bad address. */ 186 switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr)) 187 { 188 case 1: 189 break; 190 case -1: 191 perror("inet_pton"); 192 abort(); 193 break; 194 default: 195 abort(); 196 break; 197 } 198 } else 199#endif 200 { 201 sin->sin_family = AF_INET; 202 sin->sin_addr.s_addr = inet_addr(addr); 203 if (sin->sin_addr.s_addr == 0) 204 abort(); 205 } 206 } 207} 208 209struct ifnet * 210get_unit(name, family) 211 char *name; 212 int family; 213{ 214 struct ifnet *ifp, **ifpp, **old_ifneta; 215 char *addr; 216#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 217 defined(__FreeBSD__) 218 219 if (!*name) 220 return NULL; 221 222 if (name == NULL) 223 name = "anon0"; 224 225 addr = strchr(name, '='); 226 if (addr != NULL) 227 *addr++ = '\0'; 228 229 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 230 if (!strcmp(name, ifp->if_xname)) { 231 if (addr != NULL) 232 ipf_setifpaddr(ifp, addr); 233 return ifp; 234 } 235 } 236#else 237 char *s, ifname[LIFNAMSIZ+1]; 238 239 if (name == NULL) 240 name = "anon0"; 241 242 addr = strchr(name, '='); 243 if (addr != NULL) 244 *addr++ = '\0'; 245 246 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 247 COPYIFNAME(family, ifp, ifname); 248 if (!strcmp(name, ifname)) { 249 if (addr != NULL) 250 ipf_setifpaddr(ifp, addr); 251 return ifp; 252 } 253 } 254#endif 255 256 if (!ifneta) { 257 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); 258 if (!ifneta) 259 return NULL; 260 ifneta[1] = NULL; 261 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); 262 if (!ifneta[0]) { 263 free(ifneta); 264 return NULL; 265 } 266 nifs = 1; 267 } else { 268 old_ifneta = ifneta; 269 nifs++; 270 ifneta = (struct ifnet **)reallocarray(ifneta, nifs + 1, 271 sizeof(ifp)); 272 if (!ifneta) { 273 free(old_ifneta); 274 nifs = 0; 275 return NULL; 276 } 277 ifneta[nifs] = NULL; 278 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); 279 if (!ifneta[nifs - 1]) { 280 nifs--; 281 return NULL; 282 } 283 } 284 ifp = ifneta[nifs - 1]; 285 286#if defined(__NetBSD__) || defined(__FreeBSD__) 287 TAILQ_INIT(&ifp->if_addrlist); 288#endif 289#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 290 defined(__FreeBSD__) 291 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); 292#else 293 s = name + strlen(name) - 1; 294 for (; s > name; s--) { 295 if (!ISDIGIT(*s)) { 296 s++; 297 break; 298 } 299 } 300 301 if ((s > name) && (*s != 0) && ISDIGIT(*s)) { 302 ifp->if_unit = atoi(s); 303 ifp->if_name = (char *)malloc(s - name + 1); 304 (void) strncpy(ifp->if_name, name, s - name); 305 ifp->if_name[s - name] = '\0'; 306 } else { 307 ifp->if_name = strdup(name); 308 ifp->if_unit = -1; 309 } 310#endif 311 ifp->if_output = (void *)no_output; 312 313 if (addr != NULL) { 314 ipf_setifpaddr(ifp, addr); 315 } 316 317 return ifp; 318} 319 320 321char * 322get_ifname(ifp) 323 struct ifnet *ifp; 324{ 325 static char ifname[LIFNAMSIZ]; 326 327#if defined(__NetBSD__) || defined(__FreeBSD__) 328 sprintf(ifname, "%s", ifp->if_xname); 329#else 330 if (ifp->if_unit != -1) 331 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); 332 else 333 strcpy(ifname, ifp->if_name); 334#endif 335 return ifname; 336} 337 338 339 340void 341init_ifp() 342{ 343 struct ifnet *ifp, **ifpp; 344 char fname[32]; 345 int fd; 346 347#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 348 defined(__FreeBSD__) 349 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 350 ifp->if_output = (void *)write_output; 351 sprintf(fname, "/tmp/%s", ifp->if_xname); 352 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 353 if (fd == -1) 354 perror("open"); 355 else 356 close(fd); 357 } 358#else 359 360 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 361 ifp->if_output = (void *)write_output; 362 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 363 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 364 if (fd == -1) 365 perror("open"); 366 else 367 close(fd); 368 } 369#endif 370} 371 372 373int 374ipf_fastroute(m, mpp, fin, fdp) 375 mb_t *m, **mpp; 376 fr_info_t *fin; 377 frdest_t *fdp; 378{ 379 struct ifnet *ifp; 380 ip_t *ip = fin->fin_ip; 381 frdest_t node; 382 int error = 0; 383 frentry_t *fr; 384 void *sifp; 385 int sout; 386 387 sifp = fin->fin_ifp; 388 sout = fin->fin_out; 389 fr = fin->fin_fr; 390 ip->ip_sum = 0; 391 392 if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && 393 (fdp->fd_type == FRD_DSTLIST)) { 394 bzero(&node, sizeof(node)); 395 ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node); 396 fdp = &node; 397 } 398 ifp = fdp->fd_ptr; 399 400 if (ifp == NULL) 401 return 0; /* no routing table out here */ 402 403 if (fin->fin_out == 0) { 404 fin->fin_ifp = ifp; 405 fin->fin_out = 1; 406 (void) ipf_acctpkt(fin, NULL); 407 fin->fin_fr = NULL; 408 if (!fr || !(fr->fr_flags & FR_RETMASK)) { 409 u_32_t pass; 410 411 (void) ipf_state_check(fin, &pass); 412 } 413 414 switch (ipf_nat_checkout(fin, NULL)) 415 { 416 case 0 : 417 break; 418 case 1 : 419 ip->ip_sum = 0; 420 break; 421 case -1 : 422 error = -1; 423 goto done; 424 break; 425 } 426 427 } 428 429 m->mb_ifp = ifp; 430 printpacket(fin->fin_out, m); 431 432 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 433done: 434 fin->fin_ifp = sifp; 435 fin->fin_out = sout; 436 return error; 437} 438 439 440int 441ipf_send_reset(fin) 442 fr_info_t *fin; 443{ 444 ipfkverbose("- TCP RST sent\n"); 445 return 0; 446} 447 448 449int 450ipf_send_icmp_err(type, fin, dst) 451 int type; 452 fr_info_t *fin; 453 int dst; 454{ 455 ipfkverbose("- ICMP unreachable sent\n"); 456 return 0; 457} 458 459 460void 461m_freem(m) 462 mb_t *m; 463{ 464 return; 465} 466 467 468void 469m_copydata(m, off, len, cp) 470 mb_t *m; 471 int off, len; 472 caddr_t cp; 473{ 474 bcopy((char *)m + off, cp, len); 475} 476 477 478int 479ipfuiomove(buf, len, rwflag, uio) 480 caddr_t buf; 481 int len, rwflag; 482 struct uio *uio; 483{ 484 int left, ioc, num, offset; 485 struct iovec *io; 486 char *start; 487 488 if (rwflag == UIO_READ) { 489 left = len; 490 ioc = 0; 491 492 offset = uio->uio_offset; 493 494 while ((left > 0) && (ioc < uio->uio_iovcnt)) { 495 io = uio->uio_iov + ioc; 496 num = io->iov_len; 497 if (num > left) 498 num = left; 499 start = (char *)io->iov_base + offset; 500 if (start > (char *)io->iov_base + io->iov_len) { 501 offset -= io->iov_len; 502 ioc++; 503 continue; 504 } 505 bcopy(buf, start, num); 506 uio->uio_resid -= num; 507 uio->uio_offset += num; 508 left -= num; 509 if (left > 0) 510 ioc++; 511 } 512 if (left > 0) 513 return EFAULT; 514 } 515 return 0; 516} 517 518 519u_32_t 520ipf_newisn(fin) 521 fr_info_t *fin; 522{ 523 static int iss_seq_off = 0; 524 u_char hash[16]; 525 u_32_t newiss; 526 MD5_CTX ctx; 527 528 /* 529 * Compute the base value of the ISS. It is a hash 530 * of (saddr, sport, daddr, dport, secret). 531 */ 532 MD5Init(&ctx); 533 534 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 535 sizeof(fin->fin_fi.fi_src)); 536 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 537 sizeof(fin->fin_fi.fi_dst)); 538 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 539 540 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ 541 542 MD5Final(hash, &ctx); 543 544 memcpy(&newiss, hash, sizeof(newiss)); 545 546 /* 547 * Now increment our "timer", and add it in to 548 * the computed value. 549 * 550 * XXX Use `addin'? 551 * XXX TCP_ISSINCR too large to use? 552 */ 553 iss_seq_off += 0x00010000; 554 newiss += iss_seq_off; 555 return newiss; 556} 557 558 559/* ------------------------------------------------------------------------ */ 560/* Function: ipf_nextipid */ 561/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 562/* Parameters: fin(I) - pointer to packet information */ 563/* */ 564/* Returns the next IPv4 ID to use for this packet. */ 565/* ------------------------------------------------------------------------ */ 566INLINE u_short 567ipf_nextipid(fin) 568 fr_info_t *fin; 569{ 570 static u_short ipid = 0; 571 ipf_main_softc_t *softc = fin->fin_main_soft; 572 u_short id; 573 574 MUTEX_ENTER(&softc->ipf_rw); 575 if (fin->fin_pktnum != 0) { 576 /* 577 * The -1 is for aligned test results. 578 */ 579 id = (fin->fin_pktnum - 1) & 0xffff; 580 } else { 581 } 582 id = ipid++; 583 MUTEX_EXIT(&softc->ipf_rw); 584 585 return id; 586} 587 588 589INLINE int 590ipf_checkv4sum(fin) 591 fr_info_t *fin; 592{ 593 594 if (fin->fin_flx & FI_SHORT) 595 return 1; 596 597 if (ipf_checkl4sum(fin) == -1) { 598 fin->fin_flx |= FI_BAD; 599 return -1; 600 } 601 return 0; 602} 603 604 605#ifdef USE_INET6 606INLINE int 607ipf_checkv6sum(fin) 608 fr_info_t *fin; 609{ 610 if (fin->fin_flx & FI_SHORT) 611 return 1; 612 613 if (ipf_checkl4sum(fin) == -1) { 614 fin->fin_flx |= FI_BAD; 615 return -1; 616 } 617 return 0; 618} 619#endif 620 621 622#if 0 623/* 624 * See above for description, except that all addressing is in user space. 625 */ 626int 627copyoutptr(softc, src, dst, size) 628 void *src, *dst; 629 size_t size; 630{ 631 caddr_t ca; 632 633 bcopy(dst, (char *)&ca, sizeof(ca)); 634 bcopy(src, ca, size); 635 return 0; 636} 637 638 639/* 640 * See above for description, except that all addressing is in user space. 641 */ 642int 643copyinptr(src, dst, size) 644 void *src, *dst; 645 size_t size; 646{ 647 caddr_t ca; 648 649 bcopy(src, (char *)&ca, sizeof(ca)); 650 bcopy(ca, dst, size); 651 return 0; 652} 653#endif 654 655 656/* 657 * return the first IP Address associated with an interface 658 */ 659int 660ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) 661 ipf_main_softc_t *softc; 662 int v, atype; 663 void *ifptr; 664 i6addr_t *inp, *inpmask; 665{ 666 struct ifnet *ifp = ifptr; 667 struct ifaddr *ifa; 668 669#if defined(__NetBSD__) || defined(__FreeBSD__) 670 ifa = ifp->if_addrlist.tqh_first; 671#else 672 ifa = ifp->if_addrlist; 673#endif 674 if (ifa != NULL) { 675 if (v == 4) { 676 struct sockaddr_in *sin, mask; 677 678 mask.sin_addr.s_addr = 0xffffffff; 679 680 sin = (struct sockaddr_in *)&ifa->ifa_addr; 681 682 return ipf_ifpfillv4addr(atype, sin, &mask, 683 &inp->in4, &inpmask->in4); 684 } 685#ifdef USE_INET6 686 if (v == 6) { 687 struct sockaddr_in6 *sin6, mask; 688 689 sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; 690 ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff; 691 ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff; 692 ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff; 693 ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff; 694 return ipf_ifpfillv6addr(atype, sin6, &mask, 695 inp, inpmask); 696 } 697#endif 698 } 699 return 0; 700} 701 702 703/* 704 * This function is not meant to be random, rather just produce a 705 * sequence of numbers that isn't linear to show "randomness". 706 */ 707u_32_t 708ipf_random() 709{ 710 static unsigned int last = 0xa5a5a5a5; 711 static int calls = 0; 712 int number; 713 714 calls++; 715 716 /* 717 * These are deliberately chosen to ensure that there is some 718 * attempt to test whether the output covers the range in test n18. 719 */ 720 switch (calls) 721 { 722 case 1 : 723 number = 0; 724 break; 725 case 2 : 726 number = 4; 727 break; 728 case 3 : 729 number = 3999; 730 break; 731 case 4 : 732 number = 4000; 733 break; 734 case 5 : 735 number = 48999; 736 break; 737 case 6 : 738 number = 49000; 739 break; 740 default : 741 number = last; 742 last *= calls; 743 last++; 744 number ^= last; 745 break; 746 } 747 return number; 748} 749 750 751int 752ipf_verifysrc(fin) 753 fr_info_t *fin; 754{ 755 return 1; 756} 757 758 759int 760ipf_inject(fin, m) 761 fr_info_t *fin; 762 mb_t *m; 763{ 764 FREE_MB_T(m); 765 766 return 0; 767} 768 769 770u_int 771ipf_pcksum(fin, hlen, sum) 772 fr_info_t *fin; 773 int hlen; 774 u_int sum; 775{ 776 u_short *sp; 777 u_int sum2; 778 int slen; 779 780 slen = fin->fin_plen - hlen; 781 sp = (u_short *)((u_char *)fin->fin_ip + hlen); 782 783 for (; slen > 1; slen -= 2) 784 sum += *sp++; 785 if (slen) 786 sum += ntohs(*(u_char *)sp << 8); 787 while (sum > 0xffff) 788 sum = (sum & 0xffff) + (sum >> 16); 789 sum2 = (u_short)(~sum & 0xffff); 790 791 return sum2; 792} 793 794 795void * 796ipf_pullup(m, fin, plen) 797 mb_t *m; 798 fr_info_t *fin; 799 int plen; 800{ 801 if (M_LEN(m) >= plen) 802 return fin->fin_ip; 803 804 /* 805 * Fake ipf_pullup failing 806 */ 807 fin->fin_reason = FRB_PULLUP; 808 *fin->fin_mp = NULL; 809 fin->fin_m = NULL; 810 fin->fin_ip = NULL; 811 return NULL; 812} 813