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