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