1 /* $NetBSD: ip_fil_netbsd.c,v 1.5 2013/06/29 21:06:57 rmind Exp $ */ 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 #if defined(__NetBSD__) 10 #include <sys/cdefs.h> 11 __KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.5 2013/06/29 21:06:57 rmind Exp $"); 12 #else 13 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 14 static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 1.1.1.2 2012/07/22 13:45:17 darrenr Exp"; 15 #endif 16 #endif 17 18 #if defined(KERNEL) || defined(_KERNEL) 19 # undef KERNEL 20 # undef _KERNEL 21 # define KERNEL 1 22 # define _KERNEL 1 23 #endif 24 #include <sys/param.h> 25 #if (NetBSD >= 199905) && !defined(IPFILTER_LKM) 26 # include "opt_ipsec.h" 27 #endif 28 #include <sys/errno.h> 29 #include <sys/types.h> 30 #include <sys/file.h> 31 #include <sys/ioctl.h> 32 #include <sys/time.h> 33 #include <sys/systm.h> 34 #include <sys/select.h> 35 #if (NetBSD > 199609) 36 # include <sys/dirent.h> 37 #else 38 # include <sys/dir.h> 39 #endif 40 #if (__NetBSD_Version__ >= 599005900) 41 # include <sys/cprng.h> 42 #endif 43 #include <sys/mbuf.h> 44 #include <sys/protosw.h> 45 #include <sys/socket.h> 46 #include <sys/poll.h> 47 #if (__NetBSD_Version__ >= 399002000) 48 # include <sys/kauth.h> 49 #endif 50 51 #include <net/if.h> 52 #include <net/route.h> 53 #include <netinet/in.h> 54 #include <netinet/in_var.h> 55 #include <netinet/in_systm.h> 56 #include <netinet/ip.h> 57 #include <netinet/ip_var.h> 58 #include <netinet/tcp.h> 59 #if __NetBSD_Version__ >= 105190000 /* 1.5T */ 60 # include <netinet/tcp_timer.h> 61 # include <netinet/tcp_var.h> 62 #endif 63 #include <netinet/udp.h> 64 #include <netinet/tcpip.h> 65 #include <netinet/ip_icmp.h> 66 #include "netinet/ip_compat.h" 67 #ifdef USE_INET6 68 # include <netinet/icmp6.h> 69 # if (__NetBSD_Version__ >= 106000000) 70 # include <netinet6/nd6.h> 71 # endif 72 #endif 73 #include "netinet/ip_fil.h" 74 #include "netinet/ip_nat.h" 75 #include "netinet/ip_frag.h" 76 #include "netinet/ip_state.h" 77 #include "netinet/ip_proxy.h" 78 #include "netinet/ip_auth.h" 79 #include "netinet/ip_sync.h" 80 #include "netinet/ip_lookup.h" 81 #include "netinet/ip_dstlist.h" 82 #ifdef IPFILTER_SCAN 83 #include "netinet/ip_scan.h" 84 #endif 85 #include <sys/md5.h> 86 #include <sys/kernel.h> 87 #include <sys/conf.h> 88 #ifdef INET 89 extern int ip_optcopy (struct ip *, struct ip *); 90 #endif 91 92 #ifdef IPFILTER_M_IPFILTER 93 MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures"); 94 #endif 95 96 #if __NetBSD_Version__ >= 105009999 97 # define csuminfo csum_flags 98 #endif 99 100 #if __NetBSD_Version__ < 200000000 101 extern struct protosw inetsw[]; 102 #endif 103 104 #if (__NetBSD_Version__ >= 599002000) 105 static kauth_listener_t ipf_listener; 106 #endif 107 108 #if (__NetBSD_Version__ < 399001400) 109 extern int ip6_getpmtu (struct route_in6 *, struct route_in6 *, 110 struct ifnet *, struct in6_addr *, u_long *, 111 int *); 112 #endif 113 #if (NetBSD >= 199511) 114 static int ipfopen(dev_t dev, int flags, int devtype, PROC_T *p); 115 static int ipfclose(dev_t dev, int flags, int devtype, PROC_T *p); 116 #else 117 # if (__NetBSD_Version__ >= 399001400) 118 static int ipfopen(dev_t dev, int flags, struct lwp *); 119 static int ipfclose(dev_t dev, int flags, struct lwp *); 120 # else 121 static int ipfopen(dev_t dev, int flags); 122 static int ipfclose(dev_t dev, int flags); 123 # endif /* __NetBSD_Version__ >= 399001400 */ 124 #endif 125 static int ipfread(dev_t, struct uio *, int ioflag); 126 static int ipfwrite(dev_t, struct uio *, int ioflag); 127 static int ipfpoll(dev_t, int events, PROC_T *); 128 static void ipf_timer_func(void *ptr); 129 130 const struct cdevsw ipl_cdevsw = { 131 ipfopen, ipfclose, ipfread, ipfwrite, ipfioctl, 132 nostop, notty, ipfpoll, nommap, 133 #if (__NetBSD_Version__ >= 200000000) 134 nokqfilter, 135 #endif 136 #ifdef D_OTHER 137 D_OTHER, 138 #endif 139 }; 140 141 ipf_main_softc_t ipfmain; 142 143 static u_short ipid = 0; 144 static int (*ipf_savep)(void *, ip_t *, int, void *, int, struct mbuf **); 145 static int ipf_send_ip(fr_info_t *, mb_t *); 146 #ifdef USE_INET6 147 static int ipf_fastroute6(struct mbuf *, struct mbuf **, 148 fr_info_t *, frdest_t *); 149 #endif 150 151 #if defined(NETBSD_PF) 152 # include <net/pfil.h> 153 /* 154 * We provide the ipf_checkp name just to minimize changes later. 155 */ 156 int (*ipf_checkp)(void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp); 157 #endif /* NETBSD_PF */ 158 159 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) 160 # include <net/pfil.h> 161 162 static int ipf_check_wrapper(void *, struct mbuf **, struct ifnet *, int ); 163 164 static int 165 ipf_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 166 { 167 struct ip *ip; 168 int rv, hlen; 169 170 #if __NetBSD_Version__ >= 200080000 171 /* 172 * ensure that mbufs are writable beforehand 173 * as it's assumed by ipf code. 174 * XXX inefficient 175 */ 176 int error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT); 177 178 if (error) { 179 m_freem(*mp); 180 *mp = NULL; 181 return error; 182 } 183 #endif 184 ip = mtod(*mp, struct ip *); 185 hlen = ip->ip_hl << 2; 186 187 #ifdef INET 188 #if defined(M_CSUM_TCPv4) 189 /* 190 * If the packet is out-bound, we can't delay checksums 191 * here. For in-bound, the checksum has already been 192 * validated. 193 */ 194 if (dir == PFIL_OUT) { 195 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) { 196 in_delayed_cksum(*mp); 197 (*mp)->m_pkthdr.csum_flags &= 198 ~(M_CSUM_TCPv4|M_CSUM_UDPv4); 199 } 200 } 201 #endif /* M_CSUM_TCPv4 */ 202 #endif /* INET */ 203 204 /* 205 * Note, we don't need to update the checksum, because 206 * it has already been verified. 207 */ 208 rv = ipf_check(&ipfmain, ip, hlen, ifp, (dir == PFIL_OUT), mp); 209 210 return (rv); 211 } 212 213 # ifdef USE_INET6 214 # include <netinet/ip6.h> 215 216 static int ipf_check_wrapper6(void *, struct mbuf **, struct ifnet *, int ); 217 218 static int 219 ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 220 { 221 #if defined(INET6) 222 # if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000) 223 /* 224 * If the packet is out-bound, we can't delay checksums 225 * here. For in-bound, the checksum has already been 226 * validated. 227 */ 228 if (dir == PFIL_OUT) { 229 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) { 230 # if (__NetBSD_Version__ > 399000600) 231 in6_delayed_cksum(*mp); 232 # endif 233 (*mp)->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv6| 234 M_CSUM_UDPv6); 235 } 236 } 237 # endif 238 #endif /* INET6 */ 239 240 return (ipf_check(&ipfmain, mtod(*mp, struct ip *), sizeof(struct ip6_hdr), 241 ifp, (dir == PFIL_OUT), mp)); 242 } 243 # endif 244 245 246 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 247 static int ipf_pfilsync(void *, struct mbuf **, struct ifnet *, int); 248 249 static int 250 ipf_pfilsync(void *hdr, struct mbuf **mp, struct ifnet *ifp, int dir) 251 { 252 /* 253 * The interface pointer is useless for create (we have nothing to 254 * compare it to) and at detach, the interface name is still in the 255 * list of active NICs (albeit, down, but that's not any real 256 * indicator) and doing ifunit() on the name will still return the 257 * pointer, so it's not much use then, either. 258 */ 259 ipf_sync(&ipfmain, NULL); 260 return 0; 261 } 262 # endif 263 264 #endif /* __NetBSD_Version__ >= 105110000 */ 265 266 267 #if defined(IPFILTER_LKM) 268 int 269 ipf_identify(s) 270 char *s; 271 { 272 if (strcmp(s, "ipl") == 0) 273 return 1; 274 return 0; 275 } 276 #endif /* IPFILTER_LKM */ 277 278 #if (__NetBSD_Version__ >= 599002000) 279 static int 280 ipf_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 281 void *arg0, void *arg1, void *arg2, void *arg3) 282 { 283 int result; 284 enum kauth_network_req req; 285 286 result = KAUTH_RESULT_DEFER; 287 req = (enum kauth_network_req)arg0; 288 289 if (action != KAUTH_NETWORK_FIREWALL) 290 return result; 291 292 /* These must have came from device context. */ 293 if ((req == KAUTH_REQ_NETWORK_FIREWALL_FW) || 294 (req == KAUTH_REQ_NETWORK_FIREWALL_NAT)) 295 result = KAUTH_RESULT_ALLOW; 296 297 return result; 298 } 299 #endif 300 301 /* 302 * Try to detect the case when compiling for NetBSD with pseudo-device 303 */ 304 void 305 ipfilterattach(int count) 306 { 307 308 #if (__NetBSD_Version__ >= 599002000) 309 ipf_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 310 ipf_listener_cb, NULL); 311 #endif 312 313 if (ipf_load_all() == 0) 314 (void) ipf_create_all(&ipfmain); 315 } 316 317 318 int 319 ipfattach(ipf_main_softc_t *softc) 320 { 321 SPL_INT(s); 322 #if (__NetBSD_Version__ >= 499005500) 323 int i; 324 #endif 325 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) 326 int error = 0; 327 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000) 328 pfil_head_t *ph_inet; 329 # ifdef USE_INET6 330 pfil_head_t *ph_inet6; 331 # endif 332 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 333 pfil_head_t *ph_ifsync; 334 # endif 335 # endif 336 #endif 337 338 SPL_NET(s); 339 if ((softc->ipf_running > 0) || (ipf_checkp == ipf_check)) { 340 printf("IP Filter: already initialized\n"); 341 SPL_X(s); 342 IPFERROR(130017); 343 return EBUSY; 344 } 345 346 if (ipf_init_all(softc) < 0) { 347 SPL_X(s); 348 IPFERROR(130015); 349 return EIO; 350 } 351 352 #ifdef NETBSD_PF 353 # if (__NetBSD_Version__ >= 104200000) 354 # if __NetBSD_Version__ >= 105110000 355 ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET); 356 # ifdef USE_INET6 357 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6); 358 # endif 359 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 360 ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0); 361 # endif 362 363 if (ph_inet == NULL 364 # ifdef USE_INET6 365 && ph_inet6 == NULL 366 # endif 367 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 368 && ph_ifsync == NULL 369 # endif 370 ) { 371 SPL_X(s); 372 IPFERROR(130016); 373 return ENODEV; 374 } 375 376 if (ph_inet != NULL) 377 error = pfil_add_hook((void *)ipf_check_wrapper, NULL, 378 PFIL_IN|PFIL_OUT, ph_inet); 379 else 380 error = 0; 381 # else 382 error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 383 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 384 # endif 385 if (error) { 386 IPFERROR(130013); 387 goto pfil_error; 388 } 389 # else 390 pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT); 391 # endif 392 393 # ifdef USE_INET6 394 # if __NetBSD_Version__ >= 105110000 395 if (ph_inet6 != NULL) 396 error = pfil_add_hook((void *)ipf_check_wrapper6, NULL, 397 PFIL_IN|PFIL_OUT, ph_inet6); 398 else 399 error = 0; 400 if (error) { 401 pfil_remove_hook((void *)ipf_check_wrapper6, NULL, 402 PFIL_IN|PFIL_OUT, ph_inet6); 403 ipfmain.ipf_interror = 130014; 404 goto pfil_error; 405 } 406 # else 407 error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 408 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); 409 if (error) { 410 pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 411 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 412 IPFERROR(130014); 413 goto pfil_error; 414 } 415 # endif 416 # endif 417 418 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 419 if (ph_ifsync != NULL) 420 (void) pfil_add_hook((void *)ipf_pfilsync, NULL, 421 PFIL_IFNET, ph_ifsync); 422 # endif 423 #endif 424 425 #if (__NetBSD_Version__ >= 499005500) 426 for (i = 0; i < IPL_LOGSIZE; i++) 427 selinit(&ipfmain.ipf_selwait[i]); 428 #else 429 bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait)); 430 #endif 431 ipf_savep = ipf_checkp; 432 ipf_checkp = ipf_check; 433 434 #ifdef INET 435 if (softc->ipf_control_forwarding & 1) 436 ipforwarding = 1; 437 #endif 438 439 ipid = 0; 440 441 SPL_X(s); 442 443 #if (__NetBSD_Version__ >= 104010000) 444 # if (__NetBSD_Version__ >= 499002000) 445 callout_init(&softc->ipf_slow_ch, 0); 446 # else 447 callout_init(&softc->ipf_slow_ch); 448 # endif 449 callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT, 450 ipf_timer_func, softc); 451 #else 452 timeout(ipf_timer_func, softc, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 453 #endif 454 455 return 0; 456 457 #if __NetBSD_Version__ >= 105110000 458 pfil_error: 459 SPL_X(s); 460 ipf_fini_all(softc); 461 return error; 462 #endif 463 } 464 465 static void 466 ipf_timer_func(void *ptr) 467 { 468 ipf_main_softc_t *softc = ptr; 469 SPL_INT(s); 470 471 SPL_NET(s); 472 READ_ENTER(&softc->ipf_global); 473 474 if (softc->ipf_running > 0) 475 ipf_slowtimer(softc); 476 477 if (softc->ipf_running == -1 || softc->ipf_running == 1) { 478 #if NETBSD_GE_REV(104240000) 479 callout_reset(&softc->ipf_slow_ch, hz / 2, 480 ipf_timer_func, softc); 481 #else 482 timeout(ipf_timer_func, softc, 483 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT); 484 #endif 485 } 486 RWLOCK_EXIT(&softc->ipf_global); 487 SPL_X(s); 488 } 489 490 491 /* 492 * Disable the filter by removing the hooks from the IP input/output 493 * stream. 494 */ 495 int 496 ipfdetach(ipf_main_softc_t *softc) 497 { 498 SPL_INT(s); 499 #if (__NetBSD_Version__ >= 499005500) 500 int i; 501 #endif 502 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000) 503 int error = 0; 504 # if __NetBSD_Version__ >= 105150000 505 pfil_head_t *ph_inet = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET); 506 # ifdef USE_INET6 507 pfil_head_t *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, (void *)AF_INET6); 508 # endif 509 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 510 struct pfil_head *ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0); 511 # endif 512 # endif 513 #endif 514 515 SPL_NET(s); 516 517 #if (__NetBSD_Version__ >= 104010000) 518 if (softc->ipf_running > 0) 519 callout_stop(&softc->ipf_slow_ch); 520 #else 521 untimeout(ipf_slowtimer, NULL); 522 #endif /* NetBSD */ 523 524 ipf_checkp = ipf_savep; 525 (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE); 526 (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE); 527 528 #ifdef INET 529 if (softc->ipf_control_forwarding & 2) 530 ipforwarding = 0; 531 #endif 532 533 #ifdef NETBSD_PF 534 # if (__NetBSD_Version__ >= 104200000) 535 # if __NetBSD_Version__ >= 105110000 536 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET) 537 (void) pfil_remove_hook((void *)ipf_pfilsync, NULL, 538 PFIL_IFNET, ph_ifsync); 539 # endif 540 541 if (ph_inet != NULL) 542 error = pfil_remove_hook((void *)ipf_check_wrapper, NULL, 543 PFIL_IN|PFIL_OUT, ph_inet); 544 else 545 error = 0; 546 # else 547 error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 548 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); 549 # endif 550 if (error) { 551 SPL_X(s); 552 IPFERROR(130011); 553 return error; 554 } 555 # else 556 pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT); 557 # endif 558 # ifdef USE_INET6 559 # if __NetBSD_Version__ >= 105110000 560 if (ph_inet6 != NULL) 561 error = pfil_remove_hook((void *)ipf_check_wrapper6, NULL, 562 PFIL_IN|PFIL_OUT, ph_inet6); 563 else 564 error = 0; 565 # else 566 error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT, 567 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh); 568 # endif 569 if (error) { 570 SPL_X(s); 571 IPFERROR(130012); 572 return error; 573 } 574 # endif 575 #endif 576 SPL_X(s); 577 578 #if (__NetBSD_Version__ >= 499005500) 579 for (i = 0; i < IPL_LOGSIZE; i++) 580 seldestroy(&ipfmain.ipf_selwait[i]); 581 #endif 582 583 ipf_fini_all(softc); 584 585 return 0; 586 } 587 588 589 /* 590 * Filter ioctl interface. 591 */ 592 int 593 ipfioctl(dev_t dev, u_long cmd, 594 #if (__NetBSD_Version__ >= 499001000) 595 void *data, 596 #else 597 caddr_t data, 598 #endif 599 int mode 600 #if (NetBSD >= 199511) 601 # if (__NetBSD_Version__ >= 399001400) 602 , struct lwp *p 603 # if (__NetBSD_Version__ >= 399002000) 604 # define UID(l) kauth_cred_getuid((l)->l_cred) 605 # else 606 # define UID(l) ((l)->l_proc->p_cred->p_ruid) 607 # endif 608 # else 609 , struct proc *p 610 # define UID(p) ((p)->p_cred->p_ruid) 611 # endif 612 #endif 613 ) 614 { 615 int error = 0, unit = 0; 616 SPL_INT(s); 617 618 #if (__NetBSD_Version__ >= 399002000) 619 if ((mode & FWRITE) && 620 kauth_authorize_network(p->l_cred, KAUTH_NETWORK_FIREWALL, 621 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL, 622 NULL, NULL)) { 623 ipfmain.ipf_interror = 130005; 624 return EPERM; 625 } 626 #else 627 if ((securelevel >= 2) && (mode & FWRITE)) { 628 ipfmain.ipf_interror = 130001; 629 return EPERM; 630 } 631 #endif 632 633 unit = GET_MINOR(dev); 634 if ((IPL_LOGMAX < unit) || (unit < 0)) { 635 ipfmain.ipf_interror = 130002; 636 return ENXIO; 637 } 638 639 if (ipfmain.ipf_running <= 0) { 640 if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) { 641 ipfmain.ipf_interror = 130003; 642 return EIO; 643 } 644 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET && 645 cmd != SIOCIPFSET && cmd != SIOCFRENB && 646 cmd != SIOCGETFS && cmd != SIOCGETFF && 647 cmd != SIOCIPFINTERROR) { 648 ipfmain.ipf_interror = 130004; 649 return EIO; 650 } 651 } 652 653 SPL_NET(s); 654 655 error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, UID(p), p); 656 if (error != -1) { 657 SPL_X(s); 658 return error; 659 } 660 661 SPL_X(s); 662 return error; 663 } 664 665 666 /* 667 * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that 668 * requires a large amount of setting up and isn't any more efficient. 669 */ 670 int 671 ipf_send_reset(fr_info_t *fin) 672 { 673 struct tcphdr *tcp, *tcp2; 674 int tlen = 0, hlen; 675 struct mbuf *m; 676 #ifdef USE_INET6 677 ip6_t *ip6; 678 #endif 679 ip_t *ip; 680 681 tcp = fin->fin_dp; 682 if (tcp->th_flags & TH_RST) 683 return -1; /* feedback loop */ 684 685 if (ipf_checkl4sum(fin) == -1) 686 return -1; 687 688 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) + 689 ((tcp->th_flags & TH_SYN) ? 1 : 0) + 690 ((tcp->th_flags & TH_FIN) ? 1 : 0); 691 692 #ifdef USE_INET6 693 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t); 694 #else 695 hlen = sizeof(ip_t); 696 #endif 697 #ifdef MGETHDR 698 MGETHDR(m, M_DONTWAIT, MT_HEADER); 699 #else 700 MGET(m, M_DONTWAIT, MT_HEADER); 701 #endif 702 if (m == NULL) 703 return -1; 704 if (sizeof(*tcp2) + hlen > MHLEN) { 705 MCLGET(m, M_DONTWAIT); 706 if (m == NULL) 707 return -1; 708 if ((m->m_flags & M_EXT) == 0) { 709 FREE_MB_T(m); 710 return -1; 711 } 712 } 713 714 m->m_len = sizeof(*tcp2) + hlen; 715 m->m_data += max_linkhdr; 716 m->m_pkthdr.len = m->m_len; 717 m->m_pkthdr.rcvif = (struct ifnet *)0; 718 ip = mtod(m, struct ip *); 719 bzero((char *)ip, hlen); 720 #ifdef USE_INET6 721 ip6 = (ip6_t *)ip; 722 #endif 723 bzero((char *)ip, sizeof(*tcp2) + hlen); 724 tcp2 = (struct tcphdr *)((char *)ip + hlen); 725 tcp2->th_sport = tcp->th_dport; 726 tcp2->th_dport = tcp->th_sport; 727 728 if (tcp->th_flags & TH_ACK) { 729 tcp2->th_seq = tcp->th_ack; 730 tcp2->th_flags = TH_RST; 731 tcp2->th_ack = 0; 732 } else { 733 tcp2->th_seq = 0; 734 tcp2->th_ack = ntohl(tcp->th_seq); 735 tcp2->th_ack += tlen; 736 tcp2->th_ack = htonl(tcp2->th_ack); 737 tcp2->th_flags = TH_RST|TH_ACK; 738 } 739 tcp2->th_x2 = 0; 740 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2); 741 tcp2->th_win = tcp->th_win; 742 tcp2->th_sum = 0; 743 tcp2->th_urp = 0; 744 745 #ifdef USE_INET6 746 if (fin->fin_v == 6) { 747 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 748 ip6->ip6_plen = htons(sizeof(struct tcphdr)); 749 ip6->ip6_nxt = IPPROTO_TCP; 750 ip6->ip6_hlim = 0; 751 ip6->ip6_src = fin->fin_dst6.in6; 752 ip6->ip6_dst = fin->fin_src6.in6; 753 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP, 754 sizeof(*ip6), sizeof(*tcp2)); 755 return ipf_send_ip(fin, m); 756 } 757 #endif 758 #ifdef INET 759 ip->ip_p = IPPROTO_TCP; 760 ip->ip_len = htons(sizeof(struct tcphdr)); 761 ip->ip_src.s_addr = fin->fin_daddr; 762 ip->ip_dst.s_addr = fin->fin_saddr; 763 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2)); 764 ip->ip_len = hlen + sizeof(*tcp2); 765 return ipf_send_ip(fin, m); 766 #else 767 return 0; 768 #endif 769 } 770 771 772 /* 773 * Expects ip_len to be in host byte order when called. 774 */ 775 static int 776 ipf_send_ip(fr_info_t *fin, mb_t *m) 777 { 778 fr_info_t fnew; 779 #ifdef INET 780 ip_t *oip; 781 #endif 782 ip_t *ip; 783 int hlen; 784 785 ip = mtod(m, ip_t *); 786 bzero((char *)&fnew, sizeof(fnew)); 787 fnew.fin_main_soft = fin->fin_main_soft; 788 789 IP_V_A(ip, fin->fin_v); 790 switch (fin->fin_v) 791 { 792 #ifdef INET 793 case 4 : 794 oip = fin->fin_ip; 795 hlen = sizeof(*oip); 796 fnew.fin_v = 4; 797 fnew.fin_p = ip->ip_p; 798 fnew.fin_plen = ntohs(ip->ip_len); 799 HTONS(ip->ip_len); 800 IP_HL_A(ip, sizeof(*oip) >> 2); 801 ip->ip_tos = oip->ip_tos; 802 ip->ip_id = ipf_nextipid(fin); 803 ip->ip_off = htons(ip_mtudisc ? IP_DF : 0); 804 ip->ip_ttl = ip_defttl; 805 ip->ip_sum = 0; 806 break; 807 #endif 808 #ifdef USE_INET6 809 case 6 : 810 { 811 ip6_t *ip6 = (ip6_t *)ip; 812 813 ip6->ip6_vfc = 0x60; 814 ip6->ip6_hlim = IPDEFTTL; 815 816 hlen = sizeof(*ip6); 817 fnew.fin_p = ip6->ip6_nxt; 818 fnew.fin_v = 6; 819 fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen; 820 break; 821 } 822 #endif 823 default : 824 return EINVAL; 825 } 826 #ifdef KAME_IPSEC 827 m->m_pkthdr.rcvif = NULL; 828 #endif 829 830 fnew.fin_ifp = fin->fin_ifp; 831 fnew.fin_flx = FI_NOCKSUM; 832 fnew.fin_m = m; 833 fnew.fin_ip = ip; 834 fnew.fin_mp = &m; 835 fnew.fin_hlen = hlen; 836 fnew.fin_dp = (char *)ip + hlen; 837 (void) ipf_makefrip(hlen, ip, &fnew); 838 839 return ipf_fastroute(m, &m, &fnew, NULL); 840 } 841 842 843 int 844 ipf_send_icmp_err(int type, fr_info_t *fin, int dst) 845 { 846 int err, hlen, xtra, iclen, ohlen, avail, code; 847 struct in_addr dst4; 848 struct icmp *icmp; 849 struct mbuf *m; 850 i6addr_t dst6; 851 void *ifp; 852 #ifdef USE_INET6 853 ip6_t *ip6; 854 #endif 855 ip_t *ip, *ip2; 856 857 if ((type < 0) || (type > ICMP_MAXTYPE)) 858 return -1; 859 860 code = fin->fin_icode; 861 #ifdef USE_INET6 862 if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int))) 863 return -1; 864 #endif 865 866 if (ipf_checkl4sum(fin) == -1) 867 return -1; 868 #ifdef MGETHDR 869 MGETHDR(m, M_DONTWAIT, MT_HEADER); 870 #else 871 MGET(m, M_DONTWAIT, MT_HEADER); 872 #endif 873 if (m == NULL) 874 return -1; 875 avail = MHLEN; 876 877 xtra = 0; 878 hlen = 0; 879 ohlen = 0; 880 dst4.s_addr = 0; 881 ifp = fin->fin_ifp; 882 if (fin->fin_v == 4) { 883 if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) 884 switch (ntohs(fin->fin_data[0]) >> 8) 885 { 886 case ICMP_ECHO : 887 case ICMP_TSTAMP : 888 case ICMP_IREQ : 889 case ICMP_MASKREQ : 890 break; 891 default : 892 FREE_MB_T(m); 893 return 0; 894 } 895 896 if (dst == 0) { 897 if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, 898 &dst6, NULL) == -1) { 899 FREE_MB_T(m); 900 return -1; 901 } 902 dst4 = dst6.in4; 903 } else 904 dst4.s_addr = fin->fin_daddr; 905 906 hlen = sizeof(ip_t); 907 ohlen = fin->fin_hlen; 908 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 909 if (fin->fin_hlen < fin->fin_plen) 910 xtra = MIN(fin->fin_dlen, 8); 911 else 912 xtra = 0; 913 } 914 915 #ifdef USE_INET6 916 else if (fin->fin_v == 6) { 917 hlen = sizeof(ip6_t); 918 ohlen = sizeof(ip6_t); 919 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 920 type = icmptoicmp6types[type]; 921 if (type == ICMP6_DST_UNREACH) 922 code = icmptoicmp6unreach[code]; 923 924 if (iclen + max_linkhdr + fin->fin_plen > avail) { 925 MCLGET(m, M_DONTWAIT); 926 if (m == NULL) 927 return -1; 928 if ((m->m_flags & M_EXT) == 0) { 929 FREE_MB_T(m); 930 return -1; 931 } 932 avail = MCLBYTES; 933 } 934 xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); 935 xtra = MIN(xtra, IPV6_MMTU - iclen); 936 if (dst == 0) { 937 if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, 938 &dst6, NULL) == -1) { 939 FREE_MB_T(m); 940 return -1; 941 } 942 } else 943 dst6 = fin->fin_dst6; 944 } 945 #endif 946 else { 947 FREE_MB_T(m); 948 return -1; 949 } 950 951 avail -= (max_linkhdr + iclen); 952 if (avail < 0) { 953 FREE_MB_T(m); 954 return -1; 955 } 956 if (xtra > avail) 957 xtra = avail; 958 iclen += xtra; 959 m->m_data += max_linkhdr; 960 m->m_pkthdr.rcvif = (struct ifnet *)0; 961 m->m_pkthdr.len = iclen; 962 m->m_len = iclen; 963 ip = mtod(m, ip_t *); 964 icmp = (struct icmp *)((char *)ip + hlen); 965 ip2 = (ip_t *)&icmp->icmp_ip; 966 967 icmp->icmp_type = type; 968 icmp->icmp_code = fin->fin_icode; 969 icmp->icmp_cksum = 0; 970 #ifdef icmp_nextmtu 971 if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { 972 if (fin->fin_mtu != 0) { 973 icmp->icmp_nextmtu = htons(fin->fin_mtu); 974 975 } else if (ifp != NULL) { 976 icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); 977 978 } else { /* make up a number... */ 979 icmp->icmp_nextmtu = htons(fin->fin_plen - 20); 980 } 981 } 982 #endif 983 984 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); 985 986 #if defined(M_CSUM_IPv4) 987 /* 988 * Clear any in-bound checksum flags for this packet. 989 */ 990 m->m_pkthdr.csuminfo = 0; 991 #endif /* __NetBSD__ && M_CSUM_IPv4 */ 992 993 #ifdef USE_INET6 994 ip6 = (ip6_t *)ip; 995 if (fin->fin_v == 6) { 996 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 997 ip6->ip6_plen = htons(iclen - hlen); 998 ip6->ip6_nxt = IPPROTO_ICMPV6; 999 ip6->ip6_hlim = 0; 1000 ip6->ip6_src = dst6.in6; 1001 ip6->ip6_dst = fin->fin_src6.in6; 1002 if (xtra > 0) 1003 bcopy((char *)fin->fin_ip + ohlen, 1004 (char *)&icmp->icmp_ip + ohlen, xtra); 1005 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, 1006 sizeof(*ip6), iclen - hlen); 1007 } else 1008 #endif 1009 { 1010 ip->ip_p = IPPROTO_ICMP; 1011 ip->ip_src.s_addr = dst4.s_addr; 1012 ip->ip_dst.s_addr = fin->fin_saddr; 1013 1014 if (xtra > 0) 1015 bcopy((char *)fin->fin_ip + ohlen, 1016 (char *)&icmp->icmp_ip + ohlen, xtra); 1017 icmp->icmp_cksum = ipf_cksum((u_short *)icmp, 1018 sizeof(*icmp) + 8); 1019 ip->ip_len = iclen; 1020 ip->ip_p = IPPROTO_ICMP; 1021 } 1022 err = ipf_send_ip(fin, m); 1023 return err; 1024 } 1025 1026 1027 /* 1028 * m0 - pointer to mbuf where the IP packet starts 1029 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain 1030 */ 1031 int 1032 ipf_fastroute(mb_t *m0, mb_t **mpp, fr_info_t *fin, frdest_t *fdp) 1033 { 1034 register struct ip *ip, *mhip; 1035 register struct mbuf *m = *mpp; 1036 register struct route *ro; 1037 int len, off, error = 0, hlen, code; 1038 struct ifnet *ifp, *sifp; 1039 ipf_main_softc_t *softc; 1040 #if __NetBSD_Version__ >= 499001100 1041 union { 1042 struct sockaddr dst; 1043 struct sockaddr_in dst4; 1044 } u; 1045 #else 1046 struct sockaddr_in *dst4; 1047 #endif 1048 struct sockaddr *dst; 1049 u_short ip_off, ip_len; 1050 struct route iproute; 1051 struct rtentry *rt; 1052 frdest_t node; 1053 frentry_t *fr; 1054 1055 if (fin->fin_v == 6) { 1056 #ifdef USE_INET6 1057 error = ipf_fastroute6(m0, mpp, fin, fdp); 1058 #else 1059 error = EPROTONOSUPPORT; 1060 #endif 1061 if ((error != 0) && (*mpp != NULL)) 1062 FREE_MB_T(*mpp); 1063 return error; 1064 } 1065 #ifndef INET 1066 FREE_MB_T(*mpp); 1067 return EPROTONOSUPPORT; 1068 #else 1069 1070 hlen = fin->fin_hlen; 1071 ip = mtod(m0, struct ip *); 1072 softc = fin->fin_main_soft; 1073 rt = NULL; 1074 ifp = NULL; 1075 1076 # if defined(M_CSUM_IPv4) 1077 /* 1078 * Clear any in-bound checksum flags for this packet. 1079 */ 1080 m0->m_pkthdr.csuminfo = 0; 1081 # endif /* __NetBSD__ && M_CSUM_IPv4 */ 1082 1083 /* 1084 * Route packet. 1085 */ 1086 ro = &iproute; 1087 memset(ro, 0, sizeof(*ro)); 1088 fr = fin->fin_fr; 1089 1090 if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && 1091 (fdp->fd_type == FRD_DSTLIST)) { 1092 if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) 1093 fdp = &node; 1094 } 1095 if (fdp != NULL) 1096 ifp = fdp->fd_ptr; 1097 else 1098 ifp = fin->fin_ifp; 1099 1100 if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { 1101 error = -2; 1102 goto bad; 1103 } 1104 1105 # if __NetBSD_Version__ >= 499001100 1106 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 1107 sockaddr_in_init(&u.dst4, &fdp->fd_ip, 0); 1108 else 1109 sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); 1110 dst = &u.dst; 1111 rtcache_setdst(ro, dst); 1112 rt = rtcache_init(ro); 1113 # else 1114 dst4 = (struct sockaddr_in *)&ro->ro_dst; 1115 dst = (struct sockaddr *)dst4; 1116 dst4->sin_family = AF_INET; 1117 dst4->sin_addr = ip->ip_dst; 1118 1119 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 1120 dst4->sin_addr = fdp->fd_ip; 1121 1122 dst4->sin_len = sizeof(*dst); 1123 rtalloc(ro); 1124 rt = ro->ro_rt; 1125 # endif 1126 if ((ifp == NULL) && (rt != NULL)) 1127 ifp = rt->rt_ifp; 1128 if ((rt == NULL) || (ifp == NULL)) { 1129 #ifdef INET 1130 if (in_localaddr(ip->ip_dst)) 1131 error = EHOSTUNREACH; 1132 else 1133 #endif 1134 error = ENETUNREACH; 1135 goto bad; 1136 } 1137 1138 1139 if (rt->rt_flags & RTF_GATEWAY) 1140 dst = rt->rt_gateway; 1141 1142 rt->rt_use++; 1143 1144 /* 1145 * For input packets which are being "fastrouted", they won't 1146 * go back through output filtering and miss their chance to get 1147 * NAT'd and counted. Duplicated packets aren't considered to be 1148 * part of the normal packet stream, so do not NAT them or pass 1149 * them through stateful checking, etc. 1150 */ 1151 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { 1152 sifp = fin->fin_ifp; 1153 fin->fin_ifp = ifp; 1154 fin->fin_out = 1; 1155 (void) ipf_acctpkt(fin, NULL); 1156 fin->fin_fr = NULL; 1157 if (!fr || !(fr->fr_flags & FR_RETMASK)) { 1158 u_32_t pass; 1159 1160 (void) ipf_state_check(fin, &pass); 1161 } 1162 1163 switch (ipf_nat_checkout(fin, NULL)) 1164 { 1165 case 0 : 1166 break; 1167 case 1 : 1168 ip->ip_sum = 0; 1169 break; 1170 case -1 : 1171 error = -1; 1172 goto bad; 1173 break; 1174 } 1175 1176 fin->fin_ifp = sifp; 1177 fin->fin_out = 0; 1178 } else 1179 ip->ip_sum = 0; 1180 /* 1181 * If small enough for interface, can just send directly. 1182 */ 1183 m->m_pkthdr.rcvif = ifp; 1184 1185 ip_len = ntohs(ip->ip_len); 1186 if (ip_len <= ifp->if_mtu) { 1187 # if defined(M_CSUM_IPv4) 1188 # if (__NetBSD_Version__ >= 105009999) 1189 if (ifp->if_csum_flags_tx & M_CSUM_IPv4) 1190 m->m_pkthdr.csuminfo |= M_CSUM_IPv4; 1191 # else 1192 if (ifp->if_capabilities & IFCAP_CSUM_IPv4) 1193 m->m_pkthdr.csuminfo |= M_CSUM_IPv4; 1194 # endif /* (__NetBSD_Version__ >= 105009999) */ 1195 else if (ip->ip_sum == 0) 1196 ip->ip_sum = in_cksum(m, hlen); 1197 # else 1198 if (!ip->ip_sum) 1199 ip->ip_sum = in_cksum(m, hlen); 1200 # endif /* M_CSUM_IPv4 */ 1201 1202 error = (*ifp->if_output)(ifp, m, dst, rt); 1203 goto done; 1204 } 1205 1206 /* 1207 * Too large for interface; fragment if possible. 1208 * Must be able to put at least 8 bytes per fragment. 1209 */ 1210 ip_off = ntohs(ip->ip_off); 1211 if (ip_off & IP_DF) { 1212 error = EMSGSIZE; 1213 goto bad; 1214 } 1215 len = (ifp->if_mtu - hlen) &~ 7; 1216 if (len < 8) { 1217 error = EMSGSIZE; 1218 goto bad; 1219 } 1220 1221 { 1222 int mhlen, firstlen = len; 1223 struct mbuf **mnext = &m->m_act; 1224 1225 /* 1226 * Loop through length of segment after first fragment, 1227 * make new header and copy data of each part and link onto chain. 1228 */ 1229 m0 = m; 1230 mhlen = sizeof (struct ip); 1231 for (off = hlen + len; off < ip_len; off += len) { 1232 # ifdef MGETHDR 1233 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1234 # else 1235 MGET(m, M_DONTWAIT, MT_HEADER); 1236 # endif 1237 if (m == 0) { 1238 m = m0; 1239 error = ENOBUFS; 1240 goto bad; 1241 } 1242 m->m_data += max_linkhdr; 1243 mhip = mtod(m, struct ip *); 1244 bcopy((char *)ip, (char *)mhip, sizeof(*ip)); 1245 #ifdef INET 1246 if (hlen > sizeof (struct ip)) { 1247 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 1248 IP_HL_A(mhip, mhlen >> 2); 1249 } 1250 #endif 1251 m->m_len = mhlen; 1252 mhip->ip_off = ((off - hlen) >> 3) + ip_off; 1253 if (off + len >= ip_len) 1254 len = ip_len - off; 1255 else 1256 mhip->ip_off |= IP_MF; 1257 mhip->ip_len = htons((u_short)(len + mhlen)); 1258 m->m_next = m_copy(m0, off, len); 1259 if (m->m_next == 0) { 1260 error = ENOBUFS; /* ??? */ 1261 goto sendorfree; 1262 } 1263 m->m_pkthdr.len = mhlen + len; 1264 m->m_pkthdr.rcvif = NULL; 1265 mhip->ip_off = htons((u_short)mhip->ip_off); 1266 mhip->ip_sum = 0; 1267 #ifdef INET 1268 mhip->ip_sum = in_cksum(m, mhlen); 1269 #endif 1270 *mnext = m; 1271 mnext = &m->m_act; 1272 } 1273 /* 1274 * Update first fragment by trimming what's been copied out 1275 * and updating header, then send each fragment (in order). 1276 */ 1277 m_adj(m0, hlen + firstlen - ip_len); 1278 ip->ip_len = htons((u_short)(hlen + firstlen)); 1279 ip->ip_off = htons((u_short)IP_MF); 1280 ip->ip_sum = 0; 1281 #ifdef INET 1282 ip->ip_sum = in_cksum(m0, hlen); 1283 #endif 1284 sendorfree: 1285 for (m = m0; m; m = m0) { 1286 m0 = m->m_act; 1287 m->m_act = 0; 1288 if (error == 0) { 1289 error = (*ifp->if_output)(ifp, m, dst, rt); 1290 } else { 1291 FREE_MB_T(m); 1292 } 1293 } 1294 } 1295 done: 1296 if (!error) 1297 softc->ipf_frouteok[0]++; 1298 else 1299 softc->ipf_frouteok[1]++; 1300 1301 # if __NetBSD_Version__ >= 499001100 1302 rtcache_free(ro); 1303 # else 1304 if (rt) { 1305 RTFREE(rt); 1306 } 1307 # endif 1308 return error; 1309 bad: 1310 if (error == EMSGSIZE) { 1311 sifp = fin->fin_ifp; 1312 code = fin->fin_icode; 1313 fin->fin_icode = ICMP_UNREACH_NEEDFRAG; 1314 fin->fin_ifp = ifp; 1315 (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); 1316 fin->fin_ifp = sifp; 1317 fin->fin_icode = code; 1318 } 1319 FREE_MB_T(m); 1320 goto done; 1321 #endif /* INET */ 1322 } 1323 1324 1325 #if defined(USE_INET6) 1326 /* 1327 * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's 1328 * or ensure that it is an IPv6 packet that is being forwarded, those are 1329 * expected to be done by the called (ipf_fastroute). 1330 */ 1331 static int 1332 ipf_fastroute6(struct mbuf *m0, struct mbuf **mpp, fr_info_t *fin, 1333 frdest_t *fdp) 1334 { 1335 # if __NetBSD_Version__ >= 499001100 1336 struct route ip6route; 1337 const struct sockaddr *dst; 1338 union { 1339 struct sockaddr dst; 1340 struct sockaddr_in6 dst6; 1341 } u; 1342 struct route *ro; 1343 # else 1344 struct route_in6 ip6route; 1345 struct sockaddr_in6 *dst6; 1346 struct route_in6 *ro; 1347 # endif 1348 struct rtentry *rt; 1349 struct ifnet *ifp; 1350 frentry_t *fr; 1351 u_long mtu; 1352 int error; 1353 1354 error = 0; 1355 ro = &ip6route; 1356 fr = fin->fin_fr; 1357 1358 if (fdp != NULL) 1359 ifp = fdp->fd_ptr; 1360 else 1361 ifp = fin->fin_ifp; 1362 memset(ro, 0, sizeof(*ro)); 1363 # if __NetBSD_Version__ >= 499001100 1364 if (fdp != NULL && IP6_NOTZERO(&fdp->fd_ip6)) 1365 sockaddr_in6_init(&u.dst6, &fdp->fd_ip6.in6, 0, 0, 0); 1366 else 1367 sockaddr_in6_init(&u.dst6, &fin->fin_fi.fi_dst.in6, 0, 0, 0); 1368 dst = &u.dst; 1369 rtcache_setdst(ro, dst); 1370 1371 rt = rtcache_init(ro); 1372 if ((ifp == NULL) && (rt != NULL)) 1373 ifp = rt->rt_ifp; 1374 # else 1375 dst6 = (struct sockaddr_in6 *)&ro->ro_dst; 1376 dst6->sin6_family = AF_INET6; 1377 dst6->sin6_len = sizeof(struct sockaddr_in6); 1378 dst6->sin6_addr = fin->fin_fi.fi_dst.in6; 1379 1380 if (fdp != NULL) { 1381 if (IP6_NOTZERO(&fdp->fd_ip6)) 1382 dst6->sin6_addr = fdp->fd_ip6.in6; 1383 } 1384 1385 rtalloc((struct route *)ro); 1386 1387 if ((ifp == NULL) && (ro->ro_rt != NULL)) 1388 ifp = ro->ro_rt->rt_ifp; 1389 rt = ro->ro_rt; 1390 # endif 1391 if ((rt == NULL) || (ifp == NULL)) { 1392 1393 error = EHOSTUNREACH; 1394 goto bad; 1395 } 1396 1397 /* KAME */ 1398 # if __NetBSD_Version__ >= 499001100 1399 if (IN6_IS_ADDR_LINKLOCAL(&u.dst6.sin6_addr)) 1400 u.dst6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); 1401 # else 1402 if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) 1403 dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); 1404 # endif 1405 1406 { 1407 # if (__NetBSD_Version__ >= 106010000) 1408 struct in6_ifextra *ife; 1409 # endif 1410 if (rt->rt_flags & RTF_GATEWAY) 1411 # if __NetBSD_Version__ >= 499001100 1412 dst = rt->rt_gateway; 1413 # else 1414 dst6 = (struct sockaddr_in6 *)rt->rt_gateway; 1415 # endif 1416 rt->rt_use++; 1417 1418 /* Determine path MTU. */ 1419 # if (__NetBSD_Version__ <= 106009999) 1420 mtu = nd_ifinfo[ifp->if_index].linkmtu; 1421 # else 1422 ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6]; 1423 # ifdef IN6_LINKMTU 1424 mtu = IN6_LINKMTU(ifp); 1425 # else 1426 mtu = ife->nd_ifinfo[ifp->if_index].linkmtu; 1427 # endif 1428 # endif 1429 if ((error == 0) && (m0->m_pkthdr.len <= mtu)) { 1430 # if __NetBSD_Version__ >= 499001100 1431 error = nd6_output(ifp, ifp, m0, satocsin6(dst), rt); 1432 # else 1433 error = nd6_output(ifp, ifp, m0, dst6, rt); 1434 # endif 1435 } else { 1436 error = EMSGSIZE; 1437 } 1438 } 1439 bad: 1440 # if __NetBSD_Version__ >= 499001100 1441 rtcache_free(ro); 1442 # else 1443 if (ro->ro_rt != NULL) { 1444 RTFREE(((struct route *)ro)->ro_rt); 1445 } 1446 # endif 1447 return error; 1448 } 1449 #endif /* INET6 */ 1450 1451 1452 int 1453 ipf_verifysrc(fr_info_t *fin) 1454 { 1455 #if __NetBSD_Version__ >= 499001100 1456 union { 1457 struct sockaddr dst; 1458 struct sockaddr_in dst4; 1459 } u; 1460 struct rtentry *rt; 1461 #else 1462 struct sockaddr_in *dst; 1463 #endif 1464 struct route iproute; 1465 int rc; 1466 1467 #if __NetBSD_Version__ >= 499001100 1468 sockaddr_in_init(&u.dst4, &fin->fin_src, 0); 1469 rtcache_setdst(&iproute, &u.dst); 1470 rt = rtcache_init(&iproute); 1471 if (rt == NULL) 1472 rc = 0; 1473 else 1474 rc = (fin->fin_ifp == rt->rt_ifp); 1475 rtcache_free(&iproute); 1476 #else 1477 dst = (struct sockaddr_in *)&iproute.ro_dst; 1478 dst->sin_len = sizeof(*dst); 1479 dst->sin_family = AF_INET; 1480 dst->sin_addr = fin->fin_src; 1481 rtalloc(&iproute); 1482 if (iproute.ro_rt == NULL) 1483 return 0; 1484 rc = (fin->fin_ifp == iproute.ro_rt->rt_ifp); 1485 RTFREE(iproute.ro_rt); 1486 #endif 1487 return rc; 1488 } 1489 1490 1491 /* 1492 * return the first IP Address associated with an interface 1493 */ 1494 int 1495 ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr, 1496 i6addr_t *inp, i6addr_t *inpmask) 1497 { 1498 #ifdef USE_INET6 1499 struct in6_addr *inp6 = NULL; 1500 #endif 1501 struct sockaddr *sock, *mask; 1502 struct sockaddr_in *sin; 1503 struct ifaddr *ifa; 1504 struct ifnet *ifp; 1505 1506 if ((ifptr == NULL) || (ifptr == (void *)-1)) 1507 return -1; 1508 1509 ifp = ifptr; 1510 mask = NULL; 1511 1512 if (v == 4) 1513 inp->in4.s_addr = 0; 1514 #ifdef USE_INET6 1515 else if (v == 6) 1516 bzero((char *)inp, sizeof(*inp)); 1517 #endif 1518 1519 ifa = IFADDR_FIRST(ifp); 1520 sock = ifa ? ifa->ifa_addr : NULL; 1521 while (sock != NULL && ifa != NULL) { 1522 sin = (struct sockaddr_in *)sock; 1523 if ((v == 4) && (sin->sin_family == AF_INET)) 1524 break; 1525 #ifdef USE_INET6 1526 if ((v == 6) && (sin->sin_family == AF_INET6)) { 1527 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1528 if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1529 !IN6_IS_ADDR_LOOPBACK(inp6)) 1530 break; 1531 } 1532 #endif 1533 ifa = IFADDR_NEXT(ifa); 1534 if (ifa != NULL) 1535 sock = ifa->ifa_addr; 1536 } 1537 if (ifa == NULL || sock == NULL) 1538 return -1; 1539 1540 mask = ifa->ifa_netmask; 1541 if (atype == FRI_BROADCAST) 1542 sock = ifa->ifa_broadaddr; 1543 else if (atype == FRI_PEERADDR) 1544 sock = ifa->ifa_dstaddr; 1545 1546 #ifdef USE_INET6 1547 if (v == 6) 1548 return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, 1549 (struct sockaddr_in6 *)mask, 1550 inp, inpmask); 1551 #endif 1552 return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, 1553 (struct sockaddr_in *)mask, 1554 &inp->in4, &inpmask->in4); 1555 } 1556 1557 1558 u_32_t 1559 ipf_newisn(fr_info_t *fin) 1560 { 1561 #if __NetBSD_Version__ >= 105190000 /* 1.5T */ 1562 size_t asz; 1563 1564 if (fin->fin_v == 4) 1565 asz = sizeof(struct in_addr); 1566 else if (fin->fin_v == 6) 1567 asz = sizeof(fin->fin_src); 1568 else /* XXX: no way to return error */ 1569 return 0; 1570 #ifdef INET 1571 return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst, 1572 fin->fin_sport, fin->fin_dport, asz, 0); 1573 #else 1574 return ENOSYS; 1575 #endif 1576 #else 1577 static int iss_seq_off = 0; 1578 u_char hash[16]; 1579 u_32_t newiss; 1580 MD5_CTX ctx; 1581 1582 /* 1583 * Compute the base value of the ISS. It is a hash 1584 * of (saddr, sport, daddr, dport, secret). 1585 */ 1586 MD5Init(&ctx); 1587 1588 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 1589 sizeof(fin->fin_fi.fi_src)); 1590 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 1591 sizeof(fin->fin_fi.fi_dst)); 1592 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 1593 1594 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); 1595 1596 MD5Final(hash, &ctx); 1597 1598 memcpy(&newiss, hash, sizeof(newiss)); 1599 1600 /* 1601 * Now increment our "timer", and add it in to 1602 * the computed value. 1603 * 1604 * XXX Use `addin'? 1605 * XXX TCP_ISSINCR too large to use? 1606 */ 1607 iss_seq_off += 0x00010000; 1608 newiss += iss_seq_off; 1609 return newiss; 1610 #endif 1611 } 1612 1613 1614 /* ------------------------------------------------------------------------ */ 1615 /* Function: ipf_nextipid */ 1616 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 1617 /* Parameters: fin(I) - pointer to packet information */ 1618 /* */ 1619 /* Returns the next IPv4 ID to use for this packet. */ 1620 /* ------------------------------------------------------------------------ */ 1621 u_short 1622 ipf_nextipid(fr_info_t *fin) 1623 { 1624 #ifdef USE_MUTEXES 1625 ipf_main_softc_t *softc = fin->fin_main_soft; 1626 #endif 1627 u_short id; 1628 1629 MUTEX_ENTER(&softc->ipf_rw); 1630 id = ipid++; 1631 MUTEX_EXIT(&softc->ipf_rw); 1632 1633 return id; 1634 } 1635 1636 1637 EXTERN_INLINE int 1638 ipf_checkv4sum(fr_info_t *fin) 1639 { 1640 #ifdef M_CSUM_TCP_UDP_BAD 1641 int manual, pflag, cflags, active; 1642 mb_t *m; 1643 1644 if ((fin->fin_flx & FI_NOCKSUM) != 0) 1645 return 0; 1646 1647 if ((fin->fin_flx & FI_SHORT) != 0) 1648 return 1; 1649 1650 if (fin->fin_cksum != FI_CK_NEEDED) 1651 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1652 1653 manual = 0; 1654 m = fin->fin_m; 1655 if (m == NULL) { 1656 manual = 1; 1657 goto skipauto; 1658 } 1659 1660 switch (fin->fin_p) 1661 { 1662 case IPPROTO_UDP : 1663 pflag = M_CSUM_UDPv4; 1664 break; 1665 case IPPROTO_TCP : 1666 pflag = M_CSUM_TCPv4; 1667 break; 1668 default : 1669 pflag = 0; 1670 manual = 1; 1671 break; 1672 } 1673 1674 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; 1675 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; 1676 cflags = m->m_pkthdr.csum_flags & active; 1677 1678 if (pflag != 0) { 1679 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { 1680 fin->fin_flx |= FI_BAD; 1681 fin->fin_cksum = FI_CK_BAD; 1682 } else if (cflags == (pflag | M_CSUM_DATA)) { 1683 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) { 1684 fin->fin_flx |= FI_BAD; 1685 fin->fin_cksum = FI_CK_BAD; 1686 } else { 1687 fin->fin_cksum = FI_CK_SUMOK; 1688 } 1689 } else if (cflags == pflag) { 1690 fin->fin_cksum = FI_CK_SUMOK; 1691 } else { 1692 manual = 1; 1693 } 1694 } 1695 skipauto: 1696 if (manual != 0) { 1697 if (ipf_checkl4sum(fin) == -1) { 1698 fin->fin_flx |= FI_BAD; 1699 return -1; 1700 } 1701 } 1702 #else 1703 if (ipf_checkl4sum(fin) == -1) { 1704 fin->fin_flx |= FI_BAD; 1705 return -1; 1706 } 1707 #endif 1708 return 0; 1709 } 1710 1711 1712 #ifdef USE_INET6 1713 EXTERN_INLINE int 1714 ipf_checkv6sum(fr_info_t *fin) 1715 { 1716 # ifdef M_CSUM_TCP_UDP_BAD 1717 int manual, pflag, cflags, active; 1718 mb_t *m; 1719 1720 if ((fin->fin_flx & FI_NOCKSUM) != 0) 1721 return 0; 1722 1723 if ((fin->fin_flx & FI_SHORT) != 0) 1724 return 1; 1725 1726 if (fin->fin_cksum != FI_CK_SUMOK) 1727 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1728 1729 1730 manual = 0; 1731 m = fin->fin_m; 1732 1733 switch (fin->fin_p) 1734 { 1735 case IPPROTO_UDP : 1736 pflag = M_CSUM_UDPv6; 1737 break; 1738 case IPPROTO_TCP : 1739 pflag = M_CSUM_TCPv6; 1740 break; 1741 default : 1742 pflag = 0; 1743 manual = 1; 1744 break; 1745 } 1746 1747 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; 1748 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; 1749 cflags = m->m_pkthdr.csum_flags & active; 1750 1751 if (pflag != 0) { 1752 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { 1753 fin->fin_flx |= FI_BAD; 1754 } else if (cflags == (pflag | M_CSUM_DATA)) { 1755 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) 1756 fin->fin_flx |= FI_BAD; 1757 } else if (cflags == pflag) { 1758 ; 1759 } else { 1760 manual = 1; 1761 } 1762 } 1763 if (manual != 0) { 1764 if (ipf_checkl4sum(fin) == -1) { 1765 fin->fin_flx |= FI_BAD; 1766 return -1; 1767 } 1768 } 1769 # else 1770 if (ipf_checkl4sum(fin) == -1) { 1771 fin->fin_flx |= FI_BAD; 1772 return -1; 1773 } 1774 # endif 1775 return 0; 1776 } 1777 #endif /* USE_INET6 */ 1778 1779 1780 size_t 1781 mbufchainlen(struct mbuf *m0) 1782 { 1783 size_t len; 1784 1785 if ((m0->m_flags & M_PKTHDR) != 0) { 1786 len = m0->m_pkthdr.len; 1787 } else { 1788 struct mbuf *m; 1789 1790 for (m = m0, len = 0; m != NULL; m = m->m_next) 1791 len += m->m_len; 1792 } 1793 return len; 1794 } 1795 1796 1797 /* ------------------------------------------------------------------------ */ 1798 /* Function: ipf_pullup */ 1799 /* Returns: NULL == pullup failed, else pointer to protocol header */ 1800 /* Parameters: xmin(I)- pointer to buffer where data packet starts */ 1801 /* fin(I) - pointer to packet information */ 1802 /* len(I) - number of bytes to pullup */ 1803 /* */ 1804 /* Attempt to move at least len bytes (from the start of the buffer) into a */ 1805 /* single buffer for ease of access. Operating system native functions are */ 1806 /* used to manage buffers - if necessary. If the entire packet ends up in */ 1807 /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ 1808 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ 1809 /* and ONLY if the pullup succeeds. */ 1810 /* */ 1811 /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ 1812 /* of buffers that starts at *fin->fin_mp. */ 1813 /* ------------------------------------------------------------------------ */ 1814 void * 1815 ipf_pullup(mb_t *xmin, fr_info_t *fin, int len) 1816 { 1817 int dpoff, ipoff; 1818 mb_t *m = xmin; 1819 char *ip; 1820 1821 if (m == NULL) 1822 return NULL; 1823 1824 ip = (char *)fin->fin_ip; 1825 if ((fin->fin_flx & FI_COALESCE) != 0) 1826 return ip; 1827 1828 ipoff = fin->fin_ipoff; 1829 if (fin->fin_dp != NULL) 1830 dpoff = (char *)fin->fin_dp - (char *)ip; 1831 else 1832 dpoff = 0; 1833 1834 if (M_LEN(m) < len) { 1835 mb_t *n = *fin->fin_mp; 1836 /* 1837 * Assume that M_PKTHDR is set and just work with what is left 1838 * rather than check.. 1839 * Should not make any real difference, anyway. 1840 */ 1841 if (m != n) { 1842 /* 1843 * Record the mbuf that points to the mbuf that we're 1844 * about to go to work on so that we can update the 1845 * m_next appropriately later. 1846 */ 1847 for (; n->m_next != m; n = n->m_next) 1848 ; 1849 } else { 1850 n = NULL; 1851 } 1852 1853 #ifdef MHLEN 1854 if (len > MHLEN) 1855 #else 1856 if (len > MLEN) 1857 #endif 1858 { 1859 #ifdef HAVE_M_PULLDOWN 1860 if (m_pulldown(m, 0, len, NULL) == NULL) 1861 m = NULL; 1862 #else 1863 FREE_MB_T(*fin->fin_mp); 1864 m = NULL; 1865 n = NULL; 1866 #endif 1867 } else 1868 { 1869 m = m_pullup(m, len); 1870 } 1871 if (n != NULL) 1872 n->m_next = m; 1873 if (m == NULL) { 1874 /* 1875 * When n is non-NULL, it indicates that m pointed to 1876 * a sub-chain (tail) of the mbuf and that the head 1877 * of this chain has not yet been free'd. 1878 */ 1879 if (n != NULL) { 1880 FREE_MB_T(*fin->fin_mp); 1881 } 1882 1883 *fin->fin_mp = NULL; 1884 fin->fin_m = NULL; 1885 return NULL; 1886 } 1887 1888 if (n == NULL) 1889 *fin->fin_mp = m; 1890 1891 while (M_LEN(m) == 0) { 1892 m = m->m_next; 1893 } 1894 fin->fin_m = m; 1895 ip = MTOD(m, char *) + ipoff; 1896 1897 fin->fin_ip = (ip_t *)ip; 1898 if (fin->fin_dp != NULL) 1899 fin->fin_dp = (char *)fin->fin_ip + dpoff; 1900 if (fin->fin_fraghdr != NULL) 1901 fin->fin_fraghdr = (char *)ip + 1902 ((char *)fin->fin_fraghdr - 1903 (char *)fin->fin_ip); 1904 } 1905 1906 if (len == fin->fin_plen) 1907 fin->fin_flx |= FI_COALESCE; 1908 return ip; 1909 } 1910 1911 1912 int 1913 ipf_inject(fr_info_t *fin, mb_t *m) 1914 { 1915 int error; 1916 1917 if (fin->fin_out == 0) { 1918 struct ifqueue *ifq; 1919 1920 ifq = &ipintrq; 1921 1922 if (IF_QFULL(ifq)) { 1923 IF_DROP(ifq); 1924 FREE_MB_T(m); 1925 error = ENOBUFS; 1926 } else { 1927 IF_ENQUEUE(ifq, m); 1928 error = 0; 1929 } 1930 } else { 1931 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); 1932 } 1933 1934 return error; 1935 } 1936 1937 1938 u_32_t 1939 ipf_random(void) 1940 { 1941 int number; 1942 1943 #ifdef _CPRNG_H 1944 number = cprng_fast32(); 1945 #else 1946 number = arc4random(); 1947 #endif 1948 return number; 1949 } 1950 1951 1952 /* 1953 * routines below for saving IP headers to buffer 1954 */ 1955 static int ipfopen(dev_t dev, int flags 1956 #if (NetBSD >= 199511) 1957 , int devtype, PROC_T *p 1958 #endif 1959 ) 1960 { 1961 u_int unit = GET_MINOR(dev); 1962 int error; 1963 1964 if (IPL_LOGMAX < unit) { 1965 error = ENXIO; 1966 } else { 1967 switch (unit) 1968 { 1969 case IPL_LOGIPF : 1970 case IPL_LOGNAT : 1971 case IPL_LOGSTATE : 1972 case IPL_LOGAUTH : 1973 case IPL_LOGLOOKUP : 1974 case IPL_LOGSYNC : 1975 #ifdef IPFILTER_SCAN 1976 case IPL_LOGSCAN : 1977 #endif 1978 error = 0; 1979 break; 1980 default : 1981 error = ENXIO; 1982 break; 1983 } 1984 } 1985 return error; 1986 } 1987 1988 1989 static int ipfclose(dev_t dev, int flags 1990 #if (NetBSD >= 199511) 1991 , int devtype, PROC_T *p 1992 #endif 1993 ) 1994 { 1995 u_int unit = GET_MINOR(dev); 1996 1997 if (IPL_LOGMAX < unit) 1998 unit = ENXIO; 1999 else 2000 unit = 0; 2001 return unit; 2002 } 2003 2004 /* 2005 * ipfread/ipflog 2006 * both of these must operate with at least splnet() lest they be 2007 * called during packet processing and cause an inconsistancy to appear in 2008 * the filter lists. 2009 */ 2010 static int ipfread(dev_t dev, struct uio *uio, int ioflag) 2011 { 2012 2013 if (ipfmain.ipf_running < 1) { 2014 ipfmain.ipf_interror = 130006; 2015 return EIO; 2016 } 2017 2018 if (GET_MINOR(dev) == IPL_LOGSYNC) 2019 return ipf_sync_read(&ipfmain, uio); 2020 2021 #ifdef IPFILTER_LOG 2022 return ipf_log_read(&ipfmain, GET_MINOR(dev), uio); 2023 #else 2024 ipfmain.ipf_interror = 130007; 2025 return ENXIO; 2026 #endif 2027 } 2028 2029 2030 /* 2031 * ipfwrite 2032 * both of these must operate with at least splnet() lest they be 2033 * called during packet processing and cause an inconsistancy to appear in 2034 * the filter lists. 2035 */ 2036 static int ipfwrite(dev_t dev, struct uio *uio, int ioflag) 2037 { 2038 2039 if (ipfmain.ipf_running < 1) { 2040 ipfmain.ipf_interror = 130008; 2041 return EIO; 2042 } 2043 2044 if (GET_MINOR(dev) == IPL_LOGSYNC) 2045 return ipf_sync_write(&ipfmain, uio); 2046 ipfmain.ipf_interror = 130009; 2047 return ENXIO; 2048 } 2049 2050 2051 static int ipfpoll(dev_t dev, int events, PROC_T *p) 2052 { 2053 u_int unit = GET_MINOR(dev); 2054 int revents = 0; 2055 2056 if (IPL_LOGMAX < unit) { 2057 ipfmain.ipf_interror = 130010; 2058 return ENXIO; 2059 } 2060 2061 switch (unit) 2062 { 2063 case IPL_LOGIPF : 2064 case IPL_LOGNAT : 2065 case IPL_LOGSTATE : 2066 #ifdef IPFILTER_LOG 2067 if ((events & (POLLIN | POLLRDNORM)) && 2068 ipf_log_canread(&ipfmain, unit)) 2069 revents |= events & (POLLIN | POLLRDNORM); 2070 #endif 2071 break; 2072 case IPL_LOGAUTH : 2073 if ((events & (POLLIN | POLLRDNORM)) && 2074 ipf_auth_waiting(&ipfmain)) 2075 revents |= events & (POLLIN | POLLRDNORM); 2076 break; 2077 case IPL_LOGSYNC : 2078 if ((events & (POLLIN | POLLRDNORM)) && 2079 ipf_sync_canread(&ipfmain)) 2080 revents |= events & (POLLIN | POLLRDNORM); 2081 if ((events & (POLLOUT | POLLWRNORM)) && 2082 ipf_sync_canwrite(&ipfmain)) 2083 revents |= events & (POLLOUT | POLLWRNORM); 2084 break; 2085 case IPL_LOGSCAN : 2086 case IPL_LOGLOOKUP : 2087 default : 2088 break; 2089 } 2090 2091 if ((revents == 0) && (((events & (POLLIN|POLLRDNORM)) != 0))) 2092 selrecord(p, &ipfmain.ipf_selwait[unit]); 2093 return revents; 2094 } 2095 2096 u_int 2097 ipf_pcksum(fr_info_t *fin, int hlen, u_int sum) 2098 { 2099 struct mbuf *m; 2100 u_int sum2; 2101 int off; 2102 2103 m = fin->fin_m; 2104 off = (char *)fin->fin_dp - (char *)fin->fin_ip; 2105 m->m_data += hlen; 2106 m->m_len -= hlen; 2107 sum2 = in_cksum(fin->fin_m, fin->fin_plen - off); 2108 m->m_len += hlen; 2109 m->m_data -= hlen; 2110 2111 /* 2112 * Both sum and sum2 are partial sums, so combine them together. 2113 */ 2114 sum += ~sum2 & 0xffff; 2115 while (sum > 0xffff) 2116 sum = (sum & 0xffff) + (sum >> 16); 2117 sum2 = ~sum & 0xffff; 2118 return sum2; 2119 } 2120