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