1 2 /* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 */ 7 #if !defined(lint) 8 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 9 static const char rcsid[] = "@(#)$Id$"; 10 #endif 11 12 #if defined(KERNEL) || defined(_KERNEL) 13 # undef KERNEL 14 # undef _KERNEL 15 # define KERNEL 1 16 # define _KERNEL 1 17 #endif 18 #if defined(__FreeBSD__) && \ 19 !defined(KLD_MODULE) && !defined(IPFILTER_LKM) 20 # include "opt_inet6.h" 21 #endif 22 #include <sys/param.h> 23 #include <sys/eventhandler.h> 24 #include <sys/conf.h> 25 #include <sys/errno.h> 26 #include <sys/types.h> 27 #include <sys/file.h> 28 #include <sys/fcntl.h> 29 #include <sys/filio.h> 30 #include <sys/time.h> 31 #include <sys/systm.h> 32 #include <sys/dirent.h> 33 #if defined(__FreeBSD__) 34 # include <sys/jail.h> 35 #endif 36 #include <sys/malloc.h> 37 #include <sys/mbuf.h> 38 #include <sys/sockopt.h> 39 #include <sys/socket.h> 40 #include <sys/selinfo.h> 41 #include <net/if.h> 42 #include <net/if_var.h> 43 #include <net/netisr.h> 44 #include <net/route.h> 45 #include <net/route/nhop.h> 46 #include <netinet/in.h> 47 #include <netinet/in_fib.h> 48 #include <netinet/in_pcb.h> 49 #include <netinet/in_var.h> 50 #include <netinet/in_systm.h> 51 #include <netinet/ip.h> 52 #include <netinet/ip_var.h> 53 #include <netinet/tcp.h> 54 #include <netinet/tcp_var.h> 55 #include <net/vnet.h> 56 #include <netinet/udp.h> 57 #include <netinet/tcpip.h> 58 #include <netinet/ip_icmp.h> 59 #include "netinet/ip_compat.h" 60 #ifdef USE_INET6 61 # include <netinet/icmp6.h> 62 #endif 63 #include "netinet/ip_fil.h" 64 #include "netinet/ip_nat.h" 65 #include "netinet/ip_frag.h" 66 #include "netinet/ip_state.h" 67 #include "netinet/ip_proxy.h" 68 #include "netinet/ip_auth.h" 69 #include "netinet/ip_sync.h" 70 #include "netinet/ip_lookup.h" 71 #include "netinet/ip_dstlist.h" 72 #ifdef IPFILTER_SCAN 73 # include "netinet/ip_scan.h" 74 #endif 75 #include "netinet/ip_pool.h" 76 #include <sys/malloc.h> 77 #include <sys/kernel.h> 78 #ifdef CSUM_DATA_VALID 79 # include <machine/in_cksum.h> 80 #endif 81 extern int ip_optcopy(struct ip *, struct ip *); 82 83 #ifdef IPFILTER_M_IPFILTER 84 MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures"); 85 #endif 86 87 88 static int ipf_send_ip(fr_info_t *, mb_t *); 89 static void ipf_timer_func(void *arg); 90 91 VNET_DEFINE(ipf_main_softc_t, ipfmain) = { 92 .ipf_running = -2, 93 }; 94 #define V_ipfmain VNET(ipfmain) 95 96 #include <sys/conf.h> 97 #include <net/pfil.h> 98 99 VNET_DEFINE_STATIC(eventhandler_tag, ipf_arrivetag); 100 VNET_DEFINE_STATIC(eventhandler_tag, ipf_departtag); 101 #define V_ipf_arrivetag VNET(ipf_arrivetag) 102 #define V_ipf_departtag VNET(ipf_departtag) 103 #if 0 104 /* 105 * Disable the "cloner" event handler; we are getting interface 106 * events before the firewall is fully initiallized and also no vnet 107 * information thus leading to uninitialised memory accesses. 108 * In addition it is unclear why we need it in first place. 109 * If it turns out to be needed, well need a dedicated event handler 110 * for it to deal with the ifc and the correct vnet. 111 */ 112 VNET_DEFINE_STATIC(eventhandler_tag, ipf_clonetag); 113 #define V_ipf_clonetag VNET(ipf_clonetag) 114 #endif 115 116 static void ipf_ifevent(void *arg, struct ifnet *ifp); 117 118 static void ipf_ifevent(void *arg, struct ifnet *ifp) 119 { 120 121 CURVNET_SET(ifp->if_vnet); 122 if (V_ipfmain.ipf_running > 0) 123 ipf_sync(&V_ipfmain, NULL); 124 CURVNET_RESTORE(); 125 } 126 127 128 129 static pfil_return_t 130 ipf_check_wrapper(struct mbuf **mp, struct ifnet *ifp, int flags, 131 void *ruleset __unused, struct inpcb *inp) 132 { 133 struct ip *ip = mtod(*mp, struct ip *); 134 pfil_return_t rv; 135 136 CURVNET_SET(ifp->if_vnet); 137 rv = ipf_check(&V_ipfmain, ip, ip->ip_hl << 2, ifp, 138 !!(flags & PFIL_OUT), mp); 139 CURVNET_RESTORE(); 140 return (rv == 0 ? PFIL_PASS : PFIL_DROPPED); 141 } 142 143 #ifdef USE_INET6 144 static pfil_return_t 145 ipf_check_wrapper6(struct mbuf **mp, struct ifnet *ifp, int flags, 146 void *ruleset __unused, struct inpcb *inp) 147 { 148 pfil_return_t rv; 149 150 CURVNET_SET(ifp->if_vnet); 151 rv = ipf_check(&V_ipfmain, mtod(*mp, struct ip *), 152 sizeof(struct ip6_hdr), ifp, !!(flags & PFIL_OUT), mp); 153 CURVNET_RESTORE(); 154 155 return (rv == 0 ? PFIL_PASS : PFIL_DROPPED); 156 } 157 # endif 158 #if defined(IPFILTER_LKM) 159 int ipf_identify(char *s) 160 { 161 if (strcmp(s, "ipl") == 0) 162 return (1); 163 return (0); 164 } 165 #endif /* IPFILTER_LKM */ 166 167 168 static void 169 ipf_timer_func(void *arg) 170 { 171 ipf_main_softc_t *softc = arg; 172 SPL_INT(s); 173 174 SPL_NET(s); 175 READ_ENTER(&softc->ipf_global); 176 177 if (softc->ipf_running > 0) 178 ipf_slowtimer(softc); 179 180 if (softc->ipf_running == -1 || softc->ipf_running == 1) { 181 #if 0 182 softc->ipf_slow_ch = timeout(ipf_timer_func, softc, hz/2); 183 #endif 184 callout_init(&softc->ipf_slow_ch, 1); 185 callout_reset(&softc->ipf_slow_ch, 186 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT, 187 ipf_timer_func, softc); 188 } 189 RWLOCK_EXIT(&softc->ipf_global); 190 SPL_X(s); 191 } 192 193 194 int 195 ipfattach(ipf_main_softc_t *softc) 196 { 197 #ifdef USE_SPL 198 int s; 199 #endif 200 201 SPL_NET(s); 202 if (softc->ipf_running > 0) { 203 SPL_X(s); 204 return (EBUSY); 205 } 206 207 if (ipf_init_all(softc) < 0) { 208 SPL_X(s); 209 return (EIO); 210 } 211 212 213 bzero((char *)V_ipfmain.ipf_selwait, sizeof(V_ipfmain.ipf_selwait)); 214 softc->ipf_running = 1; 215 216 if (softc->ipf_control_forwarding & 1) 217 V_ipforwarding = 1; 218 219 SPL_X(s); 220 #if 0 221 softc->ipf_slow_ch = timeout(ipf_timer_func, softc, 222 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 223 #endif 224 callout_init(&softc->ipf_slow_ch, 1); 225 callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT, 226 ipf_timer_func, softc); 227 return (0); 228 } 229 230 231 /* 232 * Disable the filter by removing the hooks from the IP input/output 233 * stream. 234 */ 235 int 236 ipfdetach(ipf_main_softc_t *softc) 237 { 238 #ifdef USE_SPL 239 int s; 240 #endif 241 242 if (softc->ipf_control_forwarding & 2) 243 V_ipforwarding = 0; 244 245 SPL_NET(s); 246 247 #if 0 248 if (softc->ipf_slow_ch.callout != NULL) 249 untimeout(ipf_timer_func, softc, softc->ipf_slow_ch); 250 bzero(&softc->ipf_slow, sizeof(softc->ipf_slow)); 251 #endif 252 callout_drain(&softc->ipf_slow_ch); 253 254 ipf_fini_all(softc); 255 256 softc->ipf_running = -2; 257 258 SPL_X(s); 259 260 return (0); 261 } 262 263 264 /* 265 * Filter ioctl interface. 266 */ 267 int 268 ipfioctl(struct cdev *dev, ioctlcmd_t cmd, caddr_t data, 269 int mode, struct thread *p) 270 #define p_cred td_ucred 271 #define p_uid td_ucred->cr_ruid 272 { 273 int error = 0, unit = 0; 274 SPL_INT(s); 275 276 CURVNET_SET(TD_TO_VNET(p)); 277 if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE)) 278 { 279 V_ipfmain.ipf_interror = 130001; 280 CURVNET_RESTORE(); 281 return (EPERM); 282 } 283 284 if (jailed_without_vnet(p->p_cred)) { 285 V_ipfmain.ipf_interror = 130018; 286 CURVNET_RESTORE(); 287 return (EOPNOTSUPP); 288 } 289 290 unit = GET_MINOR(dev); 291 if ((IPL_LOGMAX < unit) || (unit < 0)) { 292 V_ipfmain.ipf_interror = 130002; 293 CURVNET_RESTORE(); 294 return (ENXIO); 295 } 296 297 if (V_ipfmain.ipf_running <= 0) { 298 if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { 299 V_ipfmain.ipf_interror = 130003; 300 CURVNET_RESTORE(); 301 return (EIO); 302 } 303 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && 304 cmd != SIOCIPFSET && cmd != SIOCFRENB && 305 cmd != SIOCGETFS && cmd != SIOCGETFF && 306 cmd != SIOCIPFINTERROR) { 307 V_ipfmain.ipf_interror = 130004; 308 CURVNET_RESTORE(); 309 return (EIO); 310 } 311 } 312 313 SPL_NET(s); 314 315 error = ipf_ioctlswitch(&V_ipfmain, unit, data, cmd, mode, p->p_uid, p); 316 CURVNET_RESTORE(); 317 if (error != -1) { 318 SPL_X(s); 319 return (error); 320 } 321 322 SPL_X(s); 323 324 return (error); 325 } 326 327 328 /* 329 * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that 330 * requires a large amount of setting up and isn't any more efficient. 331 */ 332 int 333 ipf_send_reset(fr_info_t *fin) 334 { 335 struct tcphdr *tcp, *tcp2; 336 int tlen = 0, hlen; 337 struct mbuf *m; 338 #ifdef USE_INET6 339 ip6_t *ip6; 340 #endif 341 ip_t *ip; 342 343 tcp = fin->fin_dp; 344 if (tcp->th_flags & TH_RST) 345 return (-1); /* feedback loop */ 346 347 if (ipf_checkl4sum(fin) == -1) 348 return (-1); 349 350 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + 351 ((tcp->th_flags & TH_SYN) ? 1 : 0) + 352 ((tcp->th_flags & TH_FIN) ? 1 : 0); 353 354 #ifdef USE_INET6 355 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); 356 #else 357 hlen = sizeof(ip_t); 358 #endif 359 #ifdef MGETHDR 360 MGETHDR(m, M_NOWAIT, MT_HEADER); 361 #else 362 MGET(m, M_NOWAIT, MT_HEADER); 363 #endif 364 if (m == NULL) 365 return (-1); 366 if (sizeof(*tcp2) + hlen > MLEN) { 367 if (!(MCLGET(m, M_NOWAIT))) { 368 FREE_MB_T(m); 369 return (-1); 370 } 371 } 372 373 m->m_len = sizeof(*tcp2) + hlen; 374 m->m_data += max_linkhdr; 375 m->m_pkthdr.len = m->m_len; 376 m->m_pkthdr.rcvif = (struct ifnet *)0; 377 ip = mtod(m, struct ip *); 378 bzero((char *)ip, hlen); 379 #ifdef USE_INET6 380 ip6 = (ip6_t *)ip; 381 #endif 382 tcp2 = (struct tcphdr *)((char *)ip + hlen); 383 tcp2->th_sport = tcp->th_dport; 384 tcp2->th_dport = tcp->th_sport; 385 386 if (tcp->th_flags & TH_ACK) { 387 tcp2->th_seq = tcp->th_ack; 388 tcp2->th_flags = TH_RST; 389 tcp2->th_ack = 0; 390 } else { 391 tcp2->th_seq = 0; 392 tcp2->th_ack = ntohl(tcp->th_seq); 393 tcp2->th_ack += tlen; 394 tcp2->th_ack = htonl(tcp2->th_ack); 395 tcp2->th_flags = TH_RST|TH_ACK; 396 } 397 TCP_X2_A(tcp2, 0); 398 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); 399 tcp2->th_win = tcp->th_win; 400 tcp2->th_sum = 0; 401 tcp2->th_urp = 0; 402 403 #ifdef USE_INET6 404 if (fin->fin_v == 6) { 405 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 406 ip6->ip6_plen = htons(sizeof(struct tcphdr)); 407 ip6->ip6_nxt = IPPROTO_TCP; 408 ip6->ip6_hlim = 0; 409 ip6->ip6_src = fin->fin_dst6.in6; 410 ip6->ip6_dst = fin->fin_src6.in6; 411 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, 412 sizeof(*ip6), sizeof(*tcp2)); 413 return (ipf_send_ip(fin, m)); 414 } 415 #endif 416 ip->ip_p = IPPROTO_TCP; 417 ip->ip_len = htons(sizeof(struct tcphdr)); 418 ip->ip_src.s_addr = fin->fin_daddr; 419 ip->ip_dst.s_addr = fin->fin_saddr; 420 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); 421 ip->ip_len = htons(hlen + sizeof(*tcp2)); 422 return (ipf_send_ip(fin, m)); 423 } 424 425 426 /* 427 * ip_len must be in network byte order when called. 428 */ 429 static int 430 ipf_send_ip(fr_info_t *fin, mb_t *m) 431 { 432 fr_info_t fnew; 433 ip_t *ip, *oip; 434 int hlen; 435 436 ip = mtod(m, ip_t *); 437 bzero((char *)&fnew, sizeof(fnew)); 438 fnew.fin_main_soft = fin->fin_main_soft; 439 440 IP_V_A(ip, fin->fin_v); 441 switch (fin->fin_v) 442 { 443 case 4 : 444 oip = fin->fin_ip; 445 hlen = sizeof(*oip); 446 fnew.fin_v = 4; 447 fnew.fin_p = ip->ip_p; 448 fnew.fin_plen = ntohs(ip->ip_len); 449 IP_HL_A(ip, sizeof(*oip) >> 2); 450 ip->ip_tos = oip->ip_tos; 451 ip->ip_id = fin->fin_ip->ip_id; 452 ip->ip_off = htons(V_path_mtu_discovery ? IP_DF : 0); 453 ip->ip_ttl = V_ip_defttl; 454 ip->ip_sum = 0; 455 break; 456 #ifdef USE_INET6 457 case 6 : 458 { 459 ip6_t *ip6 = (ip6_t *)ip; 460 461 ip6->ip6_vfc = 0x60; 462 ip6->ip6_hlim = IPDEFTTL; 463 464 hlen = sizeof(*ip6); 465 fnew.fin_p = ip6->ip6_nxt; 466 fnew.fin_v = 6; 467 fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; 468 break; 469 } 470 #endif 471 default : 472 return (EINVAL); 473 } 474 #ifdef IPSEC_SUPPORT 475 m->m_pkthdr.rcvif = NULL; 476 #endif 477 478 fnew.fin_ifp = fin->fin_ifp; 479 fnew.fin_flx = FI_NOCKSUM; 480 fnew.fin_m = m; 481 fnew.fin_ip = ip; 482 fnew.fin_mp = &m; 483 fnew.fin_hlen = hlen; 484 fnew.fin_dp = (char *)ip + hlen; 485 (void) ipf_makefrip(hlen, ip, &fnew); 486 487 return (ipf_fastroute(m, &m, &fnew, NULL)); 488 } 489 490 491 int 492 ipf_send_icmp_err(int type, fr_info_t *fin, int dst) 493 { 494 int err, hlen, xtra, iclen, ohlen, avail, code; 495 struct in_addr dst4; 496 struct icmp *icmp; 497 struct mbuf *m; 498 i6addr_t dst6; 499 void *ifp; 500 #ifdef USE_INET6 501 ip6_t *ip6; 502 #endif 503 ip_t *ip, *ip2; 504 505 if ((type < 0) || (type >= ICMP_MAXTYPE)) 506 return (-1); 507 508 code = fin->fin_icode; 509 #ifdef USE_INET6 510 /* See NetBSD ip_fil_netbsd.c r1.4: */ 511 if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int))) 512 return (-1); 513 #endif 514 515 if (ipf_checkl4sum(fin) == -1) 516 return (-1); 517 #ifdef MGETHDR 518 MGETHDR(m, M_NOWAIT, MT_HEADER); 519 #else 520 MGET(m, M_NOWAIT, MT_HEADER); 521 #endif 522 if (m == NULL) 523 return (-1); 524 avail = MHLEN; 525 526 xtra = 0; 527 hlen = 0; 528 ohlen = 0; 529 dst4.s_addr = 0; 530 ifp = fin->fin_ifp; 531 if (fin->fin_v == 4) { 532 if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) 533 switch (ntohs(fin->fin_data[0]) >> 8) 534 { 535 case ICMP_ECHO : 536 case ICMP_TSTAMP : 537 case ICMP_IREQ : 538 case ICMP_MASKREQ : 539 break; 540 default : 541 FREE_MB_T(m); 542 return (0); 543 } 544 545 if (dst == 0) { 546 if (ipf_ifpaddr(&V_ipfmain, 4, FRI_NORMAL, ifp, 547 &dst6, NULL) == -1) { 548 FREE_MB_T(m); 549 return (-1); 550 } 551 dst4 = dst6.in4; 552 } else 553 dst4.s_addr = fin->fin_daddr; 554 555 hlen = sizeof(ip_t); 556 ohlen = fin->fin_hlen; 557 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 558 if (fin->fin_hlen < fin->fin_plen) 559 xtra = MIN(fin->fin_dlen, 8); 560 else 561 xtra = 0; 562 } 563 564 #ifdef USE_INET6 565 else if (fin->fin_v == 6) { 566 hlen = sizeof(ip6_t); 567 ohlen = sizeof(ip6_t); 568 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 569 type = icmptoicmp6types[type]; 570 if (type == ICMP6_DST_UNREACH) 571 code = icmptoicmp6unreach[code]; 572 573 if (iclen + max_linkhdr + fin->fin_plen > avail) { 574 if (!(MCLGET(m, M_NOWAIT))) { 575 FREE_MB_T(m); 576 return (-1); 577 } 578 avail = MCLBYTES; 579 } 580 xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); 581 xtra = MIN(xtra, IPV6_MMTU - iclen); 582 if (dst == 0) { 583 if (ipf_ifpaddr(&V_ipfmain, 6, FRI_NORMAL, ifp, 584 &dst6, NULL) == -1) { 585 FREE_MB_T(m); 586 return (-1); 587 } 588 } else 589 dst6 = fin->fin_dst6; 590 } 591 #endif 592 else { 593 FREE_MB_T(m); 594 return (-1); 595 } 596 597 avail -= (max_linkhdr + iclen); 598 if (avail < 0) { 599 FREE_MB_T(m); 600 return (-1); 601 } 602 if (xtra > avail) 603 xtra = avail; 604 iclen += xtra; 605 m->m_data += max_linkhdr; 606 m->m_pkthdr.rcvif = (struct ifnet *)0; 607 m->m_pkthdr.len = iclen; 608 m->m_len = iclen; 609 ip = mtod(m, ip_t *); 610 icmp = (struct icmp *)((char *)ip + hlen); 611 ip2 = (ip_t *)&icmp->icmp_ip; 612 613 icmp->icmp_type = type; 614 icmp->icmp_code = fin->fin_icode; 615 icmp->icmp_cksum = 0; 616 #ifdef icmp_nextmtu 617 if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { 618 if (fin->fin_mtu != 0) { 619 icmp->icmp_nextmtu = htons(fin->fin_mtu); 620 621 } else if (ifp != NULL) { 622 icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); 623 624 } else { /* make up a number... */ 625 icmp->icmp_nextmtu = htons(fin->fin_plen - 20); 626 } 627 } 628 #endif 629 630 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); 631 632 #ifdef USE_INET6 633 ip6 = (ip6_t *)ip; 634 if (fin->fin_v == 6) { 635 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 636 ip6->ip6_plen = htons(iclen - hlen); 637 ip6->ip6_nxt = IPPROTO_ICMPV6; 638 ip6->ip6_hlim = 0; 639 ip6->ip6_src = dst6.in6; 640 ip6->ip6_dst = fin->fin_src6.in6; 641 if (xtra > 0) 642 bcopy((char *)fin->fin_ip + ohlen, 643 (char *)&icmp->icmp_ip + ohlen, xtra); 644 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, 645 sizeof(*ip6), iclen - hlen); 646 } else 647 #endif 648 { 649 ip->ip_p = IPPROTO_ICMP; 650 ip->ip_src.s_addr = dst4.s_addr; 651 ip->ip_dst.s_addr = fin->fin_saddr; 652 653 if (xtra > 0) 654 bcopy((char *)fin->fin_ip + ohlen, 655 (char *)&icmp->icmp_ip + ohlen, xtra); 656 icmp->icmp_cksum = ipf_cksum((u_short *)icmp, 657 sizeof(*icmp) + 8); 658 ip->ip_len = htons(iclen); 659 ip->ip_p = IPPROTO_ICMP; 660 } 661 err = ipf_send_ip(fin, m); 662 return (err); 663 } 664 665 666 667 668 /* 669 * m0 - pointer to mbuf where the IP packet starts 670 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain 671 */ 672 int 673 ipf_fastroute(mb_t *m0, mb_t **mpp, fr_info_t *fin, frdest_t *fdp) 674 { 675 register struct ip *ip, *mhip; 676 register struct mbuf *m = *mpp; 677 int len, off, error = 0, hlen, code; 678 struct ifnet *ifp, *sifp; 679 struct route ro; 680 struct sockaddr_in *dst; 681 const struct sockaddr *gw; 682 struct nhop_object *nh; 683 u_long fibnum = 0; 684 u_short ip_off; 685 frdest_t node; 686 frentry_t *fr; 687 688 #ifdef M_WRITABLE 689 /* 690 * HOT FIX/KLUDGE: 691 * 692 * If the mbuf we're about to send is not writable (because of 693 * a cluster reference, for example) we'll need to make a copy 694 * of it since this routine modifies the contents. 695 * 696 * If you have non-crappy network hardware that can transmit data 697 * from the mbuf, rather than making a copy, this is gonna be a 698 * problem. 699 */ 700 if (M_WRITABLE(m) == 0) { 701 m0 = m_dup(m, M_NOWAIT); 702 if (m0 != NULL) { 703 FREE_MB_T(m); 704 m = m0; 705 *mpp = m; 706 } else { 707 error = ENOBUFS; 708 FREE_MB_T(m); 709 goto done; 710 } 711 } 712 #endif 713 714 #ifdef USE_INET6 715 if (fin->fin_v == 6) { 716 /* 717 * currently "to <if>" and "to <if>:ip#" are not supported 718 * for IPv6 719 */ 720 return (ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL)); 721 } 722 #endif 723 724 hlen = fin->fin_hlen; 725 ip = mtod(m0, struct ip *); 726 ifp = NULL; 727 728 /* 729 * Route packet. 730 */ 731 bzero(&ro, sizeof (ro)); 732 dst = (struct sockaddr_in *)&ro.ro_dst; 733 dst->sin_family = AF_INET; 734 dst->sin_addr = ip->ip_dst; 735 dst->sin_len = sizeof(dst); 736 gw = (const struct sockaddr *)dst; 737 738 fr = fin->fin_fr; 739 if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && 740 (fdp->fd_type == FRD_DSTLIST)) { 741 if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) 742 fdp = &node; 743 } 744 745 if (fdp != NULL) 746 ifp = fdp->fd_ptr; 747 else 748 ifp = fin->fin_ifp; 749 750 if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { 751 error = -2; 752 goto bad; 753 } 754 755 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 756 dst->sin_addr = fdp->fd_ip; 757 758 fibnum = M_GETFIB(m0); 759 NET_EPOCH_ASSERT(); 760 nh = fib4_lookup(fibnum, dst->sin_addr, 0, NHR_NONE, 0); 761 if (nh == NULL) { 762 if (in_localaddr(ip->ip_dst)) 763 error = EHOSTUNREACH; 764 else 765 error = ENETUNREACH; 766 goto bad; 767 } 768 769 if (ifp == NULL) 770 ifp = nh->nh_ifp; 771 if (nh->nh_flags & NHF_GATEWAY) { 772 gw = &nh->gw_sa; 773 ro.ro_flags |= RT_HAS_GW; 774 } 775 776 /* 777 * For input packets which are being "fastrouted", they won't 778 * go back through output filtering and miss their chance to get 779 * NAT'd and counted. Duplicated packets aren't considered to be 780 * part of the normal packet stream, so do not NAT them or pass 781 * them through stateful checking, etc. 782 */ 783 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { 784 sifp = fin->fin_ifp; 785 fin->fin_ifp = ifp; 786 fin->fin_out = 1; 787 (void) ipf_acctpkt(fin, NULL); 788 fin->fin_fr = NULL; 789 if (!fr || !(fr->fr_flags & FR_RETMASK)) { 790 u_32_t pass; 791 792 (void) ipf_state_check(fin, &pass); 793 } 794 795 switch (ipf_nat_checkout(fin, NULL)) 796 { 797 case 0 : 798 break; 799 case 1 : 800 ip->ip_sum = 0; 801 break; 802 case -1 : 803 error = -1; 804 goto bad; 805 break; 806 } 807 808 fin->fin_ifp = sifp; 809 fin->fin_out = 0; 810 } else 811 ip->ip_sum = 0; 812 /* 813 * If small enough for interface, can just send directly. 814 */ 815 if (ntohs(ip->ip_len) <= ifp->if_mtu) { 816 if (!ip->ip_sum) 817 ip->ip_sum = in_cksum(m, hlen); 818 error = (*ifp->if_output)(ifp, m, gw, &ro); 819 goto done; 820 } 821 /* 822 * Too large for interface; fragment if possible. 823 * Must be able to put at least 8 bytes per fragment. 824 */ 825 ip_off = ntohs(ip->ip_off); 826 if (ip_off & IP_DF) { 827 error = EMSGSIZE; 828 goto bad; 829 } 830 len = (ifp->if_mtu - hlen) &~ 7; 831 if (len < 8) { 832 error = EMSGSIZE; 833 goto bad; 834 } 835 836 { 837 int mhlen, firstlen = len; 838 struct mbuf **mnext = &m->m_act; 839 840 /* 841 * Loop through length of segment after first fragment, 842 * make new header and copy data of each part and link onto chain. 843 */ 844 m0 = m; 845 mhlen = sizeof (struct ip); 846 for (off = hlen + len; off < ntohs(ip->ip_len); off += len) { 847 #ifdef MGETHDR 848 MGETHDR(m, M_NOWAIT, MT_HEADER); 849 #else 850 MGET(m, M_NOWAIT, MT_HEADER); 851 #endif 852 if (m == NULL) { 853 m = m0; 854 error = ENOBUFS; 855 goto bad; 856 } 857 m->m_data += max_linkhdr; 858 mhip = mtod(m, struct ip *); 859 bcopy((char *)ip, (char *)mhip, sizeof(*ip)); 860 if (hlen > sizeof (struct ip)) { 861 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 862 IP_HL_A(mhip, mhlen >> 2); 863 } 864 m->m_len = mhlen; 865 mhip->ip_off = ((off - hlen) >> 3) + ip_off; 866 if (off + len >= ntohs(ip->ip_len)) 867 len = ntohs(ip->ip_len) - off; 868 else 869 mhip->ip_off |= IP_MF; 870 mhip->ip_len = htons((u_short)(len + mhlen)); 871 *mnext = m; 872 m->m_next = m_copym(m0, off, len, M_NOWAIT); 873 if (m->m_next == 0) { 874 error = ENOBUFS; /* ??? */ 875 goto sendorfree; 876 } 877 m->m_pkthdr.len = mhlen + len; 878 m->m_pkthdr.rcvif = NULL; 879 mhip->ip_off = htons((u_short)mhip->ip_off); 880 mhip->ip_sum = 0; 881 mhip->ip_sum = in_cksum(m, mhlen); 882 mnext = &m->m_act; 883 } 884 /* 885 * Update first fragment by trimming what's been copied out 886 * and updating header, then send each fragment (in order). 887 */ 888 m_adj(m0, hlen + firstlen - ip->ip_len); 889 ip->ip_len = htons((u_short)(hlen + firstlen)); 890 ip->ip_off = htons((u_short)IP_MF); 891 ip->ip_sum = 0; 892 ip->ip_sum = in_cksum(m0, hlen); 893 sendorfree: 894 for (m = m0; m; m = m0) { 895 m0 = m->m_act; 896 m->m_act = 0; 897 if (error == 0) 898 error = (*ifp->if_output)(ifp, m, gw, &ro); 899 else 900 FREE_MB_T(m); 901 } 902 } 903 done: 904 if (!error) 905 V_ipfmain.ipf_frouteok[0]++; 906 else 907 V_ipfmain.ipf_frouteok[1]++; 908 909 return (0); 910 bad: 911 if (error == EMSGSIZE) { 912 sifp = fin->fin_ifp; 913 code = fin->fin_icode; 914 fin->fin_icode = ICMP_UNREACH_NEEDFRAG; 915 fin->fin_ifp = ifp; 916 (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); 917 fin->fin_ifp = sifp; 918 fin->fin_icode = code; 919 } 920 FREE_MB_T(m); 921 goto done; 922 } 923 924 925 int 926 ipf_verifysrc(fr_info_t *fin) 927 { 928 struct nhop_object *nh; 929 930 NET_EPOCH_ASSERT(); 931 nh = fib4_lookup(RT_DEFAULT_FIB, fin->fin_src, 0, NHR_NONE, 0); 932 if (nh == NULL) 933 return (0); 934 return (fin->fin_ifp == nh->nh_ifp); 935 } 936 937 938 /* 939 * return the first IP Address associated with an interface 940 */ 941 int 942 ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr, 943 i6addr_t *inp, i6addr_t *inpmask) 944 { 945 #ifdef USE_INET6 946 struct in6_addr *ia6 = NULL; 947 #endif 948 struct sockaddr *sock, *mask; 949 struct sockaddr_in *sin; 950 struct ifaddr *ifa; 951 struct ifnet *ifp; 952 953 if ((ifptr == NULL) || (ifptr == (void *)-1)) 954 return (-1); 955 956 sin = NULL; 957 ifp = ifptr; 958 959 if (v == 4) 960 inp->in4.s_addr = 0; 961 #ifdef USE_INET6 962 else if (v == 6) 963 bzero((char *)inp, sizeof(*inp)); 964 #endif 965 ifa = CK_STAILQ_FIRST(&ifp->if_addrhead); 966 967 sock = ifa->ifa_addr; 968 while (sock != NULL && ifa != NULL) { 969 sin = (struct sockaddr_in *)sock; 970 if ((v == 4) && (sin->sin_family == AF_INET)) 971 break; 972 #ifdef USE_INET6 973 if ((v == 6) && (sin->sin_family == AF_INET6)) { 974 ia6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 975 if (!IN6_IS_ADDR_LINKLOCAL(ia6) && 976 !IN6_IS_ADDR_LOOPBACK(ia6)) 977 break; 978 } 979 #endif 980 ifa = CK_STAILQ_NEXT(ifa, ifa_link); 981 if (ifa != NULL) 982 sock = ifa->ifa_addr; 983 } 984 985 if (ifa == NULL || sin == NULL) 986 return (-1); 987 988 mask = ifa->ifa_netmask; 989 if (atype == FRI_BROADCAST) 990 sock = ifa->ifa_broadaddr; 991 else if (atype == FRI_PEERADDR) 992 sock = ifa->ifa_dstaddr; 993 994 if (sock == NULL) 995 return (-1); 996 997 #ifdef USE_INET6 998 if (v == 6) { 999 return (ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, 1000 (struct sockaddr_in6 *)mask, 1001 inp, inpmask)); 1002 } 1003 #endif 1004 return (ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, 1005 (struct sockaddr_in *)mask, 1006 &inp->in4, &inpmask->in4)); 1007 } 1008 1009 1010 u_32_t 1011 ipf_newisn(fr_info_t *fin) 1012 { 1013 u_32_t newiss; 1014 newiss = arc4random(); 1015 return (newiss); 1016 } 1017 1018 1019 int 1020 ipf_checkv4sum(fr_info_t *fin) 1021 { 1022 #ifdef CSUM_DATA_VALID 1023 int manual = 0; 1024 u_short sum; 1025 ip_t *ip; 1026 mb_t *m; 1027 1028 if ((fin->fin_flx & FI_NOCKSUM) != 0) 1029 return (0); 1030 1031 if ((fin->fin_flx & FI_SHORT) != 0) 1032 return (1); 1033 1034 if (fin->fin_cksum != FI_CK_NEEDED) 1035 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1036 1037 m = fin->fin_m; 1038 if (m == NULL) { 1039 manual = 1; 1040 goto skipauto; 1041 } 1042 ip = fin->fin_ip; 1043 1044 if ((m->m_pkthdr.csum_flags & (CSUM_IP_CHECKED|CSUM_IP_VALID)) == 1045 CSUM_IP_CHECKED) { 1046 fin->fin_cksum = FI_CK_BAD; 1047 fin->fin_flx |= FI_BAD; 1048 DT2(ipf_fi_bad_checkv4sum_csum_ip_checked, fr_info_t *, fin, u_int, m->m_pkthdr.csum_flags & (CSUM_IP_CHECKED|CSUM_IP_VALID)); 1049 return (-1); 1050 } 1051 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { 1052 /* Depending on the driver, UDP may have zero checksum */ 1053 if (fin->fin_p == IPPROTO_UDP && (fin->fin_flx & 1054 (FI_FRAG|FI_SHORT|FI_BAD)) == 0) { 1055 udphdr_t *udp = fin->fin_dp; 1056 if (udp->uh_sum == 0) { 1057 /* 1058 * we're good no matter what the hardware 1059 * checksum flags and csum_data say (handling 1060 * of csum_data for zero UDP checksum is not 1061 * consistent across all drivers) 1062 */ 1063 fin->fin_cksum = 1; 1064 return (0); 1065 } 1066 } 1067 1068 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) 1069 sum = m->m_pkthdr.csum_data; 1070 else 1071 sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, 1072 htonl(m->m_pkthdr.csum_data + 1073 fin->fin_dlen + fin->fin_p)); 1074 sum ^= 0xffff; 1075 if (sum != 0) { 1076 fin->fin_cksum = FI_CK_BAD; 1077 fin->fin_flx |= FI_BAD; 1078 DT2(ipf_fi_bad_checkv4sum_sum, fr_info_t *, fin, u_int, sum); 1079 } else { 1080 fin->fin_cksum = FI_CK_SUMOK; 1081 return (0); 1082 } 1083 } else { 1084 if (m->m_pkthdr.csum_flags == CSUM_DELAY_DATA) { 1085 fin->fin_cksum = FI_CK_L4FULL; 1086 return (0); 1087 } else if (m->m_pkthdr.csum_flags == CSUM_TCP || 1088 m->m_pkthdr.csum_flags == CSUM_UDP || 1089 m->m_pkthdr.csum_flags == CSUM_IP) { 1090 fin->fin_cksum = FI_CK_L4PART; 1091 return (0); 1092 } else { 1093 manual = 1; 1094 } 1095 } 1096 skipauto: 1097 if (manual != 0) { 1098 if (ipf_checkl4sum(fin) == -1) { 1099 fin->fin_flx |= FI_BAD; 1100 DT2(ipf_fi_bad_checkv4sum_manual, fr_info_t *, fin, u_int, manual); 1101 return (-1); 1102 } 1103 } 1104 #else 1105 if (ipf_checkl4sum(fin) == -1) { 1106 fin->fin_flx |= FI_BAD; 1107 DT2(ipf_fi_bad_checkv4sum_checkl4sum, fr_info_t *, fin, u_int, -1); 1108 return (-1); 1109 } 1110 #endif 1111 return (0); 1112 } 1113 1114 1115 #ifdef USE_INET6 1116 int 1117 ipf_checkv6sum(fr_info_t *fin) 1118 { 1119 if ((fin->fin_flx & FI_NOCKSUM) != 0) { 1120 DT(ipf_checkv6sum_fi_nocksum); 1121 return (0); 1122 } 1123 1124 if ((fin->fin_flx & FI_SHORT) != 0) { 1125 DT(ipf_checkv6sum_fi_short); 1126 return (1); 1127 } 1128 1129 if (fin->fin_cksum != FI_CK_NEEDED) { 1130 DT(ipf_checkv6sum_fi_ck_needed); 1131 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1132 } 1133 1134 if (ipf_checkl4sum(fin) == -1) { 1135 fin->fin_flx |= FI_BAD; 1136 DT2(ipf_fi_bad_checkv6sum_checkl4sum, fr_info_t *, fin, u_int, -1); 1137 return (-1); 1138 } 1139 return (0); 1140 } 1141 #endif /* USE_INET6 */ 1142 1143 1144 size_t 1145 mbufchainlen(struct mbuf *m0) 1146 { 1147 size_t len; 1148 1149 if ((m0->m_flags & M_PKTHDR) != 0) { 1150 len = m0->m_pkthdr.len; 1151 } else { 1152 struct mbuf *m; 1153 1154 for (m = m0, len = 0; m != NULL; m = m->m_next) 1155 len += m->m_len; 1156 } 1157 return (len); 1158 } 1159 1160 1161 /* ------------------------------------------------------------------------ */ 1162 /* Function: ipf_pullup */ 1163 /* Returns: NULL == pullup failed, else pointer to protocol header */ 1164 /* Parameters: xmin(I)- pointer to buffer where data packet starts */ 1165 /* fin(I) - pointer to packet information */ 1166 /* len(I) - number of bytes to pullup */ 1167 /* */ 1168 /* Attempt to move at least len bytes (from the start of the buffer) into a */ 1169 /* single buffer for ease of access. Operating system native functions are */ 1170 /* used to manage buffers - if necessary. If the entire packet ends up in */ 1171 /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ 1172 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ 1173 /* and ONLY if the pullup succeeds. */ 1174 /* */ 1175 /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ 1176 /* of buffers that starts at *fin->fin_mp. */ 1177 /* ------------------------------------------------------------------------ */ 1178 ip_t * 1179 ipf_pullup(mb_t *xmin, fr_info_t *fin, int len) 1180 { 1181 int dpoff, ipoff; 1182 mb_t *m = xmin; 1183 ip_t *ip; 1184 1185 if (m == NULL) 1186 return (NULL); 1187 1188 ip = fin->fin_ip; 1189 if ((fin->fin_flx & FI_COALESCE) != 0) 1190 return (ip); 1191 1192 ipoff = fin->fin_ipoff; 1193 if (fin->fin_dp != NULL) 1194 dpoff = (char *)fin->fin_dp - (char *)ip; 1195 else 1196 dpoff = 0; 1197 1198 if (M_LEN(m) < len) { 1199 mb_t *n = *fin->fin_mp; 1200 /* 1201 * Assume that M_PKTHDR is set and just work with what is left 1202 * rather than check.. 1203 * Should not make any real difference, anyway. 1204 */ 1205 if (m != n) { 1206 /* 1207 * Record the mbuf that points to the mbuf that we're 1208 * about to go to work on so that we can update the 1209 * m_next appropriately later. 1210 */ 1211 for (; n->m_next != m; n = n->m_next) 1212 ; 1213 } else { 1214 n = NULL; 1215 } 1216 1217 #ifdef MHLEN 1218 if (len > MHLEN) 1219 #else 1220 if (len > MLEN) 1221 #endif 1222 { 1223 #ifdef HAVE_M_PULLDOWN 1224 if (m_pulldown(m, 0, len, NULL) == NULL) 1225 m = NULL; 1226 #else 1227 FREE_MB_T(*fin->fin_mp); 1228 m = NULL; 1229 n = NULL; 1230 #endif 1231 } else 1232 { 1233 1234 m = m_pullup(m, len); 1235 } 1236 if (n != NULL) 1237 n->m_next = m; 1238 if (m == NULL) { 1239 /* 1240 * When n is non-NULL, it indicates that m pointed to 1241 * a sub-chain (tail) of the mbuf and that the head 1242 * of this chain has not yet been free'd. 1243 */ 1244 if (n != NULL) { 1245 FREE_MB_T(*fin->fin_mp); 1246 } 1247 1248 *fin->fin_mp = NULL; 1249 fin->fin_m = NULL; 1250 return (NULL); 1251 } 1252 1253 if (n == NULL) 1254 *fin->fin_mp = m; 1255 1256 while (M_LEN(m) == 0) { 1257 m = m->m_next; 1258 } 1259 fin->fin_m = m; 1260 ip = MTOD(m, ip_t *) + ipoff; 1261 1262 fin->fin_ip = ip; 1263 if (fin->fin_dp != NULL) 1264 fin->fin_dp = (char *)fin->fin_ip + dpoff; 1265 if (fin->fin_fraghdr != NULL) 1266 fin->fin_fraghdr = (char *)ip + 1267 ((char *)fin->fin_fraghdr - 1268 (char *)fin->fin_ip); 1269 } 1270 1271 if (len == fin->fin_plen) 1272 fin->fin_flx |= FI_COALESCE; 1273 return (ip); 1274 } 1275 1276 1277 int 1278 ipf_inject(fr_info_t *fin, mb_t *m) 1279 { 1280 struct epoch_tracker et; 1281 int error = 0; 1282 1283 NET_EPOCH_ENTER(et); 1284 if (fin->fin_out == 0) { 1285 netisr_dispatch(NETISR_IP, m); 1286 } else { 1287 fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len); 1288 fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off); 1289 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL); 1290 } 1291 NET_EPOCH_EXIT(et); 1292 1293 return (error); 1294 } 1295 1296 VNET_DEFINE_STATIC(pfil_hook_t, ipf_inet_hook); 1297 VNET_DEFINE_STATIC(pfil_hook_t, ipf_inet6_hook); 1298 #define V_ipf_inet_hook VNET(ipf_inet_hook) 1299 #define V_ipf_inet6_hook VNET(ipf_inet6_hook) 1300 1301 int ipf_pfil_unhook(void) { 1302 1303 pfil_remove_hook(V_ipf_inet_hook); 1304 1305 #ifdef USE_INET6 1306 pfil_remove_hook(V_ipf_inet6_hook); 1307 #endif 1308 1309 return (0); 1310 } 1311 1312 int ipf_pfil_hook(void) { 1313 int error, error6; 1314 1315 struct pfil_hook_args pha = { 1316 .pa_version = PFIL_VERSION, 1317 .pa_flags = PFIL_IN | PFIL_OUT, 1318 .pa_modname = "ipfilter", 1319 .pa_rulname = "default-ip4", 1320 .pa_mbuf_chk = ipf_check_wrapper, 1321 .pa_type = PFIL_TYPE_IP4, 1322 }; 1323 V_ipf_inet_hook = pfil_add_hook(&pha); 1324 1325 #ifdef USE_INET6 1326 pha.pa_rulname = "default-ip6"; 1327 pha.pa_mbuf_chk = ipf_check_wrapper6; 1328 pha.pa_type = PFIL_TYPE_IP6; 1329 V_ipf_inet6_hook = pfil_add_hook(&pha); 1330 #endif 1331 1332 struct pfil_link_args pla = { 1333 .pa_version = PFIL_VERSION, 1334 .pa_flags = PFIL_IN | PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR, 1335 .pa_head = V_inet_pfil_head, 1336 .pa_hook = V_ipf_inet_hook, 1337 }; 1338 error = pfil_link(&pla); 1339 1340 error6 = 0; 1341 #ifdef USE_INET6 1342 pla.pa_head = V_inet6_pfil_head; 1343 pla.pa_hook = V_ipf_inet6_hook; 1344 error6 = pfil_link(&pla); 1345 #endif 1346 1347 if (error || error6) 1348 error = ENODEV; 1349 else 1350 error = 0; 1351 1352 return (error); 1353 } 1354 1355 void 1356 ipf_event_reg(void) 1357 { 1358 V_ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \ 1359 ipf_ifevent, NULL, \ 1360 EVENTHANDLER_PRI_ANY); 1361 V_ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \ 1362 ipf_ifevent, NULL, \ 1363 EVENTHANDLER_PRI_ANY); 1364 #if 0 1365 V_ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \ 1366 NULL, EVENTHANDLER_PRI_ANY); 1367 #endif 1368 } 1369 1370 void 1371 ipf_event_dereg(void) 1372 { 1373 if (V_ipf_arrivetag != NULL) { 1374 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, V_ipf_arrivetag); 1375 } 1376 if (V_ipf_departtag != NULL) { 1377 EVENTHANDLER_DEREGISTER(ifnet_departure_event, V_ipf_departtag); 1378 } 1379 #if 0 1380 if (V_ipf_clonetag != NULL) { 1381 EVENTHANDLER_DEREGISTER(if_clone_event, V_ipf_clonetag); 1382 } 1383 #endif 1384 } 1385 1386 1387 u_32_t 1388 ipf_random(void) 1389 { 1390 return (arc4random()); 1391 } 1392 1393 1394 u_int 1395 ipf_pcksum(fr_info_t *fin, int hlen, u_int sum) 1396 { 1397 struct mbuf *m; 1398 u_int sum2; 1399 int off; 1400 1401 m = fin->fin_m; 1402 off = (char *)fin->fin_dp - (char *)fin->fin_ip; 1403 m->m_data += hlen; 1404 m->m_len -= hlen; 1405 sum2 = in_cksum(fin->fin_m, fin->fin_plen - off); 1406 m->m_len += hlen; 1407 m->m_data -= hlen; 1408 1409 /* 1410 * Both sum and sum2 are partial sums, so combine them together. 1411 */ 1412 sum += ~sum2 & 0xffff; 1413 while (sum > 0xffff) 1414 sum = (sum & 0xffff) + (sum >> 16); 1415 sum2 = ~sum & 0xffff; 1416 return (sum2); 1417 } 1418 1419 #ifdef USE_INET6 1420 u_int 1421 ipf_pcksum6(struct mbuf *m, ip6_t *ip6, u_int32_t off, u_int32_t len) 1422 { 1423 #ifdef _KERNEL 1424 int sum; 1425 1426 if (m->m_len < sizeof(struct ip6_hdr)) { 1427 return (0xffff); 1428 } 1429 1430 sum = in6_cksum(m, ip6->ip6_nxt, off, len); 1431 return (sum); 1432 #else 1433 u_short *sp; 1434 u_int sum; 1435 1436 sp = (u_short *)&ip6->ip6_src; 1437 sum = *sp++; /* ip6_src */ 1438 sum += *sp++; 1439 sum += *sp++; 1440 sum += *sp++; 1441 sum += *sp++; 1442 sum += *sp++; 1443 sum += *sp++; 1444 sum += *sp++; 1445 sum += *sp++; /* ip6_dst */ 1446 sum += *sp++; 1447 sum += *sp++; 1448 sum += *sp++; 1449 sum += *sp++; 1450 sum += *sp++; 1451 sum += *sp++; 1452 sum += *sp++; 1453 return (ipf_pcksum(fin, off, sum)); 1454 #endif 1455 } 1456 #endif 1457 1458 void 1459 ipf_fbsd_kenv_get(ipf_main_softc_t *softc) 1460 { 1461 TUNABLE_INT_FETCH("net.inet.ipf.large_nat", 1462 &softc->ipf_large_nat); 1463 } 1464