67# include <netinet/tcp_var.h> 68#else 69#define V_path_mtu_discovery path_mtu_discovery 70#define V_ipforwarding ipforwarding 71#endif 72 73#include <net/if.h> 74#if __FreeBSD_version >= 300000 75# include <net/if_var.h> 76# if __FreeBSD_version >= 500043 77# include <net/netisr.h> 78# endif 79# if !defined(IPFILTER_LKM) 80# include "opt_ipfilter.h" 81# endif 82#endif 83#include <net/route.h> 84#include <netinet/in.h> 85#include <netinet/in_var.h> 86#include <netinet/in_systm.h> 87#include <netinet/ip.h> 88#include <netinet/ip_var.h> 89#include <netinet/tcp.h> 90#if defined(__osf__) 91# include <netinet/tcp_timer.h> 92#endif 93#include <netinet/udp.h> 94#include <netinet/tcpip.h> 95#include <netinet/ip_icmp.h> 96#ifndef _KERNEL 97# include "netinet/ipf.h" 98#endif 99#include "netinet/ip_compat.h" 100#ifdef USE_INET6 101# include <netinet/icmp6.h> 102#endif 103#include "netinet/ip_fil.h" 104#include "netinet/ip_nat.h" 105#include "netinet/ip_frag.h" 106#include "netinet/ip_state.h" 107#include "netinet/ip_proxy.h" 108#include "netinet/ip_auth.h" 109#ifdef IPFILTER_SYNC 110#include "netinet/ip_sync.h" 111#endif 112#ifdef IPFILTER_SCAN 113#include "netinet/ip_scan.h" 114#endif 115#include "netinet/ip_pool.h" 116#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 117# include <sys/malloc.h> 118#endif 119#include <sys/kernel.h> 120#ifdef CSUM_DATA_VALID 121#include <machine/in_cksum.h> 122#endif 123extern int ip_optcopy __P((struct ip *, struct ip *)); 124 125#if (__FreeBSD_version > 460000) && (__FreeBSD_version < 800055) 126extern int path_mtu_discovery; 127#endif 128 129# ifdef IPFILTER_M_IPFILTER 130MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures"); 131# endif 132 133 134#if !defined(__osf__) 135extern struct protosw inetsw[]; 136#endif 137 138static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); 139static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **)); 140# ifdef USE_MUTEXES 141ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; 142ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; 143ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens; 144ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; 145# endif 146int ipf_locks_done = 0; 147 148#if (__FreeBSD_version >= 300000) 149struct callout_handle fr_slowtimer_ch; 150#endif 151struct selinfo ipfselwait[IPL_LOGSIZE]; 152 153#if (__FreeBSD_version >= 500011) 154# include <sys/conf.h> 155# if defined(NETBSD_PF) 156# include <net/pfil.h> 157# if (__FreeBSD_version < 501108) 158# include <netinet/ipprotosw.h> 159# endif 160/* 161 * We provide the fr_checkp name just to minimize changes later. 162 */ 163int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); 164# endif /* NETBSD_PF */ 165#endif /* __FreeBSD_version >= 500011 */ 166 167 168#if (__FreeBSD_version >= 502103) 169static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag; 170 171static void ipf_ifevent(void *arg); 172 173static void ipf_ifevent(arg) 174void *arg; 175{ 176 frsync(NULL); 177} 178#endif 179 180 181#if (__FreeBSD_version >= 501108) && defined(_KERNEL) 182 183static int 184fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 185{ 186 struct ip *ip = mtod(*mp, struct ip *); 187 return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp); 188} 189 190# ifdef USE_INET6 191# include <netinet/ip6.h> 192 193static int 194fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 195{ 196 return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr), 197 ifp, (dir == PFIL_OUT), mp)); 198} 199# endif 200#endif /* __FreeBSD_version >= 501108 */ 201#if defined(IPFILTER_LKM) 202int iplidentify(s) 203char *s; 204{ 205 if (strcmp(s, "ipl") == 0) 206 return 1; 207 return 0; 208} 209#endif /* IPFILTER_LKM */ 210 211 212int ipfattach() 213{ 214#ifdef USE_SPL 215 int s; 216#endif 217 218 SPL_NET(s); 219 if (fr_running > 0) { 220 SPL_X(s); 221 return EBUSY; 222 } 223 224 MUTEX_INIT(&ipf_rw, "ipf rw mutex"); 225 MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex"); 226 RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); 227 RWLOCK_INIT(&ipf_tokens, "ipf token rwlock"); 228 ipf_locks_done = 1; 229 230 if (fr_initialise() < 0) { 231 SPL_X(s); 232 return EIO; 233 } 234 235 236 if (fr_checkp != fr_check) { 237 fr_savep = fr_checkp; 238 fr_checkp = fr_check; 239 } 240 241 bzero((char *)ipfselwait, sizeof(ipfselwait)); 242 bzero((char *)frcache, sizeof(frcache)); 243 fr_running = 1; 244 245 if (fr_control_forwarding & 1) 246 V_ipforwarding = 1; 247 248 SPL_X(s); 249#if (__FreeBSD_version >= 300000) 250 fr_slowtimer_ch = timeout(fr_slowtimer, NULL, 251 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 252#else 253 timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 254#endif 255 return 0; 256} 257 258 259/* 260 * Disable the filter by removing the hooks from the IP input/output 261 * stream. 262 */ 263int ipfdetach() 264{ 265#ifdef USE_SPL 266 int s; 267#endif 268 if (fr_control_forwarding & 2) 269 V_ipforwarding = 0; 270 271 SPL_NET(s); 272 273#if (__FreeBSD_version >= 300000) 274 if (fr_slowtimer_ch.callout != NULL) 275 untimeout(fr_slowtimer, NULL, fr_slowtimer_ch); 276 bzero(&fr_slowtimer_ch, sizeof(fr_slowtimer_ch)); 277#else 278 untimeout(fr_slowtimer, NULL); 279#endif /* FreeBSD */ 280 281#ifndef NETBSD_PF 282 if (fr_checkp != NULL) 283 fr_checkp = fr_savep; 284 fr_savep = NULL; 285#endif 286 287 fr_deinitialise(); 288 289 fr_running = -2; 290 291 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 292 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); 293 294 if (ipf_locks_done == 1) { 295 MUTEX_DESTROY(&ipf_timeoutlock); 296 MUTEX_DESTROY(&ipf_rw); 297 RW_DESTROY(&ipf_ipidfrag); 298 RW_DESTROY(&ipf_tokens); 299 ipf_locks_done = 0; 300 } 301 302 SPL_X(s); 303 304 return 0; 305} 306 307 308/* 309 * Filter ioctl interface. 310 */ 311int iplioctl(dev, cmd, data, mode 312# if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 313, p) 314# if (__FreeBSD_version >= 500024) 315struct thread *p; 316# if (__FreeBSD_version >= 500043) 317# define p_cred td_ucred 318# define p_uid td_ucred->cr_ruid 319# else 320# define p_cred t_proc->p_cred 321# define p_uid t_proc->p_cred->p_ruid 322# endif 323# else 324struct proc *p; 325# define p_uid p_cred->p_ruid 326# endif /* __FreeBSD_version >= 500024 */ 327# else 328) 329# endif 330#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 331struct cdev *dev; 332#else 333dev_t dev; 334#endif 335ioctlcmd_t cmd; 336caddr_t data; 337int mode; 338{ 339 int error = 0, unit = 0; 340 SPL_INT(s); 341 342#if (BSD >= 199306) && defined(_KERNEL) 343# if (__FreeBSD_version >= 500034) 344 if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE)) 345# else 346 if ((securelevel >= 3) && (mode & FWRITE)) 347# endif 348 return EPERM; 349#endif 350 351 unit = GET_MINOR(dev); 352 if ((IPL_LOGMAX < unit) || (unit < 0)) 353 return ENXIO; 354 355 if (fr_running <= 0) { 356 if (unit != IPL_LOGIPF) 357 return EIO; 358 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && 359 cmd != SIOCIPFSET && cmd != SIOCFRENB && 360 cmd != SIOCGETFS && cmd != SIOCGETFF) 361 return EIO; 362 } 363 364 SPL_NET(s); 365 366 error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p); 367 if (error != -1) { 368 SPL_X(s); 369 return error; 370 } 371 372 SPL_X(s); 373 374 return error; 375} 376 377 378#if 0 379void fr_forgetifp(ifp) 380void *ifp; 381{ 382 register frentry_t *f; 383 384 WRITE_ENTER(&ipf_mutex); 385 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) 386 if (f->fr_ifa == ifp) 387 f->fr_ifa = (void *)-1; 388 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) 389 if (f->fr_ifa == ifp) 390 f->fr_ifa = (void *)-1; 391 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) 392 if (f->fr_ifa == ifp) 393 f->fr_ifa = (void *)-1; 394 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) 395 if (f->fr_ifa == ifp) 396 f->fr_ifa = (void *)-1; 397#ifdef USE_INET6 398 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next) 399 if (f->fr_ifa == ifp) 400 f->fr_ifa = (void *)-1; 401 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next) 402 if (f->fr_ifa == ifp) 403 f->fr_ifa = (void *)-1; 404 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next) 405 if (f->fr_ifa == ifp) 406 f->fr_ifa = (void *)-1; 407 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next) 408 if (f->fr_ifa == ifp) 409 f->fr_ifa = (void *)-1; 410#endif 411 RWLOCK_EXIT(&ipf_mutex); 412 fr_natsync(ifp); 413} 414#endif 415 416 417/* 418 * routines below for saving IP headers to buffer 419 */ 420int iplopen(dev, flags 421#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) 422, devtype, p) 423int devtype; 424# if (__FreeBSD_version >= 500024) 425struct thread *p; 426# else 427struct proc *p; 428# endif /* __FreeBSD_version >= 500024 */ 429#else 430) 431#endif 432#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 433struct cdev *dev; 434#else 435dev_t dev; 436#endif 437int flags; 438{ 439 u_int min = GET_MINOR(dev); 440 441 if (IPL_LOGMAX < min) 442 min = ENXIO; 443 else 444 min = 0; 445 return min; 446} 447 448 449int iplclose(dev, flags 450#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) 451, devtype, p) 452int devtype; 453# if (__FreeBSD_version >= 500024) 454struct thread *p; 455# else 456struct proc *p; 457# endif /* __FreeBSD_version >= 500024 */ 458#else 459) 460#endif 461#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 462struct cdev *dev; 463#else 464dev_t dev; 465#endif 466int flags; 467{ 468 u_int min = GET_MINOR(dev); 469 470 if (IPL_LOGMAX < min) 471 min = ENXIO; 472 else 473 min = 0; 474 return min; 475} 476 477/* 478 * iplread/ipllog 479 * both of these must operate with at least splnet() lest they be 480 * called during packet processing and cause an inconsistancy to appear in 481 * the filter lists. 482 */ 483#if (BSD >= 199306) 484int iplread(dev, uio, ioflag) 485int ioflag; 486#else 487int iplread(dev, uio) 488#endif 489#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 490struct cdev *dev; 491#else 492dev_t dev; 493#endif 494register struct uio *uio; 495{ 496 u_int xmin = GET_MINOR(dev); 497 498 if (fr_running < 1) 499 return EIO; 500 501 if (xmin < 0) 502 return ENXIO; 503 504# ifdef IPFILTER_SYNC 505 if (xmin == IPL_LOGSYNC) 506 return ipfsync_read(uio); 507# endif 508 509#ifdef IPFILTER_LOG 510 return ipflog_read(xmin, uio); 511#else 512 return ENXIO; 513#endif 514} 515 516 517/* 518 * iplwrite 519 * both of these must operate with at least splnet() lest they be 520 * called during packet processing and cause an inconsistancy to appear in 521 * the filter lists. 522 */ 523#if (BSD >= 199306) 524int iplwrite(dev, uio, ioflag) 525int ioflag; 526#else 527int iplwrite(dev, uio) 528#endif 529#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 530struct cdev *dev; 531#else 532dev_t dev; 533#endif 534register struct uio *uio; 535{ 536 537 if (fr_running < 1) 538 return EIO; 539 540#ifdef IPFILTER_SYNC 541 if (GET_MINOR(dev) == IPL_LOGSYNC) 542 return ipfsync_write(uio); 543#endif 544 return ENXIO; 545} 546 547 548/* 549 * fr_send_reset - this could conceivably be a call to tcp_respond(), but that 550 * requires a large amount of setting up and isn't any more efficient. 551 */ 552int fr_send_reset(fin) 553fr_info_t *fin; 554{ 555 struct tcphdr *tcp, *tcp2; 556 int tlen = 0, hlen; 557 struct mbuf *m; 558#ifdef USE_INET6 559 ip6_t *ip6; 560#endif 561 ip_t *ip; 562 563 tcp = fin->fin_dp; 564 if (tcp->th_flags & TH_RST) 565 return -1; /* feedback loop */ 566 567 if (fr_checkl4sum(fin) == -1) 568 return -1; 569 570 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + 571 ((tcp->th_flags & TH_SYN) ? 1 : 0) + 572 ((tcp->th_flags & TH_FIN) ? 1 : 0); 573 574#ifdef USE_INET6 575 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); 576#else 577 hlen = sizeof(ip_t); 578#endif 579#ifdef MGETHDR 580 MGETHDR(m, M_DONTWAIT, MT_HEADER); 581#else 582 MGET(m, M_DONTWAIT, MT_HEADER); 583#endif 584 if (m == NULL) 585 return -1; 586 if (sizeof(*tcp2) + hlen > MLEN) { 587 MCLGET(m, M_DONTWAIT); 588 if ((m->m_flags & M_EXT) == 0) { 589 FREE_MB_T(m); 590 return -1; 591 } 592 } 593 594 m->m_len = sizeof(*tcp2) + hlen; 595#if (BSD >= 199103) 596 m->m_data += max_linkhdr; 597 m->m_pkthdr.len = m->m_len; 598 m->m_pkthdr.rcvif = (struct ifnet *)0; 599#endif 600 ip = mtod(m, struct ip *); 601 bzero((char *)ip, hlen); 602#ifdef USE_INET6 603 ip6 = (ip6_t *)ip; 604#endif 605 tcp2 = (struct tcphdr *)((char *)ip + hlen); 606 tcp2->th_sport = tcp->th_dport; 607 tcp2->th_dport = tcp->th_sport; 608 609 if (tcp->th_flags & TH_ACK) { 610 tcp2->th_seq = tcp->th_ack; 611 tcp2->th_flags = TH_RST; 612 tcp2->th_ack = 0; 613 } else { 614 tcp2->th_seq = 0; 615 tcp2->th_ack = ntohl(tcp->th_seq); 616 tcp2->th_ack += tlen; 617 tcp2->th_ack = htonl(tcp2->th_ack); 618 tcp2->th_flags = TH_RST|TH_ACK; 619 } 620 TCP_X2_A(tcp2, 0); 621 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); 622 tcp2->th_win = tcp->th_win; 623 tcp2->th_sum = 0; 624 tcp2->th_urp = 0; 625 626#ifdef USE_INET6 627 if (fin->fin_v == 6) { 628 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 629 ip6->ip6_plen = htons(sizeof(struct tcphdr)); 630 ip6->ip6_nxt = IPPROTO_TCP; 631 ip6->ip6_hlim = 0; 632 ip6->ip6_src = fin->fin_dst6; 633 ip6->ip6_dst = fin->fin_src6; 634 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, 635 sizeof(*ip6), sizeof(*tcp2)); 636 return fr_send_ip(fin, m, &m); 637 } 638#endif 639 ip->ip_p = IPPROTO_TCP; 640 ip->ip_len = htons(sizeof(struct tcphdr)); 641 ip->ip_src.s_addr = fin->fin_daddr; 642 ip->ip_dst.s_addr = fin->fin_saddr; 643 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); 644 ip->ip_len = hlen + sizeof(*tcp2); 645 return fr_send_ip(fin, m, &m); 646} 647 648 649static int fr_send_ip(fin, m, mpp) 650fr_info_t *fin; 651mb_t *m, **mpp; 652{ 653 fr_info_t fnew; 654 ip_t *ip, *oip; 655 int hlen; 656 657 ip = mtod(m, ip_t *); 658 bzero((char *)&fnew, sizeof(fnew)); 659 660 IP_V_A(ip, fin->fin_v); 661 switch (fin->fin_v) 662 { 663 case 4 : 664 fnew.fin_v = 4; 665 oip = fin->fin_ip; 666 IP_HL_A(ip, sizeof(*oip) >> 2); 667 ip->ip_tos = oip->ip_tos; 668 ip->ip_id = fin->fin_ip->ip_id; 669#if (__FreeBSD_version > 460000) 670 ip->ip_off = V_path_mtu_discovery ? IP_DF : 0; 671#else 672 ip->ip_off = 0; 673#endif 674 ip->ip_ttl = V_ip_defttl; 675 ip->ip_sum = 0; 676 hlen = sizeof(*oip); 677 break; 678#ifdef USE_INET6 679 case 6 : 680 { 681 ip6_t *ip6 = (ip6_t *)ip; 682 683 ip6->ip6_vfc = 0x60; 684 ip6->ip6_hlim = IPDEFTTL; 685 686 fnew.fin_v = 6; 687 hlen = sizeof(*ip6); 688 break; 689 } 690#endif 691 default : 692 return EINVAL; 693 } 694#ifdef IPSEC 695 m->m_pkthdr.rcvif = NULL; 696#endif 697 698 fnew.fin_ifp = fin->fin_ifp; 699 fnew.fin_flx = FI_NOCKSUM; 700 fnew.fin_m = m; 701 fnew.fin_ip = ip; 702 fnew.fin_mp = mpp; 703 fnew.fin_hlen = hlen; 704 fnew.fin_dp = (char *)ip + hlen; 705 (void) fr_makefrip(hlen, ip, &fnew); 706 707 return fr_fastroute(m, mpp, &fnew, NULL); 708} 709 710 711int fr_send_icmp_err(type, fin, dst) 712int type; 713fr_info_t *fin; 714int dst; 715{ 716 int err, hlen, xtra, iclen, ohlen, avail, code; 717 struct in_addr dst4; 718 struct icmp *icmp; 719 struct mbuf *m; 720 void *ifp; 721#ifdef USE_INET6 722 ip6_t *ip6; 723 struct in6_addr dst6; 724#endif 725 ip_t *ip, *ip2; 726 727 if ((type < 0) || (type >= ICMP_MAXTYPE)) 728 return -1; 729 730 code = fin->fin_icode; 731#ifdef USE_INET6 732 if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) 733 return -1; 734#endif 735 736 if (fr_checkl4sum(fin) == -1) 737 return -1; 738#ifdef MGETHDR 739 MGETHDR(m, M_DONTWAIT, MT_HEADER); 740#else 741 MGET(m, M_DONTWAIT, MT_HEADER); 742#endif 743 if (m == NULL) 744 return -1; 745 avail = MHLEN; 746 747 xtra = 0; 748 hlen = 0; 749 ohlen = 0; 750 ifp = fin->fin_ifp; 751 if (fin->fin_v == 4) { 752 if ((fin->fin_p == IPPROTO_ICMP) && 753 !(fin->fin_flx & FI_SHORT)) 754 switch (ntohs(fin->fin_data[0]) >> 8) 755 { 756 case ICMP_ECHO : 757 case ICMP_TSTAMP : 758 case ICMP_IREQ : 759 case ICMP_MASKREQ : 760 break; 761 default : 762 FREE_MB_T(m); 763 return 0; 764 } 765 766 if (dst == 0) { 767 if (fr_ifpaddr(4, FRI_NORMAL, ifp, 768 &dst4, NULL) == -1) { 769 FREE_MB_T(m); 770 return -1; 771 } 772 } else 773 dst4.s_addr = fin->fin_daddr; 774 775 hlen = sizeof(ip_t); 776 ohlen = fin->fin_hlen; 777 if (fin->fin_hlen < fin->fin_plen) 778 xtra = MIN(fin->fin_dlen, 8); 779 else 780 xtra = 0; 781 } 782 783#ifdef USE_INET6 784 else if (fin->fin_v == 6) { 785 hlen = sizeof(ip6_t); 786 ohlen = sizeof(ip6_t); 787 type = icmptoicmp6types[type]; 788 if (type == ICMP6_DST_UNREACH) 789 code = icmptoicmp6unreach[code]; 790 791 if (hlen + sizeof(*icmp) + max_linkhdr + 792 fin->fin_plen > avail) { 793 MCLGET(m, M_DONTWAIT); 794 if ((m->m_flags & M_EXT) == 0) { 795 FREE_MB_T(m); 796 return -1; 797 } 798 avail = MCLBYTES; 799 } 800 xtra = MIN(fin->fin_plen, 801 avail - hlen - sizeof(*icmp) - max_linkhdr); 802 if (dst == 0) { 803 if (fr_ifpaddr(6, FRI_NORMAL, ifp, 804 (struct in_addr *)&dst6, NULL) == -1) { 805 FREE_MB_T(m); 806 return -1; 807 } 808 } else 809 dst6 = fin->fin_dst6; 810 } 811#endif 812 else { 813 FREE_MB_T(m); 814 return -1; 815 } 816 817 iclen = hlen + sizeof(*icmp); 818 avail -= (max_linkhdr + iclen); 819 if (avail < 0) { 820 FREE_MB_T(m); 821 return -1; 822 } 823 if (xtra > avail) 824 xtra = avail; 825 iclen += xtra; 826 m->m_data += max_linkhdr; 827 m->m_pkthdr.rcvif = (struct ifnet *)0; 828 m->m_pkthdr.len = iclen; 829 m->m_len = iclen; 830 ip = mtod(m, ip_t *); 831 icmp = (struct icmp *)((char *)ip + hlen); 832 ip2 = (ip_t *)&icmp->icmp_ip; 833 834 icmp->icmp_type = type; 835 icmp->icmp_code = fin->fin_icode; 836 icmp->icmp_cksum = 0; 837#ifdef icmp_nextmtu 838 if (type == ICMP_UNREACH && 839 fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp) 840 icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu); 841#endif 842 843 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); 844 845#ifdef USE_INET6 846 ip6 = (ip6_t *)ip; 847 if (fin->fin_v == 6) { 848 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 849 ip6->ip6_plen = htons(iclen - hlen); 850 ip6->ip6_nxt = IPPROTO_ICMPV6; 851 ip6->ip6_hlim = 0; 852 ip6->ip6_src = dst6; 853 ip6->ip6_dst = fin->fin_src6; 854 if (xtra > 0) 855 bcopy((char *)fin->fin_ip + ohlen, 856 (char *)&icmp->icmp_ip + ohlen, xtra); 857 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, 858 sizeof(*ip6), iclen - hlen); 859 } else 860#endif 861 { 862 ip2->ip_len = htons(ip2->ip_len); 863 ip2->ip_off = htons(ip2->ip_off); 864 ip->ip_p = IPPROTO_ICMP; 865 ip->ip_src.s_addr = dst4.s_addr; 866 ip->ip_dst.s_addr = fin->fin_saddr; 867 868 if (xtra > 0) 869 bcopy((char *)fin->fin_ip + ohlen, 870 (char *)&icmp->icmp_ip + ohlen, xtra); 871 icmp->icmp_cksum = ipf_cksum((u_short *)icmp, 872 sizeof(*icmp) + 8); 873 ip->ip_len = iclen; 874 ip->ip_p = IPPROTO_ICMP; 875 } 876 err = fr_send_ip(fin, m, &m); 877 return err; 878} 879 880 881#if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) 882# if (BSD < 199306) 883int iplinit __P((void)); 884 885int 886# else 887void iplinit __P((void)); 888 889void 890# endif 891iplinit() 892{ 893 if (ipfattach() != 0) 894 printf("IP Filter failed to attach\n"); 895 ip_init(); 896} 897#endif /* __FreeBSD_version < 300000 */ 898 899 900/* 901 * m0 - pointer to mbuf where the IP packet starts 902 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain 903 */ 904int fr_fastroute(m0, mpp, fin, fdp) 905mb_t *m0, **mpp; 906fr_info_t *fin; 907frdest_t *fdp; 908{ 909 register struct ip *ip, *mhip; 910 register struct mbuf *m = *mpp; 911 register struct route *ro; 912 int len, off, error = 0, hlen, code; 913 struct ifnet *ifp, *sifp; 914 struct sockaddr_in *dst; 915 struct route iproute; 916 u_short ip_off; 917 frentry_t *fr; 918 919 ro = NULL; 920 921#ifdef M_WRITABLE 922 /* 923 * HOT FIX/KLUDGE: 924 * 925 * If the mbuf we're about to send is not writable (because of 926 * a cluster reference, for example) we'll need to make a copy 927 * of it since this routine modifies the contents. 928 * 929 * If you have non-crappy network hardware that can transmit data 930 * from the mbuf, rather than making a copy, this is gonna be a 931 * problem. 932 */ 933 if (M_WRITABLE(m) == 0) { 934 m0 = m_dup(m, M_DONTWAIT); 935 if (m0 != 0) { 936 FREE_MB_T(m); 937 m = m0; 938 *mpp = m; 939 } else { 940 error = ENOBUFS; 941 FREE_MB_T(m); 942 goto done; 943 } 944 } 945#endif 946 947#ifdef USE_INET6 948 if (fin->fin_v == 6) { 949 /* 950 * currently "to <if>" and "to <if>:ip#" are not supported 951 * for IPv6 952 */ 953#if (__FreeBSD_version >= 490000) 954 return ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); 955#else 956 return ip6_output(m0, NULL, NULL, 0, NULL, NULL); 957#endif 958 } 959#endif 960 961 hlen = fin->fin_hlen; 962 ip = mtod(m0, struct ip *); 963 964 /* 965 * Route packet. 966 */ 967 ro = &iproute; 968 bzero((caddr_t)ro, sizeof (*ro)); 969 dst = (struct sockaddr_in *)&ro->ro_dst; 970 dst->sin_family = AF_INET; 971 dst->sin_addr = ip->ip_dst; 972 973 fr = fin->fin_fr; 974 if (fdp != NULL) 975 ifp = fdp->fd_ifp; 976 else 977 ifp = fin->fin_ifp; 978 979 if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) { 980 error = -2; 981 goto bad; 982 } 983 984 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 985 dst->sin_addr = fdp->fd_ip; 986 987 dst->sin_len = sizeof(*dst); 988 in_rtalloc(ro, 0); 989 990 if ((ifp == NULL) && (ro->ro_rt != NULL)) 991 ifp = ro->ro_rt->rt_ifp; 992 993 if ((ro->ro_rt == NULL) || (ifp == NULL)) { 994 if (in_localaddr(ip->ip_dst)) 995 error = EHOSTUNREACH; 996 else 997 error = ENETUNREACH; 998 goto bad; 999 } 1000 if (ro->ro_rt->rt_flags & RTF_GATEWAY) 1001 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; 1002 if (ro->ro_rt) 1003 ro->ro_rt->rt_use++; 1004 1005 /* 1006 * For input packets which are being "fastrouted", they won't 1007 * go back through output filtering and miss their chance to get 1008 * NAT'd and counted. Duplicated packets aren't considered to be 1009 * part of the normal packet stream, so do not NAT them or pass 1010 * them through stateful checking, etc. 1011 */ 1012 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { 1013 sifp = fin->fin_ifp; 1014 fin->fin_ifp = ifp; 1015 fin->fin_out = 1; 1016 (void) fr_acctpkt(fin, NULL); 1017 fin->fin_fr = NULL; 1018 if (!fr || !(fr->fr_flags & FR_RETMASK)) { 1019 u_32_t pass; 1020 1021 if (fr_checkstate(fin, &pass) != NULL) 1022 fr_statederef((ipstate_t **)&fin->fin_state); 1023 } 1024 1025 switch (fr_checknatout(fin, NULL)) 1026 { 1027 case 0 : 1028 break; 1029 case 1 : 1030 fr_natderef((nat_t **)&fin->fin_nat); 1031 ip->ip_sum = 0; 1032 break; 1033 case -1 : 1034 error = -1; 1035 goto bad; 1036 break; 1037 } 1038 1039 fin->fin_ifp = sifp; 1040 fin->fin_out = 0; 1041 } else 1042 ip->ip_sum = 0; 1043 /* 1044 * If small enough for interface, can just send directly. 1045 */ 1046 if (ip->ip_len <= ifp->if_mtu) { 1047 ip->ip_len = htons(ip->ip_len); 1048 ip->ip_off = htons(ip->ip_off); 1049 1050 if (!ip->ip_sum) 1051 ip->ip_sum = in_cksum(m, hlen); 1052 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, 1053 ro); 1054 goto done; 1055 } 1056 /* 1057 * Too large for interface; fragment if possible. 1058 * Must be able to put at least 8 bytes per fragment. 1059 */ 1060 ip_off = ntohs(ip->ip_off); 1061 if (ip_off & IP_DF) { 1062 error = EMSGSIZE; 1063 goto bad; 1064 } 1065 len = (ifp->if_mtu - hlen) &~ 7; 1066 if (len < 8) { 1067 error = EMSGSIZE; 1068 goto bad; 1069 } 1070 1071 { 1072 int mhlen, firstlen = len; 1073 struct mbuf **mnext = &m->m_act; 1074 1075 /* 1076 * Loop through length of segment after first fragment, 1077 * make new header and copy data of each part and link onto chain. 1078 */ 1079 m0 = m; 1080 mhlen = sizeof (struct ip); 1081 for (off = hlen + len; off < ip->ip_len; off += len) { 1082#ifdef MGETHDR 1083 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1084#else 1085 MGET(m, M_DONTWAIT, MT_HEADER); 1086#endif 1087 if (m == 0) { 1088 m = m0; 1089 error = ENOBUFS; 1090 goto bad; 1091 } 1092 m->m_data += max_linkhdr; 1093 mhip = mtod(m, struct ip *); 1094 bcopy((char *)ip, (char *)mhip, sizeof(*ip)); 1095 if (hlen > sizeof (struct ip)) { 1096 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 1097 IP_HL_A(mhip, mhlen >> 2); 1098 } 1099 m->m_len = mhlen; 1100 mhip->ip_off = ((off - hlen) >> 3) + ip_off; 1101 if (off + len >= ip->ip_len) 1102 len = ip->ip_len - off; 1103 else 1104 mhip->ip_off |= IP_MF; 1105 mhip->ip_len = htons((u_short)(len + mhlen)); 1106 *mnext = m; 1107 m->m_next = m_copy(m0, off, len); 1108 if (m->m_next == 0) { 1109 error = ENOBUFS; /* ??? */ 1110 goto sendorfree; 1111 } 1112 m->m_pkthdr.len = mhlen + len; 1113 m->m_pkthdr.rcvif = NULL; 1114 mhip->ip_off = htons((u_short)mhip->ip_off); 1115 mhip->ip_sum = 0; 1116 mhip->ip_sum = in_cksum(m, mhlen); 1117 mnext = &m->m_act; 1118 } 1119 /* 1120 * Update first fragment by trimming what's been copied out 1121 * and updating header, then send each fragment (in order). 1122 */ 1123 m_adj(m0, hlen + firstlen - ip->ip_len); 1124 ip->ip_len = htons((u_short)(hlen + firstlen)); 1125 ip->ip_off = htons((u_short)IP_MF); 1126 ip->ip_sum = 0; 1127 ip->ip_sum = in_cksum(m0, hlen); 1128sendorfree: 1129 for (m = m0; m; m = m0) { 1130 m0 = m->m_act; 1131 m->m_act = 0; 1132 if (error == 0) 1133 error = (*ifp->if_output)(ifp, m, 1134 (struct sockaddr *)dst, ro); 1135 else 1136 FREE_MB_T(m); 1137 } 1138 } 1139done: 1140 if (!error) 1141 fr_frouteok[0]++; 1142 else 1143 fr_frouteok[1]++; 1144 1145 if ((ro != NULL) && (ro->ro_rt != NULL)) { 1146 RTFREE(ro->ro_rt); 1147 } 1148 *mpp = NULL; 1149 return 0; 1150bad: 1151 if (error == EMSGSIZE) { 1152 sifp = fin->fin_ifp; 1153 code = fin->fin_icode; 1154 fin->fin_icode = ICMP_UNREACH_NEEDFRAG; 1155 fin->fin_ifp = ifp; 1156 (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1); 1157 fin->fin_ifp = sifp; 1158 fin->fin_icode = code; 1159 } 1160 FREE_MB_T(m); 1161 goto done; 1162} 1163 1164 1165int fr_verifysrc(fin) 1166fr_info_t *fin; 1167{ 1168 struct sockaddr_in *dst; 1169 struct route iproute; 1170 1171 bzero((char *)&iproute, sizeof(iproute)); 1172 dst = (struct sockaddr_in *)&iproute.ro_dst; 1173 dst->sin_len = sizeof(*dst); 1174 dst->sin_family = AF_INET; 1175 dst->sin_addr = fin->fin_src; 1176 in_rtalloc(&iproute, 0); 1177 if (iproute.ro_rt == NULL) 1178 return 0; 1179 return (fin->fin_ifp == iproute.ro_rt->rt_ifp); 1180} 1181 1182 1183/* 1184 * return the first IP Address associated with an interface 1185 */ 1186int fr_ifpaddr(v, atype, ifptr, inp, inpmask) 1187int v, atype; 1188void *ifptr; 1189struct in_addr *inp, *inpmask; 1190{ 1191#ifdef USE_INET6 1192 struct in6_addr *inp6 = NULL; 1193#endif 1194 struct sockaddr *sock, *mask; 1195 struct sockaddr_in *sin; 1196 struct ifaddr *ifa; 1197 struct ifnet *ifp; 1198 1199 if ((ifptr == NULL) || (ifptr == (void *)-1)) 1200 return -1; 1201 1202 sin = NULL; 1203 ifp = ifptr; 1204 1205 if (v == 4) 1206 inp->s_addr = 0; 1207#ifdef USE_INET6 1208 else if (v == 6) 1209 bzero((char *)inp, sizeof(struct in6_addr)); 1210#endif 1211#if (__FreeBSD_version >= 300000) 1212 ifa = TAILQ_FIRST(&ifp->if_addrhead); 1213#else 1214 ifa = ifp->if_addrlist; 1215#endif /* __FreeBSD_version >= 300000 */ 1216 1217 sock = ifa->ifa_addr; 1218 while (sock != NULL && ifa != NULL) { 1219 sin = (struct sockaddr_in *)sock; 1220 if ((v == 4) && (sin->sin_family == AF_INET)) 1221 break; 1222#ifdef USE_INET6 1223 if ((v == 6) && (sin->sin_family == AF_INET6)) { 1224 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1225 if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1226 !IN6_IS_ADDR_LOOPBACK(inp6)) 1227 break; 1228 } 1229#endif 1230#if (__FreeBSD_version >= 300000) 1231 ifa = TAILQ_NEXT(ifa, ifa_link); 1232#else 1233 ifa = ifa->ifa_next; 1234#endif /* __FreeBSD_version >= 300000 */ 1235 if (ifa != NULL) 1236 sock = ifa->ifa_addr; 1237 } 1238 1239 if (ifa == NULL || sin == NULL) 1240 return -1; 1241 1242 mask = ifa->ifa_netmask; 1243 if (atype == FRI_BROADCAST) 1244 sock = ifa->ifa_broadaddr; 1245 else if (atype == FRI_PEERADDR) 1246 sock = ifa->ifa_dstaddr; 1247 1248 if (sock == NULL) 1249 return -1; 1250 1251#ifdef USE_INET6 1252 if (v == 6) { 1253 return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, 1254 (struct sockaddr_in6 *)mask, 1255 inp, inpmask); 1256 } 1257#endif 1258 return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock, 1259 (struct sockaddr_in *)mask, inp, inpmask); 1260} 1261 1262 1263u_32_t fr_newisn(fin) 1264fr_info_t *fin; 1265{ 1266 u_32_t newiss; 1267#if (__FreeBSD_version >= 400000) 1268 newiss = arc4random(); 1269#else 1270 static iss_seq_off = 0; 1271 u_char hash[16]; 1272 MD5_CTX ctx; 1273 1274 /* 1275 * Compute the base value of the ISS. It is a hash 1276 * of (saddr, sport, daddr, dport, secret). 1277 */ 1278 MD5Init(&ctx); 1279 1280 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 1281 sizeof(fin->fin_fi.fi_src)); 1282 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 1283 sizeof(fin->fin_fi.fi_dst)); 1284 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 1285 1286 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); 1287 1288 MD5Final(hash, &ctx); 1289 1290 memcpy(&newiss, hash, sizeof(newiss)); 1291 1292 /* 1293 * Now increment our "timer", and add it in to 1294 * the computed value. 1295 * 1296 * XXX Use `addin'? 1297 * XXX TCP_ISSINCR too large to use? 1298 */ 1299 iss_seq_off += 0x00010000; 1300 newiss += iss_seq_off; 1301#endif 1302 return newiss; 1303} 1304 1305 1306/* ------------------------------------------------------------------------ */ 1307/* Function: fr_nextipid */ 1308/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 1309/* Parameters: fin(I) - pointer to packet information */ 1310/* */ 1311/* Returns the next IPv4 ID to use for this packet. */ 1312/* ------------------------------------------------------------------------ */ 1313u_short fr_nextipid(fin) 1314fr_info_t *fin; 1315{ 1316#ifndef RANDOM_IP_ID 1317 static u_short ipid = 0; 1318 u_short id; 1319 1320 MUTEX_ENTER(&ipf_rw); 1321 id = ipid++; 1322 MUTEX_EXIT(&ipf_rw); 1323#else 1324 u_short id; 1325 1326 id = ip_randomid(); 1327#endif 1328 1329 return id; 1330} 1331 1332 1333INLINE void fr_checkv4sum(fin) 1334fr_info_t *fin; 1335{ 1336#ifdef CSUM_DATA_VALID 1337 int manual = 0; 1338 u_short sum; 1339 ip_t *ip; 1340 mb_t *m; 1341 1342 if ((fin->fin_flx & FI_NOCKSUM) != 0) 1343 return; 1344 1345 if (fin->fin_cksum != 0) 1346 return; 1347 1348 m = fin->fin_m; 1349 if (m == NULL) { 1350 manual = 1; 1351 goto skipauto; 1352 } 1353 ip = fin->fin_ip; 1354 1355 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 1356 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) 1357 sum = m->m_pkthdr.csum_data; 1358 else 1359 sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, 1360 htonl(m->m_pkthdr.csum_data + 1361 fin->fin_ip->ip_len + fin->fin_p)); 1362 sum ^= 0xffff; 1363 if (sum != 0) { 1364 fin->fin_flx |= FI_BAD; 1365 fin->fin_cksum = -1; 1366 } else { 1367 fin->fin_cksum = 1; 1368 } 1369 } else 1370 manual = 1; 1371skipauto: 1372# ifdef IPFILTER_CKSUM 1373 if (manual != 0) 1374 if (fr_checkl4sum(fin) == -1) 1375 fin->fin_flx |= FI_BAD; 1376# else 1377 ; 1378# endif 1379#else 1380# ifdef IPFILTER_CKSUM 1381 if (fr_checkl4sum(fin) == -1) 1382 fin->fin_flx |= FI_BAD; 1383# endif 1384#endif 1385} 1386 1387 1388#ifdef USE_INET6 1389INLINE void fr_checkv6sum(fin) 1390fr_info_t *fin; 1391{ 1392# ifdef IPFILTER_CKSUM 1393 if (fr_checkl4sum(fin) == -1) 1394 fin->fin_flx |= FI_BAD; 1395# endif 1396} 1397#endif /* USE_INET6 */ 1398 1399 1400size_t mbufchainlen(m0) 1401struct mbuf *m0; 1402{ 1403 size_t len; 1404 1405 if ((m0->m_flags & M_PKTHDR) != 0) { 1406 len = m0->m_pkthdr.len; 1407 } else { 1408 struct mbuf *m; 1409 1410 for (m = m0, len = 0; m != NULL; m = m->m_next) 1411 len += m->m_len; 1412 } 1413 return len; 1414} 1415 1416 1417/* ------------------------------------------------------------------------ */ 1418/* Function: fr_pullup */ 1419/* Returns: NULL == pullup failed, else pointer to protocol header */ 1420/* Parameters: m(I) - pointer to buffer where data packet starts */ 1421/* fin(I) - pointer to packet information */ 1422/* len(I) - number of bytes to pullup */ 1423/* */ 1424/* Attempt to move at least len bytes (from the start of the buffer) into a */ 1425/* single buffer for ease of access. Operating system native functions are */ 1426/* used to manage buffers - if necessary. If the entire packet ends up in */ 1427/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */ 1428/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ 1429/* and ONLY if the pullup succeeds. */ 1430/* */ 1431/* We assume that 'min' is a pointer to a buffer that is part of the chain */ 1432/* of buffers that starts at *fin->fin_mp. */ 1433/* ------------------------------------------------------------------------ */ 1434void *fr_pullup(min, fin, len) 1435mb_t *min; 1436fr_info_t *fin; 1437int len; 1438{ 1439 int out = fin->fin_out, dpoff, ipoff; 1440 mb_t *m = min; 1441 char *ip; 1442 1443 if (m == NULL) 1444 return NULL; 1445 1446 ip = (char *)fin->fin_ip; 1447 if ((fin->fin_flx & FI_COALESCE) != 0) 1448 return ip; 1449 1450 ipoff = fin->fin_ipoff; 1451 if (fin->fin_dp != NULL) 1452 dpoff = (char *)fin->fin_dp - (char *)ip; 1453 else 1454 dpoff = 0; 1455 1456 if (M_LEN(m) < len) { 1457#ifdef MHLEN 1458 /* 1459 * Assume that M_PKTHDR is set and just work with what is left 1460 * rather than check.. 1461 * Should not make any real difference, anyway. 1462 */ 1463 if (len > MHLEN) 1464#else 1465 if (len > MLEN) 1466#endif 1467 { 1468#ifdef HAVE_M_PULLDOWN 1469 if (m_pulldown(m, 0, len, NULL) == NULL) 1470 m = NULL; 1471#else 1472 FREE_MB_T(*fin->fin_mp); 1473 m = NULL; 1474#endif 1475 } else 1476 { 1477 m = m_pullup(m, len); 1478 } 1479 *fin->fin_mp = m; 1480 if (m == NULL) { 1481 fin->fin_m = NULL; 1482 ATOMIC_INCL(frstats[out].fr_pull[1]); 1483 return NULL; 1484 } 1485 1486 while (M_LEN(m) == 0) { 1487 m = m->m_next; 1488 } 1489 fin->fin_m = m; 1490 ip = MTOD(m, char *) + ipoff; 1491 } 1492 1493 ATOMIC_INCL(frstats[out].fr_pull[0]); 1494 fin->fin_ip = (ip_t *)ip; 1495 if (fin->fin_dp != NULL) 1496 fin->fin_dp = (char *)fin->fin_ip + dpoff; 1497 1498 if (len == fin->fin_plen) 1499 fin->fin_flx |= FI_COALESCE; 1500 return ip; 1501} 1502 1503 1504int ipf_inject(fin, m) 1505fr_info_t *fin; 1506mb_t *m; 1507{ 1508 int error = 0; 1509 1510 if (fin->fin_out == 0) { 1511#if (__FreeBSD_version >= 501000) 1512 netisr_dispatch(NETISR_IP, m); 1513#else 1514 struct ifqueue *ifq; 1515 1516 ifq = &ipintrq; 1517 1518# ifdef _IF_QFULL 1519 if (_IF_QFULL(ifq)) 1520# else 1521 if (IF_QFULL(ifq)) 1522# endif 1523 { 1524# ifdef _IF_DROP 1525 _IF_DROP(ifq); 1526# else 1527 IF_DROP(ifq); 1528# endif 1529 FREE_MB_T(m); 1530 error = ENOBUFS; 1531 } else { 1532 IF_ENQUEUE(ifq, m); 1533 } 1534#endif 1535 } else { 1536 fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len); 1537 fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off); 1538#if (__FreeBSD_version >= 470102) 1539 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); 1540#else 1541 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); 1542#endif 1543 } 1544 1545 return error; 1546} 1547 1548int ipf_pfil_unhook(void) { 1549#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) 1550# if __FreeBSD_version >= 501108 1551 struct pfil_head *ph_inet; 1552# ifdef USE_INET6 1553 struct pfil_head *ph_inet6; 1554# endif 1555# endif 1556#endif 1557 1558#ifdef NETBSD_PF 1559# if (__FreeBSD_version >= 500011) 1560# if (__FreeBSD_version >= 501108) 1561 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 1562 if (ph_inet != NULL) 1563 pfil_remove_hook((void *)fr_check_wrapper, NULL, 1564 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); 1565# else 1566 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1567 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 1568# endif 1569# else 1570 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); 1571# endif 1572# ifdef USE_INET6 1573# if (__FreeBSD_version >= 501108) 1574 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 1575 if (ph_inet6 != NULL) 1576 pfil_remove_hook((void *)fr_check_wrapper6, NULL, 1577 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); 1578# else 1579 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1580 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); 1581# endif 1582# endif 1583#endif 1584 1585 return (0); 1586} 1587 1588int ipf_pfil_hook(void) { 1589#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) 1590# if __FreeBSD_version >= 501108 1591 struct pfil_head *ph_inet; 1592# ifdef USE_INET6 1593 struct pfil_head *ph_inet6; 1594# endif 1595# endif 1596#endif 1597 1598# ifdef NETBSD_PF 1599# if __FreeBSD_version >= 500011 1600# if __FreeBSD_version >= 501108 1601 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 1602# ifdef USE_INET6 1603 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 1604# endif 1605 if (ph_inet == NULL 1606# ifdef USE_INET6 1607 && ph_inet6 == NULL 1608# endif 1609 ) 1610 return ENODEV; 1611 1612 if (ph_inet != NULL) 1613 pfil_add_hook((void *)fr_check_wrapper, NULL, 1614 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); 1615# else 1616 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1617 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 1618# endif 1619# else 1620 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); 1621# endif 1622# ifdef USE_INET6 1623# if __FreeBSD_version >= 501108 1624 if (ph_inet6 != NULL) 1625 pfil_add_hook((void *)fr_check_wrapper6, NULL, 1626 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); 1627# else 1628 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1629 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); 1630# endif 1631# endif 1632# endif 1633 return (0); 1634} 1635 1636void 1637ipf_event_reg(void) 1638{ 1639#if (__FreeBSD_version >= 502103) 1640 ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ 1641 ipf_ifevent, NULL, \ 1642 EVENTHANDLER_PRI_ANY); 1643 ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ 1644 ipf_ifevent, NULL, \ 1645 EVENTHANDLER_PRI_ANY); 1646 ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ 1647 NULL, EVENTHANDLER_PRI_ANY); 1648#endif 1649} 1650 1651void 1652ipf_event_dereg(void) 1653{ 1654#if (__FreeBSD_version >= 502103) 1655 if (ipf_arrivetag != NULL) { 1656 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag); 1657 } 1658 if (ipf_departtag != NULL) { 1659 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag); 1660 } 1661 if (ipf_clonetag != NULL) { 1662 EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag); 1663 } 1664#endif 1665}
| 66# include <netinet/tcp_var.h> 67#else 68#define V_path_mtu_discovery path_mtu_discovery 69#define V_ipforwarding ipforwarding 70#endif 71 72#include <net/if.h> 73#if __FreeBSD_version >= 300000 74# include <net/if_var.h> 75# if __FreeBSD_version >= 500043 76# include <net/netisr.h> 77# endif 78# if !defined(IPFILTER_LKM) 79# include "opt_ipfilter.h" 80# endif 81#endif 82#include <net/route.h> 83#include <netinet/in.h> 84#include <netinet/in_var.h> 85#include <netinet/in_systm.h> 86#include <netinet/ip.h> 87#include <netinet/ip_var.h> 88#include <netinet/tcp.h> 89#if defined(__osf__) 90# include <netinet/tcp_timer.h> 91#endif 92#include <netinet/udp.h> 93#include <netinet/tcpip.h> 94#include <netinet/ip_icmp.h> 95#ifndef _KERNEL 96# include "netinet/ipf.h" 97#endif 98#include "netinet/ip_compat.h" 99#ifdef USE_INET6 100# include <netinet/icmp6.h> 101#endif 102#include "netinet/ip_fil.h" 103#include "netinet/ip_nat.h" 104#include "netinet/ip_frag.h" 105#include "netinet/ip_state.h" 106#include "netinet/ip_proxy.h" 107#include "netinet/ip_auth.h" 108#ifdef IPFILTER_SYNC 109#include "netinet/ip_sync.h" 110#endif 111#ifdef IPFILTER_SCAN 112#include "netinet/ip_scan.h" 113#endif 114#include "netinet/ip_pool.h" 115#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 116# include <sys/malloc.h> 117#endif 118#include <sys/kernel.h> 119#ifdef CSUM_DATA_VALID 120#include <machine/in_cksum.h> 121#endif 122extern int ip_optcopy __P((struct ip *, struct ip *)); 123 124#if (__FreeBSD_version > 460000) && (__FreeBSD_version < 800055) 125extern int path_mtu_discovery; 126#endif 127 128# ifdef IPFILTER_M_IPFILTER 129MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures"); 130# endif 131 132 133#if !defined(__osf__) 134extern struct protosw inetsw[]; 135#endif 136 137static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **)); 138static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **)); 139# ifdef USE_MUTEXES 140ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; 141ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; 142ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens; 143ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; 144# endif 145int ipf_locks_done = 0; 146 147#if (__FreeBSD_version >= 300000) 148struct callout_handle fr_slowtimer_ch; 149#endif 150struct selinfo ipfselwait[IPL_LOGSIZE]; 151 152#if (__FreeBSD_version >= 500011) 153# include <sys/conf.h> 154# if defined(NETBSD_PF) 155# include <net/pfil.h> 156# if (__FreeBSD_version < 501108) 157# include <netinet/ipprotosw.h> 158# endif 159/* 160 * We provide the fr_checkp name just to minimize changes later. 161 */ 162int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp)); 163# endif /* NETBSD_PF */ 164#endif /* __FreeBSD_version >= 500011 */ 165 166 167#if (__FreeBSD_version >= 502103) 168static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag; 169 170static void ipf_ifevent(void *arg); 171 172static void ipf_ifevent(arg) 173void *arg; 174{ 175 frsync(NULL); 176} 177#endif 178 179 180#if (__FreeBSD_version >= 501108) && defined(_KERNEL) 181 182static int 183fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 184{ 185 struct ip *ip = mtod(*mp, struct ip *); 186 return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp); 187} 188 189# ifdef USE_INET6 190# include <netinet/ip6.h> 191 192static int 193fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 194{ 195 return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr), 196 ifp, (dir == PFIL_OUT), mp)); 197} 198# endif 199#endif /* __FreeBSD_version >= 501108 */ 200#if defined(IPFILTER_LKM) 201int iplidentify(s) 202char *s; 203{ 204 if (strcmp(s, "ipl") == 0) 205 return 1; 206 return 0; 207} 208#endif /* IPFILTER_LKM */ 209 210 211int ipfattach() 212{ 213#ifdef USE_SPL 214 int s; 215#endif 216 217 SPL_NET(s); 218 if (fr_running > 0) { 219 SPL_X(s); 220 return EBUSY; 221 } 222 223 MUTEX_INIT(&ipf_rw, "ipf rw mutex"); 224 MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex"); 225 RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); 226 RWLOCK_INIT(&ipf_tokens, "ipf token rwlock"); 227 ipf_locks_done = 1; 228 229 if (fr_initialise() < 0) { 230 SPL_X(s); 231 return EIO; 232 } 233 234 235 if (fr_checkp != fr_check) { 236 fr_savep = fr_checkp; 237 fr_checkp = fr_check; 238 } 239 240 bzero((char *)ipfselwait, sizeof(ipfselwait)); 241 bzero((char *)frcache, sizeof(frcache)); 242 fr_running = 1; 243 244 if (fr_control_forwarding & 1) 245 V_ipforwarding = 1; 246 247 SPL_X(s); 248#if (__FreeBSD_version >= 300000) 249 fr_slowtimer_ch = timeout(fr_slowtimer, NULL, 250 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 251#else 252 timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 253#endif 254 return 0; 255} 256 257 258/* 259 * Disable the filter by removing the hooks from the IP input/output 260 * stream. 261 */ 262int ipfdetach() 263{ 264#ifdef USE_SPL 265 int s; 266#endif 267 if (fr_control_forwarding & 2) 268 V_ipforwarding = 0; 269 270 SPL_NET(s); 271 272#if (__FreeBSD_version >= 300000) 273 if (fr_slowtimer_ch.callout != NULL) 274 untimeout(fr_slowtimer, NULL, fr_slowtimer_ch); 275 bzero(&fr_slowtimer_ch, sizeof(fr_slowtimer_ch)); 276#else 277 untimeout(fr_slowtimer, NULL); 278#endif /* FreeBSD */ 279 280#ifndef NETBSD_PF 281 if (fr_checkp != NULL) 282 fr_checkp = fr_savep; 283 fr_savep = NULL; 284#endif 285 286 fr_deinitialise(); 287 288 fr_running = -2; 289 290 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 291 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE); 292 293 if (ipf_locks_done == 1) { 294 MUTEX_DESTROY(&ipf_timeoutlock); 295 MUTEX_DESTROY(&ipf_rw); 296 RW_DESTROY(&ipf_ipidfrag); 297 RW_DESTROY(&ipf_tokens); 298 ipf_locks_done = 0; 299 } 300 301 SPL_X(s); 302 303 return 0; 304} 305 306 307/* 308 * Filter ioctl interface. 309 */ 310int iplioctl(dev, cmd, data, mode 311# if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 312, p) 313# if (__FreeBSD_version >= 500024) 314struct thread *p; 315# if (__FreeBSD_version >= 500043) 316# define p_cred td_ucred 317# define p_uid td_ucred->cr_ruid 318# else 319# define p_cred t_proc->p_cred 320# define p_uid t_proc->p_cred->p_ruid 321# endif 322# else 323struct proc *p; 324# define p_uid p_cred->p_ruid 325# endif /* __FreeBSD_version >= 500024 */ 326# else 327) 328# endif 329#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 330struct cdev *dev; 331#else 332dev_t dev; 333#endif 334ioctlcmd_t cmd; 335caddr_t data; 336int mode; 337{ 338 int error = 0, unit = 0; 339 SPL_INT(s); 340 341#if (BSD >= 199306) && defined(_KERNEL) 342# if (__FreeBSD_version >= 500034) 343 if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE)) 344# else 345 if ((securelevel >= 3) && (mode & FWRITE)) 346# endif 347 return EPERM; 348#endif 349 350 unit = GET_MINOR(dev); 351 if ((IPL_LOGMAX < unit) || (unit < 0)) 352 return ENXIO; 353 354 if (fr_running <= 0) { 355 if (unit != IPL_LOGIPF) 356 return EIO; 357 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && 358 cmd != SIOCIPFSET && cmd != SIOCFRENB && 359 cmd != SIOCGETFS && cmd != SIOCGETFF) 360 return EIO; 361 } 362 363 SPL_NET(s); 364 365 error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p); 366 if (error != -1) { 367 SPL_X(s); 368 return error; 369 } 370 371 SPL_X(s); 372 373 return error; 374} 375 376 377#if 0 378void fr_forgetifp(ifp) 379void *ifp; 380{ 381 register frentry_t *f; 382 383 WRITE_ENTER(&ipf_mutex); 384 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next) 385 if (f->fr_ifa == ifp) 386 f->fr_ifa = (void *)-1; 387 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next) 388 if (f->fr_ifa == ifp) 389 f->fr_ifa = (void *)-1; 390 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next) 391 if (f->fr_ifa == ifp) 392 f->fr_ifa = (void *)-1; 393 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next) 394 if (f->fr_ifa == ifp) 395 f->fr_ifa = (void *)-1; 396#ifdef USE_INET6 397 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next) 398 if (f->fr_ifa == ifp) 399 f->fr_ifa = (void *)-1; 400 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next) 401 if (f->fr_ifa == ifp) 402 f->fr_ifa = (void *)-1; 403 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next) 404 if (f->fr_ifa == ifp) 405 f->fr_ifa = (void *)-1; 406 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next) 407 if (f->fr_ifa == ifp) 408 f->fr_ifa = (void *)-1; 409#endif 410 RWLOCK_EXIT(&ipf_mutex); 411 fr_natsync(ifp); 412} 413#endif 414 415 416/* 417 * routines below for saving IP headers to buffer 418 */ 419int iplopen(dev, flags 420#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) 421, devtype, p) 422int devtype; 423# if (__FreeBSD_version >= 500024) 424struct thread *p; 425# else 426struct proc *p; 427# endif /* __FreeBSD_version >= 500024 */ 428#else 429) 430#endif 431#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 432struct cdev *dev; 433#else 434dev_t dev; 435#endif 436int flags; 437{ 438 u_int min = GET_MINOR(dev); 439 440 if (IPL_LOGMAX < min) 441 min = ENXIO; 442 else 443 min = 0; 444 return min; 445} 446 447 448int iplclose(dev, flags 449#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL) 450, devtype, p) 451int devtype; 452# if (__FreeBSD_version >= 500024) 453struct thread *p; 454# else 455struct proc *p; 456# endif /* __FreeBSD_version >= 500024 */ 457#else 458) 459#endif 460#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 461struct cdev *dev; 462#else 463dev_t dev; 464#endif 465int flags; 466{ 467 u_int min = GET_MINOR(dev); 468 469 if (IPL_LOGMAX < min) 470 min = ENXIO; 471 else 472 min = 0; 473 return min; 474} 475 476/* 477 * iplread/ipllog 478 * both of these must operate with at least splnet() lest they be 479 * called during packet processing and cause an inconsistancy to appear in 480 * the filter lists. 481 */ 482#if (BSD >= 199306) 483int iplread(dev, uio, ioflag) 484int ioflag; 485#else 486int iplread(dev, uio) 487#endif 488#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 489struct cdev *dev; 490#else 491dev_t dev; 492#endif 493register struct uio *uio; 494{ 495 u_int xmin = GET_MINOR(dev); 496 497 if (fr_running < 1) 498 return EIO; 499 500 if (xmin < 0) 501 return ENXIO; 502 503# ifdef IPFILTER_SYNC 504 if (xmin == IPL_LOGSYNC) 505 return ipfsync_read(uio); 506# endif 507 508#ifdef IPFILTER_LOG 509 return ipflog_read(xmin, uio); 510#else 511 return ENXIO; 512#endif 513} 514 515 516/* 517 * iplwrite 518 * both of these must operate with at least splnet() lest they be 519 * called during packet processing and cause an inconsistancy to appear in 520 * the filter lists. 521 */ 522#if (BSD >= 199306) 523int iplwrite(dev, uio, ioflag) 524int ioflag; 525#else 526int iplwrite(dev, uio) 527#endif 528#if defined(_KERNEL) && (__FreeBSD_version >= 502116) 529struct cdev *dev; 530#else 531dev_t dev; 532#endif 533register struct uio *uio; 534{ 535 536 if (fr_running < 1) 537 return EIO; 538 539#ifdef IPFILTER_SYNC 540 if (GET_MINOR(dev) == IPL_LOGSYNC) 541 return ipfsync_write(uio); 542#endif 543 return ENXIO; 544} 545 546 547/* 548 * fr_send_reset - this could conceivably be a call to tcp_respond(), but that 549 * requires a large amount of setting up and isn't any more efficient. 550 */ 551int fr_send_reset(fin) 552fr_info_t *fin; 553{ 554 struct tcphdr *tcp, *tcp2; 555 int tlen = 0, hlen; 556 struct mbuf *m; 557#ifdef USE_INET6 558 ip6_t *ip6; 559#endif 560 ip_t *ip; 561 562 tcp = fin->fin_dp; 563 if (tcp->th_flags & TH_RST) 564 return -1; /* feedback loop */ 565 566 if (fr_checkl4sum(fin) == -1) 567 return -1; 568 569 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + 570 ((tcp->th_flags & TH_SYN) ? 1 : 0) + 571 ((tcp->th_flags & TH_FIN) ? 1 : 0); 572 573#ifdef USE_INET6 574 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); 575#else 576 hlen = sizeof(ip_t); 577#endif 578#ifdef MGETHDR 579 MGETHDR(m, M_DONTWAIT, MT_HEADER); 580#else 581 MGET(m, M_DONTWAIT, MT_HEADER); 582#endif 583 if (m == NULL) 584 return -1; 585 if (sizeof(*tcp2) + hlen > MLEN) { 586 MCLGET(m, M_DONTWAIT); 587 if ((m->m_flags & M_EXT) == 0) { 588 FREE_MB_T(m); 589 return -1; 590 } 591 } 592 593 m->m_len = sizeof(*tcp2) + hlen; 594#if (BSD >= 199103) 595 m->m_data += max_linkhdr; 596 m->m_pkthdr.len = m->m_len; 597 m->m_pkthdr.rcvif = (struct ifnet *)0; 598#endif 599 ip = mtod(m, struct ip *); 600 bzero((char *)ip, hlen); 601#ifdef USE_INET6 602 ip6 = (ip6_t *)ip; 603#endif 604 tcp2 = (struct tcphdr *)((char *)ip + hlen); 605 tcp2->th_sport = tcp->th_dport; 606 tcp2->th_dport = tcp->th_sport; 607 608 if (tcp->th_flags & TH_ACK) { 609 tcp2->th_seq = tcp->th_ack; 610 tcp2->th_flags = TH_RST; 611 tcp2->th_ack = 0; 612 } else { 613 tcp2->th_seq = 0; 614 tcp2->th_ack = ntohl(tcp->th_seq); 615 tcp2->th_ack += tlen; 616 tcp2->th_ack = htonl(tcp2->th_ack); 617 tcp2->th_flags = TH_RST|TH_ACK; 618 } 619 TCP_X2_A(tcp2, 0); 620 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); 621 tcp2->th_win = tcp->th_win; 622 tcp2->th_sum = 0; 623 tcp2->th_urp = 0; 624 625#ifdef USE_INET6 626 if (fin->fin_v == 6) { 627 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 628 ip6->ip6_plen = htons(sizeof(struct tcphdr)); 629 ip6->ip6_nxt = IPPROTO_TCP; 630 ip6->ip6_hlim = 0; 631 ip6->ip6_src = fin->fin_dst6; 632 ip6->ip6_dst = fin->fin_src6; 633 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, 634 sizeof(*ip6), sizeof(*tcp2)); 635 return fr_send_ip(fin, m, &m); 636 } 637#endif 638 ip->ip_p = IPPROTO_TCP; 639 ip->ip_len = htons(sizeof(struct tcphdr)); 640 ip->ip_src.s_addr = fin->fin_daddr; 641 ip->ip_dst.s_addr = fin->fin_saddr; 642 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); 643 ip->ip_len = hlen + sizeof(*tcp2); 644 return fr_send_ip(fin, m, &m); 645} 646 647 648static int fr_send_ip(fin, m, mpp) 649fr_info_t *fin; 650mb_t *m, **mpp; 651{ 652 fr_info_t fnew; 653 ip_t *ip, *oip; 654 int hlen; 655 656 ip = mtod(m, ip_t *); 657 bzero((char *)&fnew, sizeof(fnew)); 658 659 IP_V_A(ip, fin->fin_v); 660 switch (fin->fin_v) 661 { 662 case 4 : 663 fnew.fin_v = 4; 664 oip = fin->fin_ip; 665 IP_HL_A(ip, sizeof(*oip) >> 2); 666 ip->ip_tos = oip->ip_tos; 667 ip->ip_id = fin->fin_ip->ip_id; 668#if (__FreeBSD_version > 460000) 669 ip->ip_off = V_path_mtu_discovery ? IP_DF : 0; 670#else 671 ip->ip_off = 0; 672#endif 673 ip->ip_ttl = V_ip_defttl; 674 ip->ip_sum = 0; 675 hlen = sizeof(*oip); 676 break; 677#ifdef USE_INET6 678 case 6 : 679 { 680 ip6_t *ip6 = (ip6_t *)ip; 681 682 ip6->ip6_vfc = 0x60; 683 ip6->ip6_hlim = IPDEFTTL; 684 685 fnew.fin_v = 6; 686 hlen = sizeof(*ip6); 687 break; 688 } 689#endif 690 default : 691 return EINVAL; 692 } 693#ifdef IPSEC 694 m->m_pkthdr.rcvif = NULL; 695#endif 696 697 fnew.fin_ifp = fin->fin_ifp; 698 fnew.fin_flx = FI_NOCKSUM; 699 fnew.fin_m = m; 700 fnew.fin_ip = ip; 701 fnew.fin_mp = mpp; 702 fnew.fin_hlen = hlen; 703 fnew.fin_dp = (char *)ip + hlen; 704 (void) fr_makefrip(hlen, ip, &fnew); 705 706 return fr_fastroute(m, mpp, &fnew, NULL); 707} 708 709 710int fr_send_icmp_err(type, fin, dst) 711int type; 712fr_info_t *fin; 713int dst; 714{ 715 int err, hlen, xtra, iclen, ohlen, avail, code; 716 struct in_addr dst4; 717 struct icmp *icmp; 718 struct mbuf *m; 719 void *ifp; 720#ifdef USE_INET6 721 ip6_t *ip6; 722 struct in6_addr dst6; 723#endif 724 ip_t *ip, *ip2; 725 726 if ((type < 0) || (type >= ICMP_MAXTYPE)) 727 return -1; 728 729 code = fin->fin_icode; 730#ifdef USE_INET6 731 if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int))) 732 return -1; 733#endif 734 735 if (fr_checkl4sum(fin) == -1) 736 return -1; 737#ifdef MGETHDR 738 MGETHDR(m, M_DONTWAIT, MT_HEADER); 739#else 740 MGET(m, M_DONTWAIT, MT_HEADER); 741#endif 742 if (m == NULL) 743 return -1; 744 avail = MHLEN; 745 746 xtra = 0; 747 hlen = 0; 748 ohlen = 0; 749 ifp = fin->fin_ifp; 750 if (fin->fin_v == 4) { 751 if ((fin->fin_p == IPPROTO_ICMP) && 752 !(fin->fin_flx & FI_SHORT)) 753 switch (ntohs(fin->fin_data[0]) >> 8) 754 { 755 case ICMP_ECHO : 756 case ICMP_TSTAMP : 757 case ICMP_IREQ : 758 case ICMP_MASKREQ : 759 break; 760 default : 761 FREE_MB_T(m); 762 return 0; 763 } 764 765 if (dst == 0) { 766 if (fr_ifpaddr(4, FRI_NORMAL, ifp, 767 &dst4, NULL) == -1) { 768 FREE_MB_T(m); 769 return -1; 770 } 771 } else 772 dst4.s_addr = fin->fin_daddr; 773 774 hlen = sizeof(ip_t); 775 ohlen = fin->fin_hlen; 776 if (fin->fin_hlen < fin->fin_plen) 777 xtra = MIN(fin->fin_dlen, 8); 778 else 779 xtra = 0; 780 } 781 782#ifdef USE_INET6 783 else if (fin->fin_v == 6) { 784 hlen = sizeof(ip6_t); 785 ohlen = sizeof(ip6_t); 786 type = icmptoicmp6types[type]; 787 if (type == ICMP6_DST_UNREACH) 788 code = icmptoicmp6unreach[code]; 789 790 if (hlen + sizeof(*icmp) + max_linkhdr + 791 fin->fin_plen > avail) { 792 MCLGET(m, M_DONTWAIT); 793 if ((m->m_flags & M_EXT) == 0) { 794 FREE_MB_T(m); 795 return -1; 796 } 797 avail = MCLBYTES; 798 } 799 xtra = MIN(fin->fin_plen, 800 avail - hlen - sizeof(*icmp) - max_linkhdr); 801 if (dst == 0) { 802 if (fr_ifpaddr(6, FRI_NORMAL, ifp, 803 (struct in_addr *)&dst6, NULL) == -1) { 804 FREE_MB_T(m); 805 return -1; 806 } 807 } else 808 dst6 = fin->fin_dst6; 809 } 810#endif 811 else { 812 FREE_MB_T(m); 813 return -1; 814 } 815 816 iclen = hlen + sizeof(*icmp); 817 avail -= (max_linkhdr + iclen); 818 if (avail < 0) { 819 FREE_MB_T(m); 820 return -1; 821 } 822 if (xtra > avail) 823 xtra = avail; 824 iclen += xtra; 825 m->m_data += max_linkhdr; 826 m->m_pkthdr.rcvif = (struct ifnet *)0; 827 m->m_pkthdr.len = iclen; 828 m->m_len = iclen; 829 ip = mtod(m, ip_t *); 830 icmp = (struct icmp *)((char *)ip + hlen); 831 ip2 = (ip_t *)&icmp->icmp_ip; 832 833 icmp->icmp_type = type; 834 icmp->icmp_code = fin->fin_icode; 835 icmp->icmp_cksum = 0; 836#ifdef icmp_nextmtu 837 if (type == ICMP_UNREACH && 838 fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp) 839 icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu); 840#endif 841 842 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); 843 844#ifdef USE_INET6 845 ip6 = (ip6_t *)ip; 846 if (fin->fin_v == 6) { 847 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 848 ip6->ip6_plen = htons(iclen - hlen); 849 ip6->ip6_nxt = IPPROTO_ICMPV6; 850 ip6->ip6_hlim = 0; 851 ip6->ip6_src = dst6; 852 ip6->ip6_dst = fin->fin_src6; 853 if (xtra > 0) 854 bcopy((char *)fin->fin_ip + ohlen, 855 (char *)&icmp->icmp_ip + ohlen, xtra); 856 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, 857 sizeof(*ip6), iclen - hlen); 858 } else 859#endif 860 { 861 ip2->ip_len = htons(ip2->ip_len); 862 ip2->ip_off = htons(ip2->ip_off); 863 ip->ip_p = IPPROTO_ICMP; 864 ip->ip_src.s_addr = dst4.s_addr; 865 ip->ip_dst.s_addr = fin->fin_saddr; 866 867 if (xtra > 0) 868 bcopy((char *)fin->fin_ip + ohlen, 869 (char *)&icmp->icmp_ip + ohlen, xtra); 870 icmp->icmp_cksum = ipf_cksum((u_short *)icmp, 871 sizeof(*icmp) + 8); 872 ip->ip_len = iclen; 873 ip->ip_p = IPPROTO_ICMP; 874 } 875 err = fr_send_ip(fin, m, &m); 876 return err; 877} 878 879 880#if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) 881# if (BSD < 199306) 882int iplinit __P((void)); 883 884int 885# else 886void iplinit __P((void)); 887 888void 889# endif 890iplinit() 891{ 892 if (ipfattach() != 0) 893 printf("IP Filter failed to attach\n"); 894 ip_init(); 895} 896#endif /* __FreeBSD_version < 300000 */ 897 898 899/* 900 * m0 - pointer to mbuf where the IP packet starts 901 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain 902 */ 903int fr_fastroute(m0, mpp, fin, fdp) 904mb_t *m0, **mpp; 905fr_info_t *fin; 906frdest_t *fdp; 907{ 908 register struct ip *ip, *mhip; 909 register struct mbuf *m = *mpp; 910 register struct route *ro; 911 int len, off, error = 0, hlen, code; 912 struct ifnet *ifp, *sifp; 913 struct sockaddr_in *dst; 914 struct route iproute; 915 u_short ip_off; 916 frentry_t *fr; 917 918 ro = NULL; 919 920#ifdef M_WRITABLE 921 /* 922 * HOT FIX/KLUDGE: 923 * 924 * If the mbuf we're about to send is not writable (because of 925 * a cluster reference, for example) we'll need to make a copy 926 * of it since this routine modifies the contents. 927 * 928 * If you have non-crappy network hardware that can transmit data 929 * from the mbuf, rather than making a copy, this is gonna be a 930 * problem. 931 */ 932 if (M_WRITABLE(m) == 0) { 933 m0 = m_dup(m, M_DONTWAIT); 934 if (m0 != 0) { 935 FREE_MB_T(m); 936 m = m0; 937 *mpp = m; 938 } else { 939 error = ENOBUFS; 940 FREE_MB_T(m); 941 goto done; 942 } 943 } 944#endif 945 946#ifdef USE_INET6 947 if (fin->fin_v == 6) { 948 /* 949 * currently "to <if>" and "to <if>:ip#" are not supported 950 * for IPv6 951 */ 952#if (__FreeBSD_version >= 490000) 953 return ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL); 954#else 955 return ip6_output(m0, NULL, NULL, 0, NULL, NULL); 956#endif 957 } 958#endif 959 960 hlen = fin->fin_hlen; 961 ip = mtod(m0, struct ip *); 962 963 /* 964 * Route packet. 965 */ 966 ro = &iproute; 967 bzero((caddr_t)ro, sizeof (*ro)); 968 dst = (struct sockaddr_in *)&ro->ro_dst; 969 dst->sin_family = AF_INET; 970 dst->sin_addr = ip->ip_dst; 971 972 fr = fin->fin_fr; 973 if (fdp != NULL) 974 ifp = fdp->fd_ifp; 975 else 976 ifp = fin->fin_ifp; 977 978 if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) { 979 error = -2; 980 goto bad; 981 } 982 983 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 984 dst->sin_addr = fdp->fd_ip; 985 986 dst->sin_len = sizeof(*dst); 987 in_rtalloc(ro, 0); 988 989 if ((ifp == NULL) && (ro->ro_rt != NULL)) 990 ifp = ro->ro_rt->rt_ifp; 991 992 if ((ro->ro_rt == NULL) || (ifp == NULL)) { 993 if (in_localaddr(ip->ip_dst)) 994 error = EHOSTUNREACH; 995 else 996 error = ENETUNREACH; 997 goto bad; 998 } 999 if (ro->ro_rt->rt_flags & RTF_GATEWAY) 1000 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; 1001 if (ro->ro_rt) 1002 ro->ro_rt->rt_use++; 1003 1004 /* 1005 * For input packets which are being "fastrouted", they won't 1006 * go back through output filtering and miss their chance to get 1007 * NAT'd and counted. Duplicated packets aren't considered to be 1008 * part of the normal packet stream, so do not NAT them or pass 1009 * them through stateful checking, etc. 1010 */ 1011 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { 1012 sifp = fin->fin_ifp; 1013 fin->fin_ifp = ifp; 1014 fin->fin_out = 1; 1015 (void) fr_acctpkt(fin, NULL); 1016 fin->fin_fr = NULL; 1017 if (!fr || !(fr->fr_flags & FR_RETMASK)) { 1018 u_32_t pass; 1019 1020 if (fr_checkstate(fin, &pass) != NULL) 1021 fr_statederef((ipstate_t **)&fin->fin_state); 1022 } 1023 1024 switch (fr_checknatout(fin, NULL)) 1025 { 1026 case 0 : 1027 break; 1028 case 1 : 1029 fr_natderef((nat_t **)&fin->fin_nat); 1030 ip->ip_sum = 0; 1031 break; 1032 case -1 : 1033 error = -1; 1034 goto bad; 1035 break; 1036 } 1037 1038 fin->fin_ifp = sifp; 1039 fin->fin_out = 0; 1040 } else 1041 ip->ip_sum = 0; 1042 /* 1043 * If small enough for interface, can just send directly. 1044 */ 1045 if (ip->ip_len <= ifp->if_mtu) { 1046 ip->ip_len = htons(ip->ip_len); 1047 ip->ip_off = htons(ip->ip_off); 1048 1049 if (!ip->ip_sum) 1050 ip->ip_sum = in_cksum(m, hlen); 1051 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, 1052 ro); 1053 goto done; 1054 } 1055 /* 1056 * Too large for interface; fragment if possible. 1057 * Must be able to put at least 8 bytes per fragment. 1058 */ 1059 ip_off = ntohs(ip->ip_off); 1060 if (ip_off & IP_DF) { 1061 error = EMSGSIZE; 1062 goto bad; 1063 } 1064 len = (ifp->if_mtu - hlen) &~ 7; 1065 if (len < 8) { 1066 error = EMSGSIZE; 1067 goto bad; 1068 } 1069 1070 { 1071 int mhlen, firstlen = len; 1072 struct mbuf **mnext = &m->m_act; 1073 1074 /* 1075 * Loop through length of segment after first fragment, 1076 * make new header and copy data of each part and link onto chain. 1077 */ 1078 m0 = m; 1079 mhlen = sizeof (struct ip); 1080 for (off = hlen + len; off < ip->ip_len; off += len) { 1081#ifdef MGETHDR 1082 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1083#else 1084 MGET(m, M_DONTWAIT, MT_HEADER); 1085#endif 1086 if (m == 0) { 1087 m = m0; 1088 error = ENOBUFS; 1089 goto bad; 1090 } 1091 m->m_data += max_linkhdr; 1092 mhip = mtod(m, struct ip *); 1093 bcopy((char *)ip, (char *)mhip, sizeof(*ip)); 1094 if (hlen > sizeof (struct ip)) { 1095 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 1096 IP_HL_A(mhip, mhlen >> 2); 1097 } 1098 m->m_len = mhlen; 1099 mhip->ip_off = ((off - hlen) >> 3) + ip_off; 1100 if (off + len >= ip->ip_len) 1101 len = ip->ip_len - off; 1102 else 1103 mhip->ip_off |= IP_MF; 1104 mhip->ip_len = htons((u_short)(len + mhlen)); 1105 *mnext = m; 1106 m->m_next = m_copy(m0, off, len); 1107 if (m->m_next == 0) { 1108 error = ENOBUFS; /* ??? */ 1109 goto sendorfree; 1110 } 1111 m->m_pkthdr.len = mhlen + len; 1112 m->m_pkthdr.rcvif = NULL; 1113 mhip->ip_off = htons((u_short)mhip->ip_off); 1114 mhip->ip_sum = 0; 1115 mhip->ip_sum = in_cksum(m, mhlen); 1116 mnext = &m->m_act; 1117 } 1118 /* 1119 * Update first fragment by trimming what's been copied out 1120 * and updating header, then send each fragment (in order). 1121 */ 1122 m_adj(m0, hlen + firstlen - ip->ip_len); 1123 ip->ip_len = htons((u_short)(hlen + firstlen)); 1124 ip->ip_off = htons((u_short)IP_MF); 1125 ip->ip_sum = 0; 1126 ip->ip_sum = in_cksum(m0, hlen); 1127sendorfree: 1128 for (m = m0; m; m = m0) { 1129 m0 = m->m_act; 1130 m->m_act = 0; 1131 if (error == 0) 1132 error = (*ifp->if_output)(ifp, m, 1133 (struct sockaddr *)dst, ro); 1134 else 1135 FREE_MB_T(m); 1136 } 1137 } 1138done: 1139 if (!error) 1140 fr_frouteok[0]++; 1141 else 1142 fr_frouteok[1]++; 1143 1144 if ((ro != NULL) && (ro->ro_rt != NULL)) { 1145 RTFREE(ro->ro_rt); 1146 } 1147 *mpp = NULL; 1148 return 0; 1149bad: 1150 if (error == EMSGSIZE) { 1151 sifp = fin->fin_ifp; 1152 code = fin->fin_icode; 1153 fin->fin_icode = ICMP_UNREACH_NEEDFRAG; 1154 fin->fin_ifp = ifp; 1155 (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1); 1156 fin->fin_ifp = sifp; 1157 fin->fin_icode = code; 1158 } 1159 FREE_MB_T(m); 1160 goto done; 1161} 1162 1163 1164int fr_verifysrc(fin) 1165fr_info_t *fin; 1166{ 1167 struct sockaddr_in *dst; 1168 struct route iproute; 1169 1170 bzero((char *)&iproute, sizeof(iproute)); 1171 dst = (struct sockaddr_in *)&iproute.ro_dst; 1172 dst->sin_len = sizeof(*dst); 1173 dst->sin_family = AF_INET; 1174 dst->sin_addr = fin->fin_src; 1175 in_rtalloc(&iproute, 0); 1176 if (iproute.ro_rt == NULL) 1177 return 0; 1178 return (fin->fin_ifp == iproute.ro_rt->rt_ifp); 1179} 1180 1181 1182/* 1183 * return the first IP Address associated with an interface 1184 */ 1185int fr_ifpaddr(v, atype, ifptr, inp, inpmask) 1186int v, atype; 1187void *ifptr; 1188struct in_addr *inp, *inpmask; 1189{ 1190#ifdef USE_INET6 1191 struct in6_addr *inp6 = NULL; 1192#endif 1193 struct sockaddr *sock, *mask; 1194 struct sockaddr_in *sin; 1195 struct ifaddr *ifa; 1196 struct ifnet *ifp; 1197 1198 if ((ifptr == NULL) || (ifptr == (void *)-1)) 1199 return -1; 1200 1201 sin = NULL; 1202 ifp = ifptr; 1203 1204 if (v == 4) 1205 inp->s_addr = 0; 1206#ifdef USE_INET6 1207 else if (v == 6) 1208 bzero((char *)inp, sizeof(struct in6_addr)); 1209#endif 1210#if (__FreeBSD_version >= 300000) 1211 ifa = TAILQ_FIRST(&ifp->if_addrhead); 1212#else 1213 ifa = ifp->if_addrlist; 1214#endif /* __FreeBSD_version >= 300000 */ 1215 1216 sock = ifa->ifa_addr; 1217 while (sock != NULL && ifa != NULL) { 1218 sin = (struct sockaddr_in *)sock; 1219 if ((v == 4) && (sin->sin_family == AF_INET)) 1220 break; 1221#ifdef USE_INET6 1222 if ((v == 6) && (sin->sin_family == AF_INET6)) { 1223 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1224 if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1225 !IN6_IS_ADDR_LOOPBACK(inp6)) 1226 break; 1227 } 1228#endif 1229#if (__FreeBSD_version >= 300000) 1230 ifa = TAILQ_NEXT(ifa, ifa_link); 1231#else 1232 ifa = ifa->ifa_next; 1233#endif /* __FreeBSD_version >= 300000 */ 1234 if (ifa != NULL) 1235 sock = ifa->ifa_addr; 1236 } 1237 1238 if (ifa == NULL || sin == NULL) 1239 return -1; 1240 1241 mask = ifa->ifa_netmask; 1242 if (atype == FRI_BROADCAST) 1243 sock = ifa->ifa_broadaddr; 1244 else if (atype == FRI_PEERADDR) 1245 sock = ifa->ifa_dstaddr; 1246 1247 if (sock == NULL) 1248 return -1; 1249 1250#ifdef USE_INET6 1251 if (v == 6) { 1252 return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, 1253 (struct sockaddr_in6 *)mask, 1254 inp, inpmask); 1255 } 1256#endif 1257 return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock, 1258 (struct sockaddr_in *)mask, inp, inpmask); 1259} 1260 1261 1262u_32_t fr_newisn(fin) 1263fr_info_t *fin; 1264{ 1265 u_32_t newiss; 1266#if (__FreeBSD_version >= 400000) 1267 newiss = arc4random(); 1268#else 1269 static iss_seq_off = 0; 1270 u_char hash[16]; 1271 MD5_CTX ctx; 1272 1273 /* 1274 * Compute the base value of the ISS. It is a hash 1275 * of (saddr, sport, daddr, dport, secret). 1276 */ 1277 MD5Init(&ctx); 1278 1279 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 1280 sizeof(fin->fin_fi.fi_src)); 1281 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 1282 sizeof(fin->fin_fi.fi_dst)); 1283 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 1284 1285 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); 1286 1287 MD5Final(hash, &ctx); 1288 1289 memcpy(&newiss, hash, sizeof(newiss)); 1290 1291 /* 1292 * Now increment our "timer", and add it in to 1293 * the computed value. 1294 * 1295 * XXX Use `addin'? 1296 * XXX TCP_ISSINCR too large to use? 1297 */ 1298 iss_seq_off += 0x00010000; 1299 newiss += iss_seq_off; 1300#endif 1301 return newiss; 1302} 1303 1304 1305/* ------------------------------------------------------------------------ */ 1306/* Function: fr_nextipid */ 1307/* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 1308/* Parameters: fin(I) - pointer to packet information */ 1309/* */ 1310/* Returns the next IPv4 ID to use for this packet. */ 1311/* ------------------------------------------------------------------------ */ 1312u_short fr_nextipid(fin) 1313fr_info_t *fin; 1314{ 1315#ifndef RANDOM_IP_ID 1316 static u_short ipid = 0; 1317 u_short id; 1318 1319 MUTEX_ENTER(&ipf_rw); 1320 id = ipid++; 1321 MUTEX_EXIT(&ipf_rw); 1322#else 1323 u_short id; 1324 1325 id = ip_randomid(); 1326#endif 1327 1328 return id; 1329} 1330 1331 1332INLINE void fr_checkv4sum(fin) 1333fr_info_t *fin; 1334{ 1335#ifdef CSUM_DATA_VALID 1336 int manual = 0; 1337 u_short sum; 1338 ip_t *ip; 1339 mb_t *m; 1340 1341 if ((fin->fin_flx & FI_NOCKSUM) != 0) 1342 return; 1343 1344 if (fin->fin_cksum != 0) 1345 return; 1346 1347 m = fin->fin_m; 1348 if (m == NULL) { 1349 manual = 1; 1350 goto skipauto; 1351 } 1352 ip = fin->fin_ip; 1353 1354 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 1355 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) 1356 sum = m->m_pkthdr.csum_data; 1357 else 1358 sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, 1359 htonl(m->m_pkthdr.csum_data + 1360 fin->fin_ip->ip_len + fin->fin_p)); 1361 sum ^= 0xffff; 1362 if (sum != 0) { 1363 fin->fin_flx |= FI_BAD; 1364 fin->fin_cksum = -1; 1365 } else { 1366 fin->fin_cksum = 1; 1367 } 1368 } else 1369 manual = 1; 1370skipauto: 1371# ifdef IPFILTER_CKSUM 1372 if (manual != 0) 1373 if (fr_checkl4sum(fin) == -1) 1374 fin->fin_flx |= FI_BAD; 1375# else 1376 ; 1377# endif 1378#else 1379# ifdef IPFILTER_CKSUM 1380 if (fr_checkl4sum(fin) == -1) 1381 fin->fin_flx |= FI_BAD; 1382# endif 1383#endif 1384} 1385 1386 1387#ifdef USE_INET6 1388INLINE void fr_checkv6sum(fin) 1389fr_info_t *fin; 1390{ 1391# ifdef IPFILTER_CKSUM 1392 if (fr_checkl4sum(fin) == -1) 1393 fin->fin_flx |= FI_BAD; 1394# endif 1395} 1396#endif /* USE_INET6 */ 1397 1398 1399size_t mbufchainlen(m0) 1400struct mbuf *m0; 1401{ 1402 size_t len; 1403 1404 if ((m0->m_flags & M_PKTHDR) != 0) { 1405 len = m0->m_pkthdr.len; 1406 } else { 1407 struct mbuf *m; 1408 1409 for (m = m0, len = 0; m != NULL; m = m->m_next) 1410 len += m->m_len; 1411 } 1412 return len; 1413} 1414 1415 1416/* ------------------------------------------------------------------------ */ 1417/* Function: fr_pullup */ 1418/* Returns: NULL == pullup failed, else pointer to protocol header */ 1419/* Parameters: m(I) - pointer to buffer where data packet starts */ 1420/* fin(I) - pointer to packet information */ 1421/* len(I) - number of bytes to pullup */ 1422/* */ 1423/* Attempt to move at least len bytes (from the start of the buffer) into a */ 1424/* single buffer for ease of access. Operating system native functions are */ 1425/* used to manage buffers - if necessary. If the entire packet ends up in */ 1426/* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */ 1427/* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ 1428/* and ONLY if the pullup succeeds. */ 1429/* */ 1430/* We assume that 'min' is a pointer to a buffer that is part of the chain */ 1431/* of buffers that starts at *fin->fin_mp. */ 1432/* ------------------------------------------------------------------------ */ 1433void *fr_pullup(min, fin, len) 1434mb_t *min; 1435fr_info_t *fin; 1436int len; 1437{ 1438 int out = fin->fin_out, dpoff, ipoff; 1439 mb_t *m = min; 1440 char *ip; 1441 1442 if (m == NULL) 1443 return NULL; 1444 1445 ip = (char *)fin->fin_ip; 1446 if ((fin->fin_flx & FI_COALESCE) != 0) 1447 return ip; 1448 1449 ipoff = fin->fin_ipoff; 1450 if (fin->fin_dp != NULL) 1451 dpoff = (char *)fin->fin_dp - (char *)ip; 1452 else 1453 dpoff = 0; 1454 1455 if (M_LEN(m) < len) { 1456#ifdef MHLEN 1457 /* 1458 * Assume that M_PKTHDR is set and just work with what is left 1459 * rather than check.. 1460 * Should not make any real difference, anyway. 1461 */ 1462 if (len > MHLEN) 1463#else 1464 if (len > MLEN) 1465#endif 1466 { 1467#ifdef HAVE_M_PULLDOWN 1468 if (m_pulldown(m, 0, len, NULL) == NULL) 1469 m = NULL; 1470#else 1471 FREE_MB_T(*fin->fin_mp); 1472 m = NULL; 1473#endif 1474 } else 1475 { 1476 m = m_pullup(m, len); 1477 } 1478 *fin->fin_mp = m; 1479 if (m == NULL) { 1480 fin->fin_m = NULL; 1481 ATOMIC_INCL(frstats[out].fr_pull[1]); 1482 return NULL; 1483 } 1484 1485 while (M_LEN(m) == 0) { 1486 m = m->m_next; 1487 } 1488 fin->fin_m = m; 1489 ip = MTOD(m, char *) + ipoff; 1490 } 1491 1492 ATOMIC_INCL(frstats[out].fr_pull[0]); 1493 fin->fin_ip = (ip_t *)ip; 1494 if (fin->fin_dp != NULL) 1495 fin->fin_dp = (char *)fin->fin_ip + dpoff; 1496 1497 if (len == fin->fin_plen) 1498 fin->fin_flx |= FI_COALESCE; 1499 return ip; 1500} 1501 1502 1503int ipf_inject(fin, m) 1504fr_info_t *fin; 1505mb_t *m; 1506{ 1507 int error = 0; 1508 1509 if (fin->fin_out == 0) { 1510#if (__FreeBSD_version >= 501000) 1511 netisr_dispatch(NETISR_IP, m); 1512#else 1513 struct ifqueue *ifq; 1514 1515 ifq = &ipintrq; 1516 1517# ifdef _IF_QFULL 1518 if (_IF_QFULL(ifq)) 1519# else 1520 if (IF_QFULL(ifq)) 1521# endif 1522 { 1523# ifdef _IF_DROP 1524 _IF_DROP(ifq); 1525# else 1526 IF_DROP(ifq); 1527# endif 1528 FREE_MB_T(m); 1529 error = ENOBUFS; 1530 } else { 1531 IF_ENQUEUE(ifq, m); 1532 } 1533#endif 1534 } else { 1535 fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len); 1536 fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off); 1537#if (__FreeBSD_version >= 470102) 1538 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); 1539#else 1540 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); 1541#endif 1542 } 1543 1544 return error; 1545} 1546 1547int ipf_pfil_unhook(void) { 1548#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) 1549# if __FreeBSD_version >= 501108 1550 struct pfil_head *ph_inet; 1551# ifdef USE_INET6 1552 struct pfil_head *ph_inet6; 1553# endif 1554# endif 1555#endif 1556 1557#ifdef NETBSD_PF 1558# if (__FreeBSD_version >= 500011) 1559# if (__FreeBSD_version >= 501108) 1560 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 1561 if (ph_inet != NULL) 1562 pfil_remove_hook((void *)fr_check_wrapper, NULL, 1563 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); 1564# else 1565 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1566 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 1567# endif 1568# else 1569 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); 1570# endif 1571# ifdef USE_INET6 1572# if (__FreeBSD_version >= 501108) 1573 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 1574 if (ph_inet6 != NULL) 1575 pfil_remove_hook((void *)fr_check_wrapper6, NULL, 1576 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); 1577# else 1578 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1579 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); 1580# endif 1581# endif 1582#endif 1583 1584 return (0); 1585} 1586 1587int ipf_pfil_hook(void) { 1588#if defined(NETBSD_PF) && (__FreeBSD_version >= 500011) 1589# if __FreeBSD_version >= 501108 1590 struct pfil_head *ph_inet; 1591# ifdef USE_INET6 1592 struct pfil_head *ph_inet6; 1593# endif 1594# endif 1595#endif 1596 1597# ifdef NETBSD_PF 1598# if __FreeBSD_version >= 500011 1599# if __FreeBSD_version >= 501108 1600 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 1601# ifdef USE_INET6 1602 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 1603# endif 1604 if (ph_inet == NULL 1605# ifdef USE_INET6 1606 && ph_inet6 == NULL 1607# endif 1608 ) 1609 return ENODEV; 1610 1611 if (ph_inet != NULL) 1612 pfil_add_hook((void *)fr_check_wrapper, NULL, 1613 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet); 1614# else 1615 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1616 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 1617# endif 1618# else 1619 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK); 1620# endif 1621# ifdef USE_INET6 1622# if __FreeBSD_version >= 501108 1623 if (ph_inet6 != NULL) 1624 pfil_add_hook((void *)fr_check_wrapper6, NULL, 1625 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6); 1626# else 1627 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK, 1628 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); 1629# endif 1630# endif 1631# endif 1632 return (0); 1633} 1634 1635void 1636ipf_event_reg(void) 1637{ 1638#if (__FreeBSD_version >= 502103) 1639 ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ 1640 ipf_ifevent, NULL, \ 1641 EVENTHANDLER_PRI_ANY); 1642 ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ 1643 ipf_ifevent, NULL, \ 1644 EVENTHANDLER_PRI_ANY); 1645 ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ 1646 NULL, EVENTHANDLER_PRI_ANY); 1647#endif 1648} 1649 1650void 1651ipf_event_dereg(void) 1652{ 1653#if (__FreeBSD_version >= 502103) 1654 if (ipf_arrivetag != NULL) { 1655 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag); 1656 } 1657 if (ipf_departtag != NULL) { 1658 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag); 1659 } 1660 if (ipf_clonetag != NULL) { 1661 EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag); 1662 } 1663#endif 1664}
|