1 /* $NetBSD: ip_fil_netbsd.c,v 1.7 2013/11/01 06:42:23 mrg 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.7 2013/11/01 06:42:23 mrg 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; 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 int code; 854 ip6_t *ip6; 855 #endif 856 ip_t *ip, *ip2; 857 858 if ((type < 0) || (type > ICMP_MAXTYPE)) 859 return -1; 860 861 #ifdef USE_INET6 862 code = fin->fin_icode; 863 if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int))) 864 return -1; 865 #endif 866 867 if (ipf_checkl4sum(fin) == -1) 868 return -1; 869 #ifdef MGETHDR 870 MGETHDR(m, M_DONTWAIT, MT_HEADER); 871 #else 872 MGET(m, M_DONTWAIT, MT_HEADER); 873 #endif 874 if (m == NULL) 875 return -1; 876 avail = MHLEN; 877 878 xtra = 0; 879 hlen = 0; 880 ohlen = 0; 881 dst4.s_addr = 0; 882 ifp = fin->fin_ifp; 883 if (fin->fin_v == 4) { 884 if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT)) 885 switch (ntohs(fin->fin_data[0]) >> 8) 886 { 887 case ICMP_ECHO : 888 case ICMP_TSTAMP : 889 case ICMP_IREQ : 890 case ICMP_MASKREQ : 891 break; 892 default : 893 FREE_MB_T(m); 894 return 0; 895 } 896 897 if (dst == 0) { 898 if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp, 899 &dst6, NULL) == -1) { 900 FREE_MB_T(m); 901 return -1; 902 } 903 dst4 = dst6.in4; 904 } else 905 dst4.s_addr = fin->fin_daddr; 906 907 hlen = sizeof(ip_t); 908 ohlen = fin->fin_hlen; 909 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 910 if (fin->fin_hlen < fin->fin_plen) 911 xtra = MIN(fin->fin_dlen, 8); 912 else 913 xtra = 0; 914 } 915 916 #ifdef USE_INET6 917 else if (fin->fin_v == 6) { 918 hlen = sizeof(ip6_t); 919 ohlen = sizeof(ip6_t); 920 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen; 921 type = icmptoicmp6types[type]; 922 if (type == ICMP6_DST_UNREACH) 923 code = icmptoicmp6unreach[code]; 924 925 if (iclen + max_linkhdr + fin->fin_plen > avail) { 926 MCLGET(m, M_DONTWAIT); 927 if (m == NULL) 928 return -1; 929 if ((m->m_flags & M_EXT) == 0) { 930 FREE_MB_T(m); 931 return -1; 932 } 933 avail = MCLBYTES; 934 } 935 xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr); 936 xtra = MIN(xtra, IPV6_MMTU - iclen); 937 if (dst == 0) { 938 if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp, 939 &dst6, NULL) == -1) { 940 FREE_MB_T(m); 941 return -1; 942 } 943 } else 944 dst6 = fin->fin_dst6; 945 } 946 #endif 947 else { 948 FREE_MB_T(m); 949 return -1; 950 } 951 952 avail -= (max_linkhdr + iclen); 953 if (avail < 0) { 954 FREE_MB_T(m); 955 return -1; 956 } 957 if (xtra > avail) 958 xtra = avail; 959 iclen += xtra; 960 m->m_data += max_linkhdr; 961 m->m_pkthdr.rcvif = (struct ifnet *)0; 962 m->m_pkthdr.len = iclen; 963 m->m_len = iclen; 964 ip = mtod(m, ip_t *); 965 icmp = (struct icmp *)((char *)ip + hlen); 966 ip2 = (ip_t *)&icmp->icmp_ip; 967 968 icmp->icmp_type = type; 969 icmp->icmp_code = fin->fin_icode; 970 icmp->icmp_cksum = 0; 971 #ifdef icmp_nextmtu 972 if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) { 973 if (fin->fin_mtu != 0) { 974 icmp->icmp_nextmtu = htons(fin->fin_mtu); 975 976 } else if (ifp != NULL) { 977 icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp)); 978 979 } else { /* make up a number... */ 980 icmp->icmp_nextmtu = htons(fin->fin_plen - 20); 981 } 982 } 983 #endif 984 985 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen); 986 987 #if defined(M_CSUM_IPv4) 988 /* 989 * Clear any in-bound checksum flags for this packet. 990 */ 991 m->m_pkthdr.csuminfo = 0; 992 #endif /* __NetBSD__ && M_CSUM_IPv4 */ 993 994 #ifdef USE_INET6 995 ip6 = (ip6_t *)ip; 996 if (fin->fin_v == 6) { 997 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow; 998 ip6->ip6_plen = htons(iclen - hlen); 999 ip6->ip6_nxt = IPPROTO_ICMPV6; 1000 ip6->ip6_hlim = 0; 1001 ip6->ip6_src = dst6.in6; 1002 ip6->ip6_dst = fin->fin_src6.in6; 1003 if (xtra > 0) 1004 bcopy((char *)fin->fin_ip + ohlen, 1005 (char *)&icmp->icmp_ip + ohlen, xtra); 1006 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6, 1007 sizeof(*ip6), iclen - hlen); 1008 } else 1009 #endif 1010 { 1011 ip->ip_p = IPPROTO_ICMP; 1012 ip->ip_src.s_addr = dst4.s_addr; 1013 ip->ip_dst.s_addr = fin->fin_saddr; 1014 1015 if (xtra > 0) 1016 bcopy((char *)fin->fin_ip + ohlen, 1017 (char *)&icmp->icmp_ip + ohlen, xtra); 1018 icmp->icmp_cksum = ipf_cksum((u_short *)icmp, 1019 sizeof(*icmp) + 8); 1020 ip->ip_len = iclen; 1021 ip->ip_p = IPPROTO_ICMP; 1022 } 1023 err = ipf_send_ip(fin, m); 1024 return err; 1025 } 1026 1027 1028 /* 1029 * m0 - pointer to mbuf where the IP packet starts 1030 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain 1031 */ 1032 int 1033 ipf_fastroute(mb_t *m0, mb_t **mpp, fr_info_t *fin, frdest_t *fdp) 1034 { 1035 register struct ip *ip, *mhip; 1036 register struct mbuf *m = *mpp; 1037 register struct route *ro; 1038 int len, off, error = 0, hlen, code; 1039 struct ifnet *ifp, *sifp; 1040 ipf_main_softc_t *softc; 1041 #if __NetBSD_Version__ >= 499001100 1042 union { 1043 struct sockaddr dst; 1044 struct sockaddr_in dst4; 1045 } u; 1046 #else 1047 struct sockaddr_in *dst4; 1048 #endif 1049 struct sockaddr *dst; 1050 u_short ip_off, ip_len; 1051 struct route iproute; 1052 struct rtentry *rt; 1053 frdest_t node; 1054 frentry_t *fr; 1055 1056 if (fin->fin_v == 6) { 1057 #ifdef USE_INET6 1058 error = ipf_fastroute6(m0, mpp, fin, fdp); 1059 #else 1060 error = EPROTONOSUPPORT; 1061 #endif 1062 if ((error != 0) && (*mpp != NULL)) 1063 FREE_MB_T(*mpp); 1064 return error; 1065 } 1066 #ifndef INET 1067 FREE_MB_T(*mpp); 1068 return EPROTONOSUPPORT; 1069 #else 1070 1071 hlen = fin->fin_hlen; 1072 ip = mtod(m0, struct ip *); 1073 softc = fin->fin_main_soft; 1074 rt = NULL; 1075 ifp = NULL; 1076 1077 # if defined(M_CSUM_IPv4) 1078 /* 1079 * Clear any in-bound checksum flags for this packet. 1080 */ 1081 m0->m_pkthdr.csuminfo = 0; 1082 # endif /* __NetBSD__ && M_CSUM_IPv4 */ 1083 1084 /* 1085 * Route packet. 1086 */ 1087 ro = &iproute; 1088 memset(ro, 0, sizeof(*ro)); 1089 fr = fin->fin_fr; 1090 1091 if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && 1092 (fdp->fd_type == FRD_DSTLIST)) { 1093 if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0) 1094 fdp = &node; 1095 } 1096 if (fdp != NULL) 1097 ifp = fdp->fd_ptr; 1098 else 1099 ifp = fin->fin_ifp; 1100 1101 if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) { 1102 error = -2; 1103 goto bad; 1104 } 1105 1106 # if __NetBSD_Version__ >= 499001100 1107 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 1108 sockaddr_in_init(&u.dst4, &fdp->fd_ip, 0); 1109 else 1110 sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); 1111 dst = &u.dst; 1112 rtcache_setdst(ro, dst); 1113 rt = rtcache_init(ro); 1114 # else 1115 dst4 = (struct sockaddr_in *)&ro->ro_dst; 1116 dst = (struct sockaddr *)dst4; 1117 dst4->sin_family = AF_INET; 1118 dst4->sin_addr = ip->ip_dst; 1119 1120 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0)) 1121 dst4->sin_addr = fdp->fd_ip; 1122 1123 dst4->sin_len = sizeof(*dst); 1124 rtalloc(ro); 1125 rt = ro->ro_rt; 1126 # endif 1127 if ((ifp == NULL) && (rt != NULL)) 1128 ifp = rt->rt_ifp; 1129 if ((rt == NULL) || (ifp == NULL)) { 1130 #ifdef INET 1131 if (in_localaddr(ip->ip_dst)) 1132 error = EHOSTUNREACH; 1133 else 1134 #endif 1135 error = ENETUNREACH; 1136 goto bad; 1137 } 1138 1139 1140 if (rt->rt_flags & RTF_GATEWAY) 1141 dst = rt->rt_gateway; 1142 1143 rt->rt_use++; 1144 1145 /* 1146 * For input packets which are being "fastrouted", they won't 1147 * go back through output filtering and miss their chance to get 1148 * NAT'd and counted. Duplicated packets aren't considered to be 1149 * part of the normal packet stream, so do not NAT them or pass 1150 * them through stateful checking, etc. 1151 */ 1152 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) { 1153 sifp = fin->fin_ifp; 1154 fin->fin_ifp = ifp; 1155 fin->fin_out = 1; 1156 (void) ipf_acctpkt(fin, NULL); 1157 fin->fin_fr = NULL; 1158 if (!fr || !(fr->fr_flags & FR_RETMASK)) { 1159 u_32_t pass; 1160 1161 (void) ipf_state_check(fin, &pass); 1162 } 1163 1164 switch (ipf_nat_checkout(fin, NULL)) 1165 { 1166 case 0 : 1167 break; 1168 case 1 : 1169 ip->ip_sum = 0; 1170 break; 1171 case -1 : 1172 error = -1; 1173 goto bad; 1174 break; 1175 } 1176 1177 fin->fin_ifp = sifp; 1178 fin->fin_out = 0; 1179 } else 1180 ip->ip_sum = 0; 1181 /* 1182 * If small enough for interface, can just send directly. 1183 */ 1184 m->m_pkthdr.rcvif = ifp; 1185 1186 ip_len = ntohs(ip->ip_len); 1187 if (ip_len <= ifp->if_mtu) { 1188 # if defined(M_CSUM_IPv4) 1189 # if (__NetBSD_Version__ >= 105009999) 1190 if (ifp->if_csum_flags_tx & M_CSUM_IPv4) 1191 m->m_pkthdr.csuminfo |= M_CSUM_IPv4; 1192 # else 1193 if (ifp->if_capabilities & IFCAP_CSUM_IPv4) 1194 m->m_pkthdr.csuminfo |= M_CSUM_IPv4; 1195 # endif /* (__NetBSD_Version__ >= 105009999) */ 1196 else if (ip->ip_sum == 0) 1197 ip->ip_sum = in_cksum(m, hlen); 1198 # else 1199 if (!ip->ip_sum) 1200 ip->ip_sum = in_cksum(m, hlen); 1201 # endif /* M_CSUM_IPv4 */ 1202 1203 error = (*ifp->if_output)(ifp, m, dst, rt); 1204 goto done; 1205 } 1206 1207 /* 1208 * Too large for interface; fragment if possible. 1209 * Must be able to put at least 8 bytes per fragment. 1210 */ 1211 ip_off = ntohs(ip->ip_off); 1212 if (ip_off & IP_DF) { 1213 error = EMSGSIZE; 1214 goto bad; 1215 } 1216 len = (ifp->if_mtu - hlen) &~ 7; 1217 if (len < 8) { 1218 error = EMSGSIZE; 1219 goto bad; 1220 } 1221 1222 { 1223 int mhlen, firstlen = len; 1224 struct mbuf **mnext = &m->m_act; 1225 1226 /* 1227 * Loop through length of segment after first fragment, 1228 * make new header and copy data of each part and link onto chain. 1229 */ 1230 m0 = m; 1231 mhlen = sizeof (struct ip); 1232 for (off = hlen + len; off < ip_len; off += len) { 1233 # ifdef MGETHDR 1234 MGETHDR(m, M_DONTWAIT, MT_HEADER); 1235 # else 1236 MGET(m, M_DONTWAIT, MT_HEADER); 1237 # endif 1238 if (m == 0) { 1239 m = m0; 1240 error = ENOBUFS; 1241 goto bad; 1242 } 1243 m->m_data += max_linkhdr; 1244 mhip = mtod(m, struct ip *); 1245 bcopy((char *)ip, (char *)mhip, sizeof(*ip)); 1246 #ifdef INET 1247 if (hlen > sizeof (struct ip)) { 1248 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 1249 IP_HL_A(mhip, mhlen >> 2); 1250 } 1251 #endif 1252 m->m_len = mhlen; 1253 mhip->ip_off = ((off - hlen) >> 3) + ip_off; 1254 if (off + len >= ip_len) 1255 len = ip_len - off; 1256 else 1257 mhip->ip_off |= IP_MF; 1258 mhip->ip_len = htons((u_short)(len + mhlen)); 1259 m->m_next = m_copy(m0, off, len); 1260 if (m->m_next == 0) { 1261 error = ENOBUFS; /* ??? */ 1262 goto sendorfree; 1263 } 1264 m->m_pkthdr.len = mhlen + len; 1265 m->m_pkthdr.rcvif = NULL; 1266 mhip->ip_off = htons((u_short)mhip->ip_off); 1267 mhip->ip_sum = 0; 1268 #ifdef INET 1269 mhip->ip_sum = in_cksum(m, mhlen); 1270 #endif 1271 *mnext = m; 1272 mnext = &m->m_act; 1273 } 1274 /* 1275 * Update first fragment by trimming what's been copied out 1276 * and updating header, then send each fragment (in order). 1277 */ 1278 m_adj(m0, hlen + firstlen - ip_len); 1279 ip->ip_len = htons((u_short)(hlen + firstlen)); 1280 ip->ip_off = htons((u_short)IP_MF); 1281 ip->ip_sum = 0; 1282 #ifdef INET 1283 ip->ip_sum = in_cksum(m0, hlen); 1284 #endif 1285 sendorfree: 1286 for (m = m0; m; m = m0) { 1287 m0 = m->m_act; 1288 m->m_act = 0; 1289 if (error == 0) { 1290 error = (*ifp->if_output)(ifp, m, dst, rt); 1291 } else { 1292 FREE_MB_T(m); 1293 } 1294 } 1295 } 1296 done: 1297 if (!error) 1298 softc->ipf_frouteok[0]++; 1299 else 1300 softc->ipf_frouteok[1]++; 1301 1302 # if __NetBSD_Version__ >= 499001100 1303 rtcache_free(ro); 1304 # else 1305 if (rt) { 1306 RTFREE(rt); 1307 } 1308 # endif 1309 return error; 1310 bad: 1311 if (error == EMSGSIZE) { 1312 sifp = fin->fin_ifp; 1313 code = fin->fin_icode; 1314 fin->fin_icode = ICMP_UNREACH_NEEDFRAG; 1315 fin->fin_ifp = ifp; 1316 (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1); 1317 fin->fin_ifp = sifp; 1318 fin->fin_icode = code; 1319 } 1320 FREE_MB_T(m); 1321 goto done; 1322 #endif /* INET */ 1323 } 1324 1325 1326 #if defined(USE_INET6) 1327 /* 1328 * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's 1329 * or ensure that it is an IPv6 packet that is being forwarded, those are 1330 * expected to be done by the called (ipf_fastroute). 1331 */ 1332 static int 1333 ipf_fastroute6(struct mbuf *m0, struct mbuf **mpp, fr_info_t *fin, 1334 frdest_t *fdp) 1335 { 1336 # if __NetBSD_Version__ >= 499001100 1337 struct route ip6route; 1338 const struct sockaddr *dst; 1339 union { 1340 struct sockaddr dst; 1341 struct sockaddr_in6 dst6; 1342 } u; 1343 struct route *ro; 1344 # else 1345 struct route_in6 ip6route; 1346 struct sockaddr_in6 *dst6; 1347 struct route_in6 *ro; 1348 # endif 1349 struct rtentry *rt; 1350 struct ifnet *ifp; 1351 u_long mtu; 1352 int error; 1353 1354 error = 0; 1355 ro = &ip6route; 1356 1357 if (fdp != NULL) 1358 ifp = fdp->fd_ptr; 1359 else 1360 ifp = fin->fin_ifp; 1361 memset(ro, 0, sizeof(*ro)); 1362 # if __NetBSD_Version__ >= 499001100 1363 if (fdp != NULL && IP6_NOTZERO(&fdp->fd_ip6)) 1364 sockaddr_in6_init(&u.dst6, &fdp->fd_ip6.in6, 0, 0, 0); 1365 else 1366 sockaddr_in6_init(&u.dst6, &fin->fin_fi.fi_dst.in6, 0, 0, 0); 1367 dst = &u.dst; 1368 rtcache_setdst(ro, dst); 1369 1370 rt = rtcache_init(ro); 1371 if ((ifp == NULL) && (rt != NULL)) 1372 ifp = rt->rt_ifp; 1373 # else 1374 dst6 = (struct sockaddr_in6 *)&ro->ro_dst; 1375 dst6->sin6_family = AF_INET6; 1376 dst6->sin6_len = sizeof(struct sockaddr_in6); 1377 dst6->sin6_addr = fin->fin_fi.fi_dst.in6; 1378 1379 if (fdp != NULL) { 1380 if (IP6_NOTZERO(&fdp->fd_ip6)) 1381 dst6->sin6_addr = fdp->fd_ip6.in6; 1382 } 1383 1384 rtalloc((struct route *)ro); 1385 1386 if ((ifp == NULL) && (ro->ro_rt != NULL)) 1387 ifp = ro->ro_rt->rt_ifp; 1388 rt = ro->ro_rt; 1389 # endif 1390 if ((rt == NULL) || (ifp == NULL)) { 1391 1392 error = EHOSTUNREACH; 1393 goto bad; 1394 } 1395 1396 /* KAME */ 1397 # if __NetBSD_Version__ >= 499001100 1398 if (IN6_IS_ADDR_LINKLOCAL(&u.dst6.sin6_addr)) 1399 u.dst6.sin6_addr.s6_addr16[1] = htons(ifp->if_index); 1400 # else 1401 if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) 1402 dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index); 1403 # endif 1404 1405 { 1406 # if (__NetBSD_Version__ >= 106010000) && !defined(IN6_LINKMTU) 1407 struct in6_ifextra *ife; 1408 # endif 1409 if (rt->rt_flags & RTF_GATEWAY) 1410 # if __NetBSD_Version__ >= 499001100 1411 dst = rt->rt_gateway; 1412 # else 1413 dst6 = (struct sockaddr_in6 *)rt->rt_gateway; 1414 # endif 1415 rt->rt_use++; 1416 1417 /* Determine path MTU. */ 1418 # if (__NetBSD_Version__ <= 106009999) 1419 mtu = nd_ifinfo[ifp->if_index].linkmtu; 1420 # else 1421 # ifdef IN6_LINKMTU 1422 mtu = IN6_LINKMTU(ifp); 1423 # else 1424 ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6]; 1425 mtu = ife->nd_ifinfo[ifp->if_index].linkmtu; 1426 # endif 1427 # endif 1428 if ((error == 0) && (m0->m_pkthdr.len <= mtu)) { 1429 # if __NetBSD_Version__ >= 499001100 1430 error = nd6_output(ifp, ifp, m0, satocsin6(dst), rt); 1431 # else 1432 error = nd6_output(ifp, ifp, m0, dst6, rt); 1433 # endif 1434 } else { 1435 error = EMSGSIZE; 1436 } 1437 } 1438 bad: 1439 # if __NetBSD_Version__ >= 499001100 1440 rtcache_free(ro); 1441 # else 1442 if (ro->ro_rt != NULL) { 1443 RTFREE(((struct route *)ro)->ro_rt); 1444 } 1445 # endif 1446 return error; 1447 } 1448 #endif /* INET6 */ 1449 1450 1451 int 1452 ipf_verifysrc(fr_info_t *fin) 1453 { 1454 #if __NetBSD_Version__ >= 499001100 1455 union { 1456 struct sockaddr dst; 1457 struct sockaddr_in dst4; 1458 } u; 1459 struct rtentry *rt; 1460 #else 1461 struct sockaddr_in *dst; 1462 #endif 1463 struct route iproute; 1464 int rc; 1465 1466 #if __NetBSD_Version__ >= 499001100 1467 sockaddr_in_init(&u.dst4, &fin->fin_src, 0); 1468 rtcache_setdst(&iproute, &u.dst); 1469 rt = rtcache_init(&iproute); 1470 if (rt == NULL) 1471 rc = 0; 1472 else 1473 rc = (fin->fin_ifp == rt->rt_ifp); 1474 rtcache_free(&iproute); 1475 #else 1476 dst = (struct sockaddr_in *)&iproute.ro_dst; 1477 dst->sin_len = sizeof(*dst); 1478 dst->sin_family = AF_INET; 1479 dst->sin_addr = fin->fin_src; 1480 rtalloc(&iproute); 1481 if (iproute.ro_rt == NULL) 1482 return 0; 1483 rc = (fin->fin_ifp == iproute.ro_rt->rt_ifp); 1484 RTFREE(iproute.ro_rt); 1485 #endif 1486 return rc; 1487 } 1488 1489 1490 /* 1491 * return the first IP Address associated with an interface 1492 */ 1493 int 1494 ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr, 1495 i6addr_t *inp, i6addr_t *inpmask) 1496 { 1497 #ifdef USE_INET6 1498 struct in6_addr *inp6 = NULL; 1499 #endif 1500 struct sockaddr *sock, *mask; 1501 struct sockaddr_in *sin; 1502 struct ifaddr *ifa; 1503 struct ifnet *ifp; 1504 1505 if ((ifptr == NULL) || (ifptr == (void *)-1)) 1506 return -1; 1507 1508 ifp = ifptr; 1509 mask = NULL; 1510 1511 if (v == 4) 1512 inp->in4.s_addr = 0; 1513 #ifdef USE_INET6 1514 else if (v == 6) 1515 bzero((char *)inp, sizeof(*inp)); 1516 #endif 1517 1518 ifa = IFADDR_FIRST(ifp); 1519 sock = ifa ? ifa->ifa_addr : NULL; 1520 while (sock != NULL && ifa != NULL) { 1521 sin = (struct sockaddr_in *)sock; 1522 if ((v == 4) && (sin->sin_family == AF_INET)) 1523 break; 1524 #ifdef USE_INET6 1525 if ((v == 6) && (sin->sin_family == AF_INET6)) { 1526 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr; 1527 if (!IN6_IS_ADDR_LINKLOCAL(inp6) && 1528 !IN6_IS_ADDR_LOOPBACK(inp6)) 1529 break; 1530 } 1531 #endif 1532 ifa = IFADDR_NEXT(ifa); 1533 if (ifa != NULL) 1534 sock = ifa->ifa_addr; 1535 } 1536 if (ifa == NULL || sock == NULL) 1537 return -1; 1538 1539 mask = ifa->ifa_netmask; 1540 if (atype == FRI_BROADCAST) 1541 sock = ifa->ifa_broadaddr; 1542 else if (atype == FRI_PEERADDR) 1543 sock = ifa->ifa_dstaddr; 1544 1545 #ifdef USE_INET6 1546 if (v == 6) 1547 return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock, 1548 (struct sockaddr_in6 *)mask, 1549 inp, inpmask); 1550 #endif 1551 return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock, 1552 (struct sockaddr_in *)mask, 1553 &inp->in4, &inpmask->in4); 1554 } 1555 1556 1557 u_32_t 1558 ipf_newisn(fr_info_t *fin) 1559 { 1560 #if __NetBSD_Version__ >= 105190000 /* 1.5T */ 1561 size_t asz; 1562 1563 if (fin->fin_v == 4) 1564 asz = sizeof(struct in_addr); 1565 else if (fin->fin_v == 6) 1566 asz = sizeof(fin->fin_src); 1567 else /* XXX: no way to return error */ 1568 return 0; 1569 #ifdef INET 1570 return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst, 1571 fin->fin_sport, fin->fin_dport, asz, 0); 1572 #else 1573 return ENOSYS; 1574 #endif 1575 #else 1576 static int iss_seq_off = 0; 1577 u_char hash[16]; 1578 u_32_t newiss; 1579 MD5_CTX ctx; 1580 1581 /* 1582 * Compute the base value of the ISS. It is a hash 1583 * of (saddr, sport, daddr, dport, secret). 1584 */ 1585 MD5Init(&ctx); 1586 1587 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 1588 sizeof(fin->fin_fi.fi_src)); 1589 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 1590 sizeof(fin->fin_fi.fi_dst)); 1591 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 1592 1593 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); 1594 1595 MD5Final(hash, &ctx); 1596 1597 memcpy(&newiss, hash, sizeof(newiss)); 1598 1599 /* 1600 * Now increment our "timer", and add it in to 1601 * the computed value. 1602 * 1603 * XXX Use `addin'? 1604 * XXX TCP_ISSINCR too large to use? 1605 */ 1606 iss_seq_off += 0x00010000; 1607 newiss += iss_seq_off; 1608 return newiss; 1609 #endif 1610 } 1611 1612 1613 /* ------------------------------------------------------------------------ */ 1614 /* Function: ipf_nextipid */ 1615 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 1616 /* Parameters: fin(I) - pointer to packet information */ 1617 /* */ 1618 /* Returns the next IPv4 ID to use for this packet. */ 1619 /* ------------------------------------------------------------------------ */ 1620 u_short 1621 ipf_nextipid(fr_info_t *fin) 1622 { 1623 #ifdef USE_MUTEXES 1624 ipf_main_softc_t *softc = fin->fin_main_soft; 1625 #endif 1626 u_short id; 1627 1628 MUTEX_ENTER(&softc->ipf_rw); 1629 id = ipid++; 1630 MUTEX_EXIT(&softc->ipf_rw); 1631 1632 return id; 1633 } 1634 1635 1636 EXTERN_INLINE int 1637 ipf_checkv4sum(fr_info_t *fin) 1638 { 1639 #ifdef M_CSUM_TCP_UDP_BAD 1640 int manual, pflag, cflags, active; 1641 mb_t *m; 1642 1643 if ((fin->fin_flx & FI_NOCKSUM) != 0) 1644 return 0; 1645 1646 if ((fin->fin_flx & FI_SHORT) != 0) 1647 return 1; 1648 1649 if (fin->fin_cksum != FI_CK_NEEDED) 1650 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1651 1652 manual = 0; 1653 m = fin->fin_m; 1654 if (m == NULL) { 1655 manual = 1; 1656 goto skipauto; 1657 } 1658 1659 switch (fin->fin_p) 1660 { 1661 case IPPROTO_UDP : 1662 pflag = M_CSUM_UDPv4; 1663 break; 1664 case IPPROTO_TCP : 1665 pflag = M_CSUM_TCPv4; 1666 break; 1667 default : 1668 pflag = 0; 1669 manual = 1; 1670 break; 1671 } 1672 1673 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; 1674 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; 1675 cflags = m->m_pkthdr.csum_flags & active; 1676 1677 if (pflag != 0) { 1678 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { 1679 fin->fin_flx |= FI_BAD; 1680 fin->fin_cksum = FI_CK_BAD; 1681 } else if (cflags == (pflag | M_CSUM_DATA)) { 1682 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) { 1683 fin->fin_flx |= FI_BAD; 1684 fin->fin_cksum = FI_CK_BAD; 1685 } else { 1686 fin->fin_cksum = FI_CK_SUMOK; 1687 } 1688 } else if (cflags == pflag) { 1689 fin->fin_cksum = FI_CK_SUMOK; 1690 } else { 1691 manual = 1; 1692 } 1693 } 1694 skipauto: 1695 if (manual != 0) { 1696 if (ipf_checkl4sum(fin) == -1) { 1697 fin->fin_flx |= FI_BAD; 1698 return -1; 1699 } 1700 } 1701 #else 1702 if (ipf_checkl4sum(fin) == -1) { 1703 fin->fin_flx |= FI_BAD; 1704 return -1; 1705 } 1706 #endif 1707 return 0; 1708 } 1709 1710 1711 #ifdef USE_INET6 1712 EXTERN_INLINE int 1713 ipf_checkv6sum(fr_info_t *fin) 1714 { 1715 # ifdef M_CSUM_TCP_UDP_BAD 1716 int manual, pflag, cflags, active; 1717 mb_t *m; 1718 1719 if ((fin->fin_flx & FI_NOCKSUM) != 0) 1720 return 0; 1721 1722 if ((fin->fin_flx & FI_SHORT) != 0) 1723 return 1; 1724 1725 if (fin->fin_cksum != FI_CK_SUMOK) 1726 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1; 1727 1728 1729 manual = 0; 1730 m = fin->fin_m; 1731 1732 switch (fin->fin_p) 1733 { 1734 case IPPROTO_UDP : 1735 pflag = M_CSUM_UDPv6; 1736 break; 1737 case IPPROTO_TCP : 1738 pflag = M_CSUM_TCPv6; 1739 break; 1740 default : 1741 pflag = 0; 1742 manual = 1; 1743 break; 1744 } 1745 1746 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag; 1747 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA; 1748 cflags = m->m_pkthdr.csum_flags & active; 1749 1750 if (pflag != 0) { 1751 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) { 1752 fin->fin_flx |= FI_BAD; 1753 } else if (cflags == (pflag | M_CSUM_DATA)) { 1754 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) 1755 fin->fin_flx |= FI_BAD; 1756 } else if (cflags == pflag) { 1757 ; 1758 } else { 1759 manual = 1; 1760 } 1761 } 1762 if (manual != 0) { 1763 if (ipf_checkl4sum(fin) == -1) { 1764 fin->fin_flx |= FI_BAD; 1765 return -1; 1766 } 1767 } 1768 # else 1769 if (ipf_checkl4sum(fin) == -1) { 1770 fin->fin_flx |= FI_BAD; 1771 return -1; 1772 } 1773 # endif 1774 return 0; 1775 } 1776 #endif /* USE_INET6 */ 1777 1778 1779 size_t 1780 mbufchainlen(struct mbuf *m0) 1781 { 1782 size_t len; 1783 1784 if ((m0->m_flags & M_PKTHDR) != 0) { 1785 len = m0->m_pkthdr.len; 1786 } else { 1787 struct mbuf *m; 1788 1789 for (m = m0, len = 0; m != NULL; m = m->m_next) 1790 len += m->m_len; 1791 } 1792 return len; 1793 } 1794 1795 1796 /* ------------------------------------------------------------------------ */ 1797 /* Function: ipf_pullup */ 1798 /* Returns: NULL == pullup failed, else pointer to protocol header */ 1799 /* Parameters: xmin(I)- pointer to buffer where data packet starts */ 1800 /* fin(I) - pointer to packet information */ 1801 /* len(I) - number of bytes to pullup */ 1802 /* */ 1803 /* Attempt to move at least len bytes (from the start of the buffer) into a */ 1804 /* single buffer for ease of access. Operating system native functions are */ 1805 /* used to manage buffers - if necessary. If the entire packet ends up in */ 1806 /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */ 1807 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */ 1808 /* and ONLY if the pullup succeeds. */ 1809 /* */ 1810 /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */ 1811 /* of buffers that starts at *fin->fin_mp. */ 1812 /* ------------------------------------------------------------------------ */ 1813 void * 1814 ipf_pullup(mb_t *xmin, fr_info_t *fin, int len) 1815 { 1816 int dpoff, ipoff; 1817 mb_t *m = xmin; 1818 char *ip; 1819 1820 if (m == NULL) 1821 return NULL; 1822 1823 ip = (char *)fin->fin_ip; 1824 if ((fin->fin_flx & FI_COALESCE) != 0) 1825 return ip; 1826 1827 ipoff = fin->fin_ipoff; 1828 if (fin->fin_dp != NULL) 1829 dpoff = (char *)fin->fin_dp - (char *)ip; 1830 else 1831 dpoff = 0; 1832 1833 if (M_LEN(m) < len) { 1834 mb_t *n = *fin->fin_mp; 1835 /* 1836 * Assume that M_PKTHDR is set and just work with what is left 1837 * rather than check.. 1838 * Should not make any real difference, anyway. 1839 */ 1840 if (m != n) { 1841 /* 1842 * Record the mbuf that points to the mbuf that we're 1843 * about to go to work on so that we can update the 1844 * m_next appropriately later. 1845 */ 1846 for (; n->m_next != m; n = n->m_next) 1847 ; 1848 } else { 1849 n = NULL; 1850 } 1851 1852 #ifdef MHLEN 1853 if (len > MHLEN) 1854 #else 1855 if (len > MLEN) 1856 #endif 1857 { 1858 #ifdef HAVE_M_PULLDOWN 1859 if (m_pulldown(m, 0, len, NULL) == NULL) 1860 m = NULL; 1861 #else 1862 FREE_MB_T(*fin->fin_mp); 1863 m = NULL; 1864 n = NULL; 1865 #endif 1866 } else 1867 { 1868 m = m_pullup(m, len); 1869 } 1870 if (n != NULL) 1871 n->m_next = m; 1872 if (m == NULL) { 1873 /* 1874 * When n is non-NULL, it indicates that m pointed to 1875 * a sub-chain (tail) of the mbuf and that the head 1876 * of this chain has not yet been free'd. 1877 */ 1878 if (n != NULL) { 1879 FREE_MB_T(*fin->fin_mp); 1880 } 1881 1882 *fin->fin_mp = NULL; 1883 fin->fin_m = NULL; 1884 return NULL; 1885 } 1886 1887 if (n == NULL) 1888 *fin->fin_mp = m; 1889 1890 while (M_LEN(m) == 0) { 1891 m = m->m_next; 1892 } 1893 fin->fin_m = m; 1894 ip = MTOD(m, char *) + ipoff; 1895 1896 fin->fin_ip = (ip_t *)ip; 1897 if (fin->fin_dp != NULL) 1898 fin->fin_dp = (char *)fin->fin_ip + dpoff; 1899 if (fin->fin_fraghdr != NULL) 1900 fin->fin_fraghdr = (char *)ip + 1901 ((char *)fin->fin_fraghdr - 1902 (char *)fin->fin_ip); 1903 } 1904 1905 if (len == fin->fin_plen) 1906 fin->fin_flx |= FI_COALESCE; 1907 return ip; 1908 } 1909 1910 1911 int 1912 ipf_inject(fr_info_t *fin, mb_t *m) 1913 { 1914 int error; 1915 1916 if (fin->fin_out == 0) { 1917 struct ifqueue *ifq; 1918 1919 ifq = &ipintrq; 1920 1921 if (IF_QFULL(ifq)) { 1922 IF_DROP(ifq); 1923 FREE_MB_T(m); 1924 error = ENOBUFS; 1925 } else { 1926 IF_ENQUEUE(ifq, m); 1927 error = 0; 1928 } 1929 } else { 1930 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); 1931 } 1932 1933 return error; 1934 } 1935 1936 1937 u_32_t 1938 ipf_random(void) 1939 { 1940 int number; 1941 1942 #ifdef _CPRNG_H 1943 number = cprng_fast32(); 1944 #else 1945 number = arc4random(); 1946 #endif 1947 return number; 1948 } 1949 1950 1951 /* 1952 * routines below for saving IP headers to buffer 1953 */ 1954 static int ipfopen(dev_t dev, int flags 1955 #if (NetBSD >= 199511) 1956 , int devtype, PROC_T *p 1957 #endif 1958 ) 1959 { 1960 u_int unit = GET_MINOR(dev); 1961 int error; 1962 1963 if (IPL_LOGMAX < unit) { 1964 error = ENXIO; 1965 } else { 1966 switch (unit) 1967 { 1968 case IPL_LOGIPF : 1969 case IPL_LOGNAT : 1970 case IPL_LOGSTATE : 1971 case IPL_LOGAUTH : 1972 case IPL_LOGLOOKUP : 1973 case IPL_LOGSYNC : 1974 #ifdef IPFILTER_SCAN 1975 case IPL_LOGSCAN : 1976 #endif 1977 error = 0; 1978 break; 1979 default : 1980 error = ENXIO; 1981 break; 1982 } 1983 } 1984 return error; 1985 } 1986 1987 1988 static int ipfclose(dev_t dev, int flags 1989 #if (NetBSD >= 199511) 1990 , int devtype, PROC_T *p 1991 #endif 1992 ) 1993 { 1994 u_int unit = GET_MINOR(dev); 1995 1996 if (IPL_LOGMAX < unit) 1997 unit = ENXIO; 1998 else 1999 unit = 0; 2000 return unit; 2001 } 2002 2003 /* 2004 * ipfread/ipflog 2005 * both of these must operate with at least splnet() lest they be 2006 * called during packet processing and cause an inconsistancy to appear in 2007 * the filter lists. 2008 */ 2009 static int ipfread(dev_t dev, struct uio *uio, int ioflag) 2010 { 2011 2012 if (ipfmain.ipf_running < 1) { 2013 ipfmain.ipf_interror = 130006; 2014 return EIO; 2015 } 2016 2017 if (GET_MINOR(dev) == IPL_LOGSYNC) 2018 return ipf_sync_read(&ipfmain, uio); 2019 2020 #ifdef IPFILTER_LOG 2021 return ipf_log_read(&ipfmain, GET_MINOR(dev), uio); 2022 #else 2023 ipfmain.ipf_interror = 130007; 2024 return ENXIO; 2025 #endif 2026 } 2027 2028 2029 /* 2030 * ipfwrite 2031 * both of these must operate with at least splnet() lest they be 2032 * called during packet processing and cause an inconsistancy to appear in 2033 * the filter lists. 2034 */ 2035 static int ipfwrite(dev_t dev, struct uio *uio, int ioflag) 2036 { 2037 2038 if (ipfmain.ipf_running < 1) { 2039 ipfmain.ipf_interror = 130008; 2040 return EIO; 2041 } 2042 2043 if (GET_MINOR(dev) == IPL_LOGSYNC) 2044 return ipf_sync_write(&ipfmain, uio); 2045 ipfmain.ipf_interror = 130009; 2046 return ENXIO; 2047 } 2048 2049 2050 static int ipfpoll(dev_t dev, int events, PROC_T *p) 2051 { 2052 u_int unit = GET_MINOR(dev); 2053 int revents = 0; 2054 2055 if (IPL_LOGMAX < unit) { 2056 ipfmain.ipf_interror = 130010; 2057 return ENXIO; 2058 } 2059 2060 switch (unit) 2061 { 2062 case IPL_LOGIPF : 2063 case IPL_LOGNAT : 2064 case IPL_LOGSTATE : 2065 #ifdef IPFILTER_LOG 2066 if ((events & (POLLIN | POLLRDNORM)) && 2067 ipf_log_canread(&ipfmain, unit)) 2068 revents |= events & (POLLIN | POLLRDNORM); 2069 #endif 2070 break; 2071 case IPL_LOGAUTH : 2072 if ((events & (POLLIN | POLLRDNORM)) && 2073 ipf_auth_waiting(&ipfmain)) 2074 revents |= events & (POLLIN | POLLRDNORM); 2075 break; 2076 case IPL_LOGSYNC : 2077 if ((events & (POLLIN | POLLRDNORM)) && 2078 ipf_sync_canread(&ipfmain)) 2079 revents |= events & (POLLIN | POLLRDNORM); 2080 if ((events & (POLLOUT | POLLWRNORM)) && 2081 ipf_sync_canwrite(&ipfmain)) 2082 revents |= events & (POLLOUT | POLLWRNORM); 2083 break; 2084 case IPL_LOGSCAN : 2085 case IPL_LOGLOOKUP : 2086 default : 2087 break; 2088 } 2089 2090 if ((revents == 0) && (((events & (POLLIN|POLLRDNORM)) != 0))) 2091 selrecord(p, &ipfmain.ipf_selwait[unit]); 2092 return revents; 2093 } 2094 2095 u_int 2096 ipf_pcksum(fr_info_t *fin, int hlen, u_int sum) 2097 { 2098 struct mbuf *m; 2099 u_int sum2; 2100 int off; 2101 2102 m = fin->fin_m; 2103 off = (char *)fin->fin_dp - (char *)fin->fin_ip; 2104 m->m_data += hlen; 2105 m->m_len -= hlen; 2106 sum2 = in_cksum(fin->fin_m, fin->fin_plen - off); 2107 m->m_len += hlen; 2108 m->m_data -= hlen; 2109 2110 /* 2111 * Both sum and sum2 are partial sums, so combine them together. 2112 */ 2113 sum += ~sum2 & 0xffff; 2114 while (sum > 0xffff) 2115 sum = (sum & 0xffff) + (sum >> 16); 2116 sum2 = ~sum & 0xffff; 2117 return sum2; 2118 } 2119