1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
331183Speter/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
531183Speter *
680486Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
731183Speter */
831183Speter/*
931183Speter * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
1031183Speter * its own major char number! Way cool patch!
1131183Speter */
1231183Speter
1331183Speter
1431183Speter#include <sys/param.h>
1531183Speter
16145510Sdarrenr#ifdef	IPFILTER_LKM
17145510Sdarrenr# ifndef __FreeBSD_cc_version
18145510Sdarrenr#  include <osreldate.h>
19145510Sdarrenr# else
20145510Sdarrenr#  if __FreeBSD_cc_version < 430000
2198005Sdarrenr#   include <osreldate.h>
22145510Sdarrenr#  endif
23145510Sdarrenr# endif
24145510Sdarrenr# define	ACTUALLY_LKM_NOT_KERNEL
25145510Sdarrenr#else
26145510Sdarrenr# ifndef __FreeBSD_cc_version
27145510Sdarrenr#  include <sys/osreldate.h>
28145510Sdarrenr# else
29145510Sdarrenr#  if __FreeBSD_cc_version < 430000
3098005Sdarrenr#   include <sys/osreldate.h>
3198005Sdarrenr#  endif
3295419Sdarrenr# endif
3331183Speter#endif
3431183Speter#include <sys/systm.h>
3531183Speter#if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
3653024Sguido# ifndef ACTUALLY_LKM_NOT_KERNEL
3753024Sguido#  include "opt_devfs.h"
3853024Sguido# endif
3931183Speter# include <sys/conf.h>
4031183Speter# include <sys/kernel.h>
4131183Speter# ifdef DEVFS
4231183Speter#  include <sys/devfsext.h>
4331183Speter# endif /*DEVFS*/
4431183Speter#endif
4531183Speter#include <sys/conf.h>
4631183Speter#include <sys/file.h>
4753024Sguido#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
4853024Sguido# include <sys/lock.h>
4953024Sguido#endif
5031183Speter#include <sys/stat.h>
5131183Speter#include <sys/proc.h>
5231183Speter#include <sys/kernel.h>
5331183Speter#include <sys/vnode.h>
5431183Speter#include <sys/namei.h>
5531183Speter#include <sys/malloc.h>
5631183Speter#include <sys/mount.h>
5731183Speter#include <sys/exec.h>
5831183Speter#include <sys/mbuf.h>
5931183Speter#if	BSD >= 199506
6031183Speter# include <sys/sysctl.h>
6131183Speter#endif
6253024Sguido#if (__FreeBSD_version >= 300000)
6353024Sguido# include <sys/socket.h>
6453024Sguido#endif
6531183Speter#include <net/if.h>
6631183Speter#include <netinet/in_systm.h>
6731183Speter#include <netinet/in.h>
6831183Speter#include <netinet/ip.h>
6931183Speter#include <net/route.h>
7031183Speter#include <netinet/ip_var.h>
7131183Speter#include <netinet/tcp.h>
7231183Speter#include <netinet/tcpip.h>
7380486Sdarrenr#include <sys/sysent.h>
7431183Speter#include <sys/lkm.h>
7531183Speter#include "netinet/ipl.h"
7631183Speter#include "netinet/ip_compat.h"
7731183Speter#include "netinet/ip_fil.h"
7831183Speter#include "netinet/ip_state.h"
7931183Speter#include "netinet/ip_nat.h"
8031183Speter#include "netinet/ip_auth.h"
8131183Speter#include "netinet/ip_frag.h"
8231183Speter
8331183Speter
8431183Speter#if !defined(VOP_LEASE) && defined(LEASE_CHECK)
8531183Speter#define	VOP_LEASE	LEASE_CHECK
8631183Speter#endif
8731183Speter
8831183Speterint	xxxinit __P((struct lkm_table *, int, int));
8931183Speter
90145510Sdarrenr#ifdef  SYSCTL_OID
91145510Sdarrenrint sysctl_ipf_int SYSCTL_HANDLER_ARGS;
92145510Sdarrenr# define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
93145510Sdarrenr	SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
94145510Sdarrenr		   ptr, val, sysctl_ipf_int, "I", descr);
95145510Sdarrenr# define	CTLFLAG_OFF	0x00800000	/* IPFilter must be disabled */
96145510Sdarrenr# define	CTLFLAG_RWO	(CTLFLAG_RW|CTLFLAG_OFF)
9731183SpeterSYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
98255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipf_flags, 0, "");
99255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipf_pass, 0, "");
100255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipf_active, 0, "");
101255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipf_chksrc, 0, "");
102255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipf_minttl, 0, "");
103145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
104255332Scy	   &ipf_tcpidletimeout, 0, "");
105145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
106255332Scy	   &ipf_tcphalfclosed, 0, "");
107145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
108255332Scy	   &ipf_tcpclosewait, 0, "");
109145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
110255332Scy	   &ipf_tcplastack, 0, "");
111145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
112255332Scy	   &ipf_tcptimeout, 0, "");
113145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
114255332Scy	   &ipf_tcpclosed, 0, "");
115145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
116255332Scy	   &ipf_udptimeout, 0, "");
117145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
118255332Scy	   &ipf_icmptimeout, 0, "");
119145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
120255332Scy	   &ipf_defnatage, 0, "");
121145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
122255332Scy	   &ipf_ipfrttl, 0, "");
123255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD,
124255332Scy	   &ipf_running, 0, "");
125145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
126255332Scy	   &ipf_statesize, 0, "");
127145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
128255332Scy	   &ipf_statemax, 0, "");
129145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
130255332Scy	   &ipf_authsize, 0, "");
131145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
132255332Scy	   &ipf_authused, 0, "");
133145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
134255332Scy	   &ipf_defaultauthage, 0, "");
135145510SdarrenrSYSCTL_IPF(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW,
13660841Sdarrenr	   &ippr_ftp_pasvonly, 0, "");
13731183Speter#endif
13831183Speter
13934739Speter#ifdef DEVFS
140145510Sdarrenrstatic void *ipf_devfs[IPL_LOGSIZE];
14134739Speter#endif
14234739Speter
14331183Speter#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
144255332Scyint	ipf_major = 0;
14531183Speter
146255332Scystatic struct   cdevsw  ipfdevsw =
14753024Sguido{
148255332Scy	ipfopen,		/* open */
149255332Scy	ipfclose,		/* close */
150255332Scy	ipfread,		/* read */
151145510Sdarrenr	(void *)nullop,		/* write */
152255332Scy	ipfioctl,		/* ioctl */
153145510Sdarrenr	(void *)nullop,		/* stop */
154145510Sdarrenr	(void *)nullop,		/* reset */
155145510Sdarrenr	(void *)NULL,		/* tty */
156145510Sdarrenr	(void *)nullop,		/* select */
157145510Sdarrenr	(void *)nullop,		/* mmap */
158145510Sdarrenr	NULL			/* strategy */
15953024Sguido};
16053024Sguido
161255332ScyMOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipfdevsw);
16231183Speter
16331183Speterextern struct cdevsw cdevsw[];
16431183Speterextern int vd_unuseddev __P((void));
16531183Speterextern int nchrdev;
16631183Speter#else
16731183Speter
168255332Scystatic struct cdevsw ipf_cdevsw = {
169255332Scy	ipfopen,	ipfclose,	ipfread,	nowrite, /* 79 */
170255332Scy	ipfioctl,	nostop,		noreset,	nodevtotty,
17153024Sguido#if (__FreeBSD_version >= 300000)
172255332Scy	seltrue,	nommap,		nostrategy,	"ipf",
17353024Sguido#else
174255332Scy	noselect,	nommap,		nostrategy,	"ipf",
17553024Sguido#endif
17631183Speter	NULL,	-1
17731183Speter};
17831183Speter#endif
17931183Speter
180255332Scystatic void ipf_drvinit __P((void *));
18131183Speter
18253024Sguido#ifdef ACTUALLY_LKM_NOT_KERNEL
183255332Scystatic  int     if_ipf_unload __P((struct lkm_table *, int));
184255332Scystatic  int     if_ipf_load __P((struct lkm_table *, int));
185255332Scystatic  int     if_ipf_remove __P((void));
186255332Scystatic  int     ipf_major = CDEV_MAJOR;
18753024Sguido
188255332Scystatic int ipfaction __P((struct lkm_table *, int));
189145510Sdarrenrstatic char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH,
190145510Sdarrenr				IPL_SCAN, IPL_SYNC, IPL_POOL, NULL };
19131183Speter
19253024Sguidoextern	int	lkmenodev __P((void));
19331183Speter
194255332Scystatic int ipfaction(lkmtp, cmd)
195255332Scy	struct lkm_table *lkmtp;
196255332Scy	int cmd;
19731183Speter{
19831183Speter#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
199255332Scy	int i = ipf_major;
20031183Speter	struct lkm_dev *args = lkmtp->private.lkm_dev;
20131183Speter#endif
20231183Speter	int err = 0;
20331183Speter
20431183Speter	switch (cmd)
20531183Speter	{
20631183Speter	case LKM_E_LOAD :
20731183Speter		if (lkmexists(lkmtp))
20831183Speter			return EEXIST;
20931183Speter
21031183Speter#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
21131183Speter		for (i = 0; i < nchrdev; i++)
21231183Speter			if (cdevsw[i].d_open == lkmenodev ||
213255332Scy			    cdevsw[i].d_open == ipfopen)
21431183Speter				break;
21531183Speter		if (i == nchrdev) {
21631183Speter			printf("IP Filter: No free cdevsw slots\n");
21731183Speter			return ENODEV;
21831183Speter		}
21931183Speter
220255332Scy		ipf_major = i;
22131183Speter		args->lkm_offset = i;   /* slot in cdevsw[] */
22231183Speter#endif
223255332Scy		printf("IP Filter: loaded into slot %d\n", ipf_major);
224255332Scy		err = if_ipf_load(lkmtp, cmd);
22534739Speter		if (!err)
226255332Scy			ipf_drvinit((void *)NULL);
22734739Speter		return err;
22831183Speter		break;
22931183Speter	case LKM_E_UNLOAD :
230255332Scy		err = if_ipf_unload(lkmtp, cmd);
23134739Speter		if (!err) {
23231183Speter			printf("IP Filter: unloaded from slot %d\n",
233255332Scy				ipf_major);
23453024Sguido#ifdef	DEVFS
23534739Speter			if (ipf_devfs[IPL_LOGIPF])
23634739Speter				devfs_remove_dev(ipf_devfs[IPL_LOGIPF]);
23734739Speter			if (ipf_devfs[IPL_LOGNAT])
23834739Speter				devfs_remove_dev(ipf_devfs[IPL_LOGNAT]);
23934739Speter			if (ipf_devfs[IPL_LOGSTATE])
24034739Speter				devfs_remove_dev(ipf_devfs[IPL_LOGSTATE]);
24134739Speter			if (ipf_devfs[IPL_LOGAUTH])
24234739Speter				devfs_remove_dev(ipf_devfs[IPL_LOGAUTH]);
243145510Sdarrenr			if (ipf_devfs[IPL_LOGSCAN])
244145510Sdarrenr				devfs_remove_dev(ipf_devfs[IPL_LOGSCAN]);
245145510Sdarrenr			if (ipf_devfs[IPL_LOGSYNC])
246145510Sdarrenr				devfs_remove_dev(ipf_devfs[IPL_LOGSYNC]);
247145510Sdarrenr			if (ipf_devfs[IPL_LOGLOOKUP])
248145510Sdarrenr				devfs_remove_dev(ipf_devfs[IPL_LOGLOOKUP]);
24953024Sguido#endif
25034739Speter		}
25131183Speter		return err;
25231183Speter	case LKM_E_STAT :
25331183Speter		break;
25431183Speter	default:
25531183Speter		err = EIO;
25631183Speter		break;
25731183Speter	}
25831183Speter	return 0;
25931183Speter}
26031183Speter
26131183Speter
262255332Scystatic int if_ipf_remove __P((void))
26331183Speter{
26431183Speter	char *name;
26531183Speter	struct nameidata nd;
26631183Speter	int error, i;
26731183Speter
26831183Speter	for (i = 0; (name = ipf_devfiles[i]); i++) {
26931183Speter		NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
27031183Speter		if ((error = namei(&nd)))
27131183Speter			return (error);
27231183Speter		VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
27353024Sguido#if (__FreeBSD_version >= 300000)
27453024Sguido		VOP_LOCK(nd.ni_vp, LK_RETRY | LK_EXCLUSIVE, curproc);
27553024Sguido		VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
27653024Sguido		(void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
27753024Sguido
27853024Sguido		if (nd.ni_dvp == nd.ni_vp)
27953024Sguido			vrele(nd.ni_dvp);
28053024Sguido		else
28153024Sguido			vput(nd.ni_dvp);
28253024Sguido		if (nd.ni_vp != NULLVP)
28353024Sguido			vput(nd.ni_vp);
28453024Sguido#else
28531183Speter		VOP_LOCK(nd.ni_vp);
28631183Speter		VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
28731183Speter		(void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
28853024Sguido#endif
28931183Speter	}
29031183Speter
29131183Speter	return 0;
29231183Speter}
29331183Speter
29431183Speter
295255332Scystatic int if_ipf_unload(lkmtp, cmd)
296255332Scy	struct lkm_table *lkmtp;
297255332Scy	int cmd;
29831183Speter{
29931183Speter	int error = 0;
30031183Speter
301255332Scy	error = ipfdetach();
30231183Speter	if (!error)
303255332Scy		error = if_ipf_remove();
30431183Speter	return error;
30531183Speter}
30631183Speter
30731183Speter
308255332Scystatic int if_ipf_load(lkmtp, cmd)
309255332Scy	struct lkm_table *lkmtp;
310255332Scy	int cmd;
31131183Speter{
31231183Speter	struct nameidata nd;
31331183Speter	struct vattr vattr;
31431183Speter	int error = 0, fmode = S_IFCHR|0600, i;
31531183Speter	char *name;
31631183Speter
317255332Scy	error = ipfattach();
31831183Speter	if (error)
31931183Speter		return error;
320255332Scy	(void) if_ipf_remove();
32131183Speter
32231183Speter	for (i = 0; (name = ipf_devfiles[i]); i++) {
32331183Speter		NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
32431183Speter		if ((error = namei(&nd)))
32531183Speter			return error;
32631183Speter		if (nd.ni_vp != NULL) {
32731183Speter			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
32831183Speter			if (nd.ni_dvp == nd.ni_vp)
32931183Speter				vrele(nd.ni_dvp);
33031183Speter			else
33131183Speter				vput(nd.ni_dvp);
33231183Speter			vrele(nd.ni_vp);
33331183Speter			return (EEXIST);
33431183Speter		}
33531183Speter		VATTR_NULL(&vattr);
33631183Speter		vattr.va_type = VCHR;
33731183Speter		vattr.va_mode = (fmode & 07777);
338255332Scy		vattr.va_rdev = (ipf_major << 8) | i;
33931183Speter		VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
34031183Speter		error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
34153024Sguido#if (__FreeBSD_version >= 300000)
342145510Sdarrenr		vput(nd.ni_dvp);
34353024Sguido#endif
34431183Speter		if (error)
34531183Speter			return error;
34631183Speter	}
34731183Speter	return 0;
34831183Speter}
34931183Speter
35053024Sguido#endif  /* actually LKM */
35131183Speter
35231183Speter#if defined(__FreeBSD_version) && (__FreeBSD_version < 220000)
35331183Speter/*
35431183Speter * strlen isn't present in 2.1.* kernels.
35531183Speter */
35631183Spetersize_t strlen(string)
357255332Scy	char *string;
35831183Speter{
359145510Sdarrenr	register char *s;
36031183Speter
361145510Sdarrenr	for (s = string; *s; s++)
36231183Speter		;
363145510Sdarrenr	return (size_t)(s - string);
36431183Speter}
36531183Speter
36631183Speter
36731183Speterint xxxinit(lkmtp, cmd, ver)
368255332Scy	struct lkm_table *lkmtp;
369255332Scy	int cmd, ver;
37031183Speter{
371255332Scy	DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
37231183Speter}
37353024Sguido#else	/* __FREEBSD_version >= 220000 */
37431183Speter# ifdef	IPFILTER_LKM
37531183Speter#  include <sys/exec.h>
37631183Speter
37753024Sguido#  if (__FreeBSD_version >= 300000)
378255332ScyMOD_DEV(if_ipf, LM_DT_CHAR, CDEV_MAJOR, &ipf_cdevsw);
37953024Sguido#  else
380255332ScyMOD_DECL(if_ipf);
38131183Speter
38231183Speter
38331183Speterstatic struct lkm_dev _module = {
38431183Speter	LM_DEV,
38531183Speter	LKM_VERSION,
38631183Speter	IPL_VERSION,
38731183Speter	CDEV_MAJOR,
38831183Speter	LM_DT_CHAR,
389255332Scy	{ (void *)&ipf_cdevsw }
39031183Speter};
39153024Sguido#  endif
39231183Speter
39331183Speter
394255332Scyint if_ipf __P((struct lkm_table *, int, int));
39531183Speter
39631183Speter
397255332Scyint if_ipf(lkmtp, cmd, ver)
398255332Scy	struct lkm_table *lkmtp;
399255332Scy	int cmd, ver;
40031183Speter{
40153024Sguido#  if (__FreeBSD_version >= 300000)
402255332Scy	MOD_DISPATCH(if_ipf, lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
40353024Sguido#  else
404255332Scy	DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
40553024Sguido#  endif
40631183Speter}
40753024Sguido# endif /* IPFILTER_LKM */
408255332Scystatic ipf_devsw_installed = 0;
40931183Speter
410255332Scystatic void ipf_drvinit __P((void *unused))
41131183Speter{
41231183Speter	dev_t dev;
41334739Speter# ifdef	DEVFS
41434739Speter	void **tp = ipf_devfs;
41534739Speter# endif
41631183Speter
417255332Scy	if (!ipf_devsw_installed ) {
41831183Speter		dev = makedev(CDEV_MAJOR, 0);
419255332Scy		cdevsw_add(&dev, &ipf_cdevsw, NULL);
420255332Scy		ipf_devsw_installed = 1;
42131183Speter
42234739Speter# ifdef	DEVFS
423255332Scy		tp[IPL_LOGIPF] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGIPF,
42434739Speter						  DV_CHR, 0, 0, 0600, "ipf");
425255332Scy		tp[IPL_LOGNAT] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGNAT,
42634739Speter						  DV_CHR, 0, 0, 0600, "ipnat");
427255332Scy		tp[IPL_LOGSTATE] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGSTATE,
428145510Sdarrenr						    DV_CHR, 0, 0, 0600,
42934739Speter						    "ipstate");
430255332Scy		tp[IPL_LOGAUTH] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGAUTH,
431145510Sdarrenr						   DV_CHR, 0, 0, 0600,
43234739Speter						   "ipauth");
43334739Speter# endif
43431183Speter	}
43531183Speter}
43631183Speter
437145510Sdarrenr
438145510Sdarrenr#ifdef SYSCTL_IPF
439145510Sdarrenrint
440145510Sdarrenrsysctl_ipf_int SYSCTL_HANDLER_ARGS
441145510Sdarrenr{
442145510Sdarrenr	int error = 0;
443145510Sdarrenr
444145510Sdarrenr	if (arg1)
445145510Sdarrenr		error = SYSCTL_OUT(req, arg1, sizeof(int));
446145510Sdarrenr	else
447145510Sdarrenr		error = SYSCTL_OUT(req, &arg2, sizeof(int));
448145510Sdarrenr
449145510Sdarrenr	if (error || !req->newptr)
450145510Sdarrenr		return (error);
451145510Sdarrenr
452145510Sdarrenr	if (!arg1)
453145510Sdarrenr		error = EPERM;
454145510Sdarrenr	else {
455255332Scy		if ((oidp->oid_kind & CTLFLAG_OFF) && (ipf_running > 0))
456145510Sdarrenr			error = EBUSY;
457145510Sdarrenr		else
458145510Sdarrenr			error = SYSCTL_IN(req, arg1, sizeof(int));
459145510Sdarrenr	}
460145510Sdarrenr	return (error);
461145510Sdarrenr}
462145510Sdarrenr#endif
463145510Sdarrenr
464145510Sdarrenr
46537074Speter# if defined(IPFILTER_LKM) || \
46637074Speter     defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
467255332ScySYSINIT(ipfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipf_drvinit,NULL)
46831183Speter# endif /* IPFILTER_LKM */
46931183Speter#endif /* _FreeBSD_version */
470255332Scy
471255332Scy
472255332Scy/*
473255332Scy * routines below for saving IP headers to buffer
474255332Scy */
475255332Scyint ipfopen(dev, flags
476255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
477255332Scy, devtype, p)
478255332Scy	int devtype;
479255332Scy# if (__FreeBSD_version >= 500024)
480255332Scy	struct thread *p;
481255332Scy# else
482255332Scy	struct proc *p;
483255332Scy# endif /* __FreeBSD_version >= 500024 */
484255332Scy#else
485255332Scy)
486255332Scy#endif
487255332Scy#if (__FreeBSD_version >= 502116)
488255332Scy	struct cdev *dev;
489255332Scy#else
490255332Scy	dev_t dev;
491255332Scy#endif
492255332Scy	int flags;
493255332Scy{
494255332Scy	u_int unit = GET_MINOR(dev);
495255332Scy
496255332Scy	if (IPL_LOGMAX < unit)
497255332Scy		unit = ENXIO;
498255332Scy	else
499255332Scy		unit = 0;
500255332Scy	return unit;
501255332Scy}
502255332Scy
503255332Scy
504255332Scyint ipfclose(dev, flags
505255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
506255332Scy, devtype, p)
507255332Scy	int devtype;
508255332Scy# if (__FreeBSD_version >= 500024)
509255332Scy	struct thread *p;
510255332Scy# else
511255332Scy	struct proc *p;
512255332Scy# endif /* __FreeBSD_version >= 500024 */
513255332Scy#else
514255332Scy)
515255332Scy#endif
516255332Scy#if (__FreeBSD_version >= 502116)
517255332Scy	struct cdev *dev;
518255332Scy#else
519255332Scy	dev_t dev;
520255332Scy#endif
521255332Scy	int flags;
522255332Scy{
523255332Scy	u_int	unit = GET_MINOR(dev);
524255332Scy
525255332Scy	if (IPL_LOGMAX < unit)
526255332Scy		unit = ENXIO;
527255332Scy	else
528255332Scy		unit = 0;
529255332Scy	return unit;
530255332Scy}
531255332Scy
532255332Scy/*
533255332Scy * ipfread/ipflog
534255332Scy * both of these must operate with at least splnet() lest they be
535255332Scy * called during packet processing and cause an inconsistancy to appear in
536255332Scy * the filter lists.
537255332Scy */
538255332Scy#if (BSD >= 199306)
539255332Scyint ipfread(dev, uio, ioflag)
540255332Scy	int ioflag;
541255332Scy#else
542255332Scyint ipfread(dev, uio)
543255332Scy#endif
544255332Scy#if (__FreeBSD_version >= 502116)
545255332Scy	struct cdev *dev;
546255332Scy#else
547255332Scy	dev_t dev;
548255332Scy#endif
549255332Scy	register struct uio *uio;
550255332Scy{
551255332Scy	u_int	unit = GET_MINOR(dev);
552255332Scy
553255332Scy	if (unit < 0)
554255332Scy		return ENXIO;
555255332Scy
556255332Scy	if (ipf_running < 1)
557255332Scy		return EIO;
558255332Scy
559255332Scy	if (unit == IPL_LOGSYNC)
560255332Scy		return ipfsync_read(uio);
561255332Scy
562255332Scy#ifdef IPFILTER_LOG
563255332Scy	return ipflog_read(unit, uio);
564255332Scy#else
565255332Scy	return ENXIO;
566255332Scy#endif
567255332Scy}
568255332Scy
569255332Scy
570255332Scy/*
571255332Scy * ipfwrite
572255332Scy * both of these must operate with at least splnet() lest they be
573255332Scy * called during packet processing and cause an inconsistancy to appear in
574255332Scy * the filter lists.
575255332Scy */
576255332Scy#if (BSD >= 199306)
577255332Scyint ipfwrite(dev, uio, ioflag)
578255332Scy	int ioflag;
579255332Scy#else
580255332Scyint ipfwrite(dev, uio)
581255332Scy#endif
582255332Scy#if (__FreeBSD_version >= 502116)
583255332Scy	struct cdev *dev;
584255332Scy#else
585255332Scy	dev_t dev;
586255332Scy#endif
587255332Scy	register struct uio *uio;
588255332Scy{
589255332Scy
590255332Scy	if (ipf_running < 1)
591255332Scy		return EIO;
592255332Scy
593255332Scy	if (GET_MINOR(dev) == IPL_LOGSYNC)
594255332Scy		return ipfsync_write(uio);
595255332Scy	return ENXIO;
596255332Scy}
597