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