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