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