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