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