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