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