1145522Sdarrenr/*	$FreeBSD$	*/
2145522Sdarrenr
354221Sguido/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
554221Sguido *
654221Sguido * $FreeBSD$
7145522Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
854221Sguido */
954221Sguido
1060857Sdarrenr
1154221Sguido#include <sys/param.h>
1254221Sguido#include <sys/systm.h>
1354221Sguido#include <sys/kernel.h>
1454221Sguido#include <sys/module.h>
1554221Sguido#include <sys/conf.h>
1654221Sguido#include <sys/socket.h>
1754221Sguido#include <sys/sysctl.h>
18161356Sguido#include <sys/select.h>
19161356Sguido#if __FreeBSD_version >= 500000
20161356Sguido# include <sys/selinfo.h>
21255332Scy#endif
2254221Sguido#include <net/if.h>
2354221Sguido#include <netinet/in_systm.h>
2454221Sguido#include <netinet/in.h>
2554221Sguido
2654221Sguido
27255332Scy#include "netinet/ipl.h"
28255332Scy#include "netinet/ip_compat.h"
29255332Scy#include "netinet/ip_fil.h"
30255332Scy#include "netinet/ip_state.h"
31255332Scy#include "netinet/ip_nat.h"
32255332Scy#include "netinet/ip_auth.h"
33255332Scy#include "netinet/ip_frag.h"
34255332Scy#include "netinet/ip_sync.h"
3554221Sguido
36255332Scyextern ipf_main_softc_t ipfmain;
37255332Scy
38145522Sdarrenr#if __FreeBSD_version >= 502116
39145522Sdarrenrstatic struct cdev *ipf_devs[IPL_LOGSIZE];
40145522Sdarrenr#else
41145522Sdarrenrstatic dev_t ipf_devs[IPL_LOGSIZE];
42145522Sdarrenr#endif
4354221Sguido
44145522Sdarrenrstatic int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
45145522Sdarrenrstatic int ipf_modload(void);
46145522Sdarrenrstatic int ipf_modunload(void);
47145522Sdarrenr
48255332Scy#if (__FreeBSD_version >= 500024)
49255332Scy# if (__FreeBSD_version >= 502116)
50255332Scystatic	int	ipfopen __P((struct cdev*, int, int, struct thread *));
51255332Scystatic	int	ipfclose __P((struct cdev*, int, int, struct thread *));
52255332Scy# else
53255332Scystatic	int	ipfopen __P((dev_t, int, int, struct thread *));
54255332Scystatic	int	ipfclose __P((dev_t, int, int, struct thread *));
55255332Scy# endif /* __FreeBSD_version >= 502116 */
56255332Scy#else
57255332Scystatic	int	ipfopen __P((dev_t, int, int, struct proc *));
58255332Scystatic	int	ipfclose __P((dev_t, int, int, struct proc *));
59255332Scy#endif
60255332Scy#if (__FreeBSD_version >= 502116)
61255332Scystatic	int	ipfread __P((struct cdev*, struct uio *, int));
62255332Scystatic	int	ipfwrite __P((struct cdev*, struct uio *, int));
63255332Scy#else
64255332Scystatic	int	ipfread __P((dev_t, struct uio *, int));
65255332Scystatic	int	ipfwrite __P((dev_t, struct uio *, int));
66255332Scy#endif /* __FreeBSD_version >= 502116 */
67255332Scy
68255332Scy
6954221SguidoSYSCTL_DECL(_net_inet);
70145522Sdarrenr#define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
71145522Sdarrenr	SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
72145522Sdarrenr		   ptr, val, sysctl_ipf_int, "I", descr);
73145522Sdarrenr#define	CTLFLAG_OFF	0x00800000	/* IPFilter must be disabled */
74145522Sdarrenr#define	CTLFLAG_RWO	(CTLFLAG_RW|CTLFLAG_OFF)
7554221SguidoSYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
76255756ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipfmain.ipf_flags, 0, "");
77255756ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipfmain.ipf_pass, 0, "");
78255756ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipfmain.ipf_active, 0, "");
79145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
80255756Scy	   &ipfmain.ipf_tcpidletimeout, 0, "");
81145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
82255756Scy	   &ipfmain.ipf_tcphalfclosed, 0, "");
83145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
84255756Scy	   &ipfmain.ipf_tcpclosewait, 0, "");
85145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
86255756Scy	   &ipfmain.ipf_tcplastack, 0, "");
87145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
88255756Scy	   &ipfmain.ipf_tcptimeout, 0, "");
89145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
90255756Scy	   &ipfmain.ipf_tcpclosed, 0, "");
91145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
92255756Scy	   &ipfmain.ipf_udptimeout, 0, "");
93145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
94255756Scy	   &ipfmain.ipf_udpacktimeout, 0, "");
95145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
96255756Scy	   &ipfmain.ipf_icmptimeout, 0, "");
97255756Scy#if 0
98255756Scy/* this needs to be resolved at compile time */
99145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
100255756Scy	   &((ipf_nat_softc_t *)ipfmain.ipf_nat_soft)->ipf_nat_defage, 0, "");
101145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
102255332Scy	   &ipf_ipfrttl, 0, "");
103255756Scy#endif
104255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD,
105255756Scy	   &ipfmain.ipf_running, 0, "");
106255756Scy#if 0
107145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
108255756Scy	   &ipfmain.ipf_state_soft)->ipf_state_size, 0, "");
109145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
110255756Scy	   &(ipfmain.ipf_state_soft)->ipf_state_max, 0, "");
111145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO,
112255756Scy	   &(ipfmain.ipf_nat_soft)->ipf_nat_table_sz, 0, "");
113145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO,
114255756Scy	   &(ipfmain.ipf_nat_soft)->ipf_nat_maprules_sz, 0, "");
115145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO,
116255756Scy	   &(ipfmain.ipf_nat_soft)->ipf_nat_rdrrules_sz, 0, "");
117145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO,
118255756Scy	   &(ipfmain.ipf_nat_soft)->ipf_nat_hostmap_sz, 0, "");
119145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
120255332Scy	   &ipf_auth_size, 0, "");
121145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
122255332Scy	   &ipf_auth_used, 0, "");
123145522SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
124255332Scy	   &ipf_auth_defaultage, 0, "");
125255332Scy#endif
126255756ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipfmain.ipf_chksrc, 0, "");
127255756ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipfmain.ipf_minttl, 0, "");
12854221Sguido
129145522Sdarrenr#define CDEV_MAJOR 79
130170268Sdarrenr#include <sys/poll.h>
131170268Sdarrenr#if __FreeBSD_version >= 500043
132161356Sguido# include <sys/select.h>
133255332Scystatic int ipfpoll(struct cdev *dev, int events, struct thread *td);
134161356Sguido
135255332Scystatic struct cdevsw ipf_cdevsw = {
136255332Scy#if __FreeBSD_version >= 502103
137126080Sphk	.d_version =	D_VERSION,
138145522Sdarrenr	.d_flags =	0,	/* D_NEEDGIANT - Should be SMP safe */
139255332Scy#endif
140255332Scy	.d_open =	ipfopen,
141255332Scy	.d_close =	ipfclose,
142255332Scy	.d_read =	ipfread,
143255332Scy	.d_write =	ipfwrite,
144255332Scy	.d_ioctl =	ipfioctl,
145255332Scy	.d_poll =	ipfpoll,
146255332Scy	.d_name =	"ipf",
147255332Scy#if __FreeBSD_version < 600000
148145522Sdarrenr	.d_maj =	CDEV_MAJOR,
149255332Scy#endif
15054221Sguido};
151145522Sdarrenr#else
152255332Scystatic int ipfpoll(dev_t dev, int events, struct proc *td);
153170268Sdarrenr
154255332Scystatic struct cdevsw ipf_cdevsw = {
155255332Scy	/* open */	ipfopen,
156255332Scy	/* close */	ipfclose,
157255332Scy	/* read */	ipfread,
158255332Scy	/* write */	ipfwrite,
159255332Scy	/* ioctl */	ipfioctl,
160255332Scy	/* poll */	ipfpoll,
161145522Sdarrenr	/* mmap */	nommap,
162145522Sdarrenr	/* strategy */	nostrategy,
163255332Scy	/* name */	"ipf",
164145522Sdarrenr	/* maj */	CDEV_MAJOR,
165145522Sdarrenr	/* dump */	nodump,
166145522Sdarrenr	/* psize */	nopsize,
167145522Sdarrenr	/* flags */	0,
168145522Sdarrenr# if (__FreeBSD_version < 500043)
169145522Sdarrenr	/* bmaj */	-1,
170145522Sdarrenr# endif
171255332Scy# if (__FreeBSD_version >= 430000)
172145522Sdarrenr	/* kqfilter */	NULL
173170268Sdarrenr# endif
174145522Sdarrenr};
175139255Sdarrenr#endif
176139255Sdarrenr
177145522Sdarrenrstatic char *ipf_devfiles[] = {	IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
178145522Sdarrenr				IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
179145522Sdarrenr
180145522Sdarrenr
18154221Sguidostatic int
18254221Sguidoipfilter_modevent(module_t mod, int type, void *unused)
18354221Sguido{
184145522Sdarrenr	int error = 0;
18554221Sguido
186145522Sdarrenr	switch (type)
187145522Sdarrenr	{
18854221Sguido	case MOD_LOAD :
189145522Sdarrenr		error = ipf_modload();
190145522Sdarrenr		break;
19160857Sdarrenr
192145522Sdarrenr	case MOD_UNLOAD :
193145522Sdarrenr		error = ipf_modunload();
194145522Sdarrenr		break;
195145522Sdarrenr	default:
196145522Sdarrenr		error = EINVAL;
197145522Sdarrenr		break;
198145522Sdarrenr	}
199145522Sdarrenr	return error;
200145522Sdarrenr}
20154221Sguido
20254221Sguido
203145522Sdarrenrstatic int
204145522Sdarrenripf_modload()
205145522Sdarrenr{
206145522Sdarrenr	char *defpass, *c, *str;
207145522Sdarrenr	int i, j, error;
20854221Sguido
209255332Scy	if (ipf_load_all() != 0)
210255332Scy		return EIO;
211170268Sdarrenr
212255332Scy	if (ipf_create_all(&ipfmain) == NULL)
213255332Scy		return EIO;
214255332Scy
215255332Scy	error = ipfattach(&ipfmain);
216255332Scy	if (error)
217145522Sdarrenr		return error;
21854221Sguido
219145522Sdarrenr	for (i = 0; i < IPL_LOGSIZE; i++)
220145522Sdarrenr		ipf_devs[i] = NULL;
221145522Sdarrenr
222145522Sdarrenr	for (i = 0; (str = ipf_devfiles[i]); i++) {
22354221Sguido		c = NULL;
224145522Sdarrenr		for(j = strlen(str); j > 0; j--)
225145522Sdarrenr			if (str[j] == '/') {
226145522Sdarrenr				c = str + j + 1;
22754221Sguido				break;
22854221Sguido			}
22954221Sguido		if (!c)
230145522Sdarrenr			c = str;
231255332Scy		ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
232145522Sdarrenr	}
23354221Sguido
234172776Sdarrenr	error = ipf_pfil_hook();
235172776Sdarrenr	if (error != 0)
236172776Sdarrenr		return error;
237172776Sdarrenr	ipf_event_reg();
238172776Sdarrenr
239255332Scy	if (FR_ISPASS(ipfmain.ipf_pass))
240145522Sdarrenr		defpass = "pass";
241255332Scy	else if (FR_ISBLOCK(ipfmain.ipf_pass))
242145522Sdarrenr		defpass = "block";
243255332Scy	else
244145522Sdarrenr		defpass = "no-match -> block";
245145522Sdarrenr
246145522Sdarrenr	printf("%s initialized.  Default = %s all, Logging = %s%s\n",
247255332Scy		ipfilter_version, defpass,
248145522Sdarrenr#ifdef IPFILTER_LOG
249145522Sdarrenr		"enabled",
250145522Sdarrenr#else
251145522Sdarrenr		"disabled",
252145522Sdarrenr#endif
253145522Sdarrenr#ifdef IPFILTER_COMPILED
254145522Sdarrenr		" (COMPILED)"
255145522Sdarrenr#else
256145522Sdarrenr		""
257145522Sdarrenr#endif
258255332Scy		);
259145522Sdarrenr	return 0;
260145522Sdarrenr}
261145522Sdarrenr
262145522Sdarrenr
263145522Sdarrenrstatic int
264145522Sdarrenripf_modunload()
265145522Sdarrenr{
266145522Sdarrenr	int error, i;
267145522Sdarrenr
268255332Scy	if (ipfmain.ipf_refcnt)
269145522Sdarrenr		return EBUSY;
270145522Sdarrenr
271255332Scy	error = ipf_pfil_unhook();
272255332Scy	if (error != 0)
273255332Scy		return error;
274255332Scy
275255332Scy	if (ipfmain.ipf_running >= 0) {
276255332Scy		error = ipfdetach(&ipfmain);
277145522Sdarrenr		if (error != 0)
278145522Sdarrenr			return error;
279255332Scy
280255332Scy		ipf_destroy_all(&ipfmain);
281255332Scy		ipf_unload_all();
282145522Sdarrenr	} else
283145522Sdarrenr		error = 0;
284145522Sdarrenr
285255332Scy	ipfmain.ipf_running = -2;
286170268Sdarrenr
287145522Sdarrenr	for (i = 0; ipf_devfiles[i]; i++) {
288145522Sdarrenr		if (ipf_devs[i] != NULL)
289145522Sdarrenr			destroy_dev(ipf_devs[i]);
29054221Sguido	}
291145522Sdarrenr
292145522Sdarrenr	printf("%s unloaded\n", ipfilter_version);
293145522Sdarrenr
29454221Sguido	return error;
29554221Sguido}
29654221Sguido
297145522Sdarrenr
29854221Sguidostatic moduledata_t ipfiltermod = {
299145522Sdarrenr	"ipfilter",
30054221Sguido	ipfilter_modevent,
301241394Skevlo	0
30254221Sguido};
303145522Sdarrenr
304145522Sdarrenr
30554221SguidoDECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
306145522Sdarrenr#ifdef	MODULE_VERSION
307145522SdarrenrMODULE_VERSION(ipfilter, 1);
308145522Sdarrenr#endif
309145522Sdarrenr
310145522Sdarrenr
311145522Sdarrenr#ifdef SYSCTL_IPF
312145522Sdarrenrint
313145522Sdarrenrsysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
314145522Sdarrenr{
315145522Sdarrenr	int error = 0;
316145522Sdarrenr
317145522Sdarrenr	if (arg1)
318145522Sdarrenr		error = SYSCTL_OUT(req, arg1, sizeof(int));
319145522Sdarrenr	else
320145522Sdarrenr		error = SYSCTL_OUT(req, &arg2, sizeof(int));
321145522Sdarrenr
322145522Sdarrenr	if (error || !req->newptr)
323145522Sdarrenr		return (error);
324145522Sdarrenr
325145522Sdarrenr	if (!arg1)
326145522Sdarrenr		error = EPERM;
327145522Sdarrenr	else {
328255332Scy		if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0))
329145522Sdarrenr			error = EBUSY;
330145522Sdarrenr		else
331145522Sdarrenr			error = SYSCTL_IN(req, arg1, sizeof(int));
332145522Sdarrenr	}
333145522Sdarrenr	return (error);
334145522Sdarrenr}
335145522Sdarrenr#endif
336161356Sguido
337161356Sguido
338161356Sguidostatic int
339170268Sdarrenr#if __FreeBSD_version >= 500043
340255332Scyipfpoll(struct cdev *dev, int events, struct thread *td)
341170268Sdarrenr#else
342255332Scyipfpoll(dev_t dev, int events, struct proc *td)
343170268Sdarrenr#endif
344161356Sguido{
345255332Scy	int unit = GET_MINOR(dev);
346161356Sguido	int revents;
347161356Sguido
348255332Scy	if (unit < 0 || unit > IPL_LOGMAX)
349161356Sguido		return 0;
350161356Sguido
351161356Sguido	revents = 0;
352161356Sguido
353255332Scy	switch (unit)
354161356Sguido	{
355161356Sguido	case IPL_LOGIPF :
356161356Sguido	case IPL_LOGNAT :
357161356Sguido	case IPL_LOGSTATE :
358161356Sguido#ifdef IPFILTER_LOG
359255332Scy		if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit))
360161356Sguido			revents |= events & (POLLIN | POLLRDNORM);
361255332Scy#endif
362161356Sguido		break;
363161356Sguido	case IPL_LOGAUTH :
364255332Scy		if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain))
365161356Sguido			revents |= events & (POLLIN | POLLRDNORM);
366255332Scy		break;
367161356Sguido	case IPL_LOGSYNC :
368255332Scy		if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain))
369161356Sguido			revents |= events & (POLLIN | POLLRDNORM);
370255332Scy		if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain))
371161356Sguido			revents |= events & (POLLOUT | POLLWRNORM);
372161356Sguido		break;
373161356Sguido	case IPL_LOGSCAN :
374161356Sguido	case IPL_LOGLOOKUP :
375161356Sguido	default :
376161356Sguido		break;
377161356Sguido	}
378161356Sguido
379161356Sguido	if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
380255332Scy		selrecord(td, &ipfmain.ipf_selwait[unit]);
381161356Sguido
382161356Sguido	return revents;
383161356Sguido}
384255332Scy
385255332Scy
386255332Scy/*
387255332Scy * routines below for saving IP headers to buffer
388255332Scy */
389255332Scystatic int ipfopen(dev, flags
390255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
391255332Scy, devtype, p)
392255332Scy	int devtype;
393255332Scy# if (__FreeBSD_version >= 500024)
394255332Scy	struct thread *p;
395255332Scy# else
396255332Scy	struct proc *p;
397255332Scy# endif /* __FreeBSD_version >= 500024 */
398255332Scy#else
399255332Scy)
400255332Scy#endif
401255332Scy#if (__FreeBSD_version >= 502116)
402255332Scy	struct cdev *dev;
403255332Scy#else
404255332Scy	dev_t dev;
405255332Scy#endif
406255332Scy	int flags;
407255332Scy{
408255332Scy	int unit = GET_MINOR(dev);
409255332Scy	int error;
410255332Scy
411255332Scy	if (IPL_LOGMAX < unit)
412255332Scy		error = ENXIO;
413255332Scy	else {
414255332Scy		switch (unit)
415255332Scy		{
416255332Scy		case IPL_LOGIPF :
417255332Scy		case IPL_LOGNAT :
418255332Scy		case IPL_LOGSTATE :
419255332Scy		case IPL_LOGAUTH :
420255332Scy		case IPL_LOGLOOKUP :
421255332Scy		case IPL_LOGSYNC :
422255332Scy#ifdef IPFILTER_SCAN
423255332Scy		case IPL_LOGSCAN :
424255332Scy#endif
425255332Scy			error = 0;
426255332Scy			break;
427255332Scy		default :
428255332Scy			error = ENXIO;
429255332Scy			break;
430255332Scy		}
431255332Scy	}
432255332Scy	return error;
433255332Scy}
434255332Scy
435255332Scy
436255332Scystatic int ipfclose(dev, flags
437255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
438255332Scy, devtype, p)
439255332Scy	int devtype;
440255332Scy# if (__FreeBSD_version >= 500024)
441255332Scy	struct thread *p;
442255332Scy# else
443255332Scy	struct proc *p;
444255332Scy# endif /* __FreeBSD_version >= 500024 */
445255332Scy#else
446255332Scy)
447255332Scy#endif
448255332Scy#if (__FreeBSD_version >= 502116)
449255332Scy	struct cdev *dev;
450255332Scy#else
451255332Scy	dev_t dev;
452255332Scy#endif
453255332Scy	int flags;
454255332Scy{
455255332Scy	int	unit = GET_MINOR(dev);
456255332Scy
457255332Scy	if (IPL_LOGMAX < unit)
458255332Scy		unit = ENXIO;
459255332Scy	else
460255332Scy		unit = 0;
461255332Scy	return unit;
462255332Scy}
463255332Scy
464255332Scy/*
465255332Scy * ipfread/ipflog
466255332Scy * both of these must operate with at least splnet() lest they be
467255332Scy * called during packet processing and cause an inconsistancy to appear in
468255332Scy * the filter lists.
469255332Scy */
470255332Scy#if (BSD >= 199306)
471255332Scystatic int ipfread(dev, uio, ioflag)
472255332Scy	int ioflag;
473255332Scy#else
474255332Scystatic int ipfread(dev, uio)
475255332Scy#endif
476255332Scy#if (__FreeBSD_version >= 502116)
477255332Scy	struct cdev *dev;
478255332Scy#else
479255332Scy	dev_t dev;
480255332Scy#endif
481255332Scy	struct uio *uio;
482255332Scy{
483255332Scy	int	unit = GET_MINOR(dev);
484255332Scy
485255332Scy	if (unit < 0)
486255332Scy		return ENXIO;
487255332Scy
488255332Scy	if (ipfmain.ipf_running < 1)
489255332Scy		return EIO;
490255332Scy
491255332Scy	if (unit == IPL_LOGSYNC)
492255332Scy		return ipf_sync_read(&ipfmain, uio);
493255332Scy
494255332Scy#ifdef IPFILTER_LOG
495255332Scy	return ipf_log_read(&ipfmain, unit, uio);
496255332Scy#else
497255332Scy	return ENXIO;
498255332Scy#endif
499255332Scy}
500255332Scy
501255332Scy
502255332Scy/*
503255332Scy * ipfwrite
504255332Scy * both of these must operate with at least splnet() lest they be
505255332Scy * called during packet processing and cause an inconsistancy to appear in
506255332Scy * the filter lists.
507255332Scy */
508255332Scy#if (BSD >= 199306)
509255332Scystatic int ipfwrite(dev, uio, ioflag)
510255332Scy	int ioflag;
511255332Scy#else
512255332Scystatic int ipfwrite(dev, uio)
513255332Scy#endif
514255332Scy#if (__FreeBSD_version >= 502116)
515255332Scy	struct cdev *dev;
516255332Scy#else
517255332Scy	dev_t dev;
518255332Scy#endif
519255332Scy	struct uio *uio;
520255332Scy{
521255332Scy
522255332Scy	if (ipfmain.ipf_running < 1)
523255332Scy		return EIO;
524255332Scy
525255332Scy	if (GET_MINOR(dev) == IPL_LOGSYNC)
526255332Scy		return ipf_sync_write(&ipfmain, uio);
527255332Scy	return ENXIO;
528255332Scy}
529