summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/mln_ipl.c
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-10-05 03:26:51 +0000
committerngie <ngie@FreeBSD.org>2015-10-05 03:26:51 +0000
commite1dd16d965b177f109afb771e59432e36f335d0a (patch)
tree15db092a5401cf329f1bff9d3bf700d1fde0f121 /contrib/ipfilter/mln_ipl.c
parent115d008392113efc6f844baa7cc407e9eaae63db (diff)
downloadFreeBSD-src-e1dd16d965b177f109afb771e59432e36f335d0a.zip
FreeBSD-src-e1dd16d965b177f109afb771e59432e36f335d0a.tar.gz
Revert r288682
I meant to do this on ^/user/ngie/more-tests Pointyhat to: ngie (use svn info next time...)
Diffstat (limited to 'contrib/ipfilter/mln_ipl.c')
-rw-r--r--contrib/ipfilter/mln_ipl.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/contrib/ipfilter/mln_ipl.c b/contrib/ipfilter/mln_ipl.c
new file mode 100644
index 0000000..28b5407
--- /dev/null
+++ b/contrib/ipfilter/mln_ipl.c
@@ -0,0 +1,355 @@
+/* $FreeBSD$ */
+
+/*
+ * Copyright (C) 2012 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ *
+ */
+/*
+ * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
+ * its own major char number! Way cool patch!
+ */
+
+
+#include <sys/param.h>
+
+/*
+ * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns
+ * on those hooks. We don't need any special mods with this!
+ */
+#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \
+ (defined(NetBSD1_2) && NetBSD1_2 > 1)
+# define NETBSD_PF
+#endif
+
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/vnode.h>
+#include <sys/namei.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/exec.h>
+#include <sys/mbuf.h>
+#include <net/if.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <net/route.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <sys/lkm.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+#include "ipl.h"
+#include "ip_compat.h"
+#include "ip_fil.h"
+#include "ip_auth.h"
+#include "ip_state.h"
+#include "ip_nat.h"
+#include "ip_sync.h"
+
+#if !defined(__NetBSD_Version__) || __NetBSD_Version__ < 103050000
+#define vn_lock(v,f) VOP_LOCK(v)
+#endif
+
+#if !defined(VOP_LEASE) && defined(LEASE_CHECK)
+#define VOP_LEASE LEASE_CHECK
+#endif
+
+
+extern int lkmenodev __P((void));
+
+#if NetBSD >= 199706
+int ipflkm_lkmentry __P((struct lkm_table *, int, int));
+#else
+int xxxinit __P((struct lkm_table *, int, int));
+#endif
+static int ipf_unload __P((void));
+static int ipf_load __P((void));
+static int ipf_remove __P((void));
+static int ipfaction __P((struct lkm_table *, int));
+static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
+ IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
+ IPLOOKUP_NAME, NULL };
+
+int ipf_major = 0;
+extern ipf_main_softc_t ipfmain;
+extern const struct cdevsw ipl_cdevsw;
+
+#if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000)
+MOD_DEV(IPL_VERSION, "ipf", NULL, -1, &ipl_cdevsw, -1);
+#else
+MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
+#endif
+
+extern int vd_unuseddev __P((void));
+extern struct cdevsw cdevsw[];
+extern int nchrdev;
+
+
+int
+#if NetBSD >= 199706
+ipflkm_lkmentry(lkmtp, cmd, ver)
+#else
+xxxinit(lkmtp, cmd, ver)
+#endif
+ struct lkm_table *lkmtp;
+ int cmd, ver;
+{
+ DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
+}
+
+
+static int
+ipfaction(lkmtp, cmd)
+ struct lkm_table *lkmtp;
+ int cmd;
+{
+#if !defined(__NetBSD__) || (__NetBSD_Version__ < 106080000)
+ int i;
+#endif
+ struct lkm_dev *args = lkmtp->private.lkm_dev;
+ int err = 0;
+
+ switch (cmd)
+ {
+ case LKM_E_LOAD :
+ if (lkmexists(lkmtp))
+ return EEXIST;
+
+#if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000)
+# if (__NetBSD_Version__ < 200000000)
+ err = devsw_attach(args->lkm_devname,
+ args->lkm_bdev, &args->lkm_bdevmaj,
+ args->lkm_cdev, &args->lkm_cdevmaj);
+ if (err != 0)
+ return (err);
+# endif
+ ipf_major = args->lkm_cdevmaj;
+#else
+ for (i = 0; i < nchrdev; i++)
+ if (cdevsw[i].d_open == (dev_type_open((*)))lkmenodev ||
+ cdevsw[i].d_open == ipfopen)
+ break;
+ if (i == nchrdev) {
+ printf("IP Filter: No free cdevsw slots\n");
+ return ENODEV;
+ }
+
+ ipf_major = i;
+ args->lkm_offset = i; /* slot in cdevsw[] */
+#endif
+ printf("IP Filter: loaded into slot %d\n", ipf_major);
+ return ipf_load();
+ case LKM_E_UNLOAD :
+#if defined(__NetBSD__) && (__NetBSD_Version__ >= 106080000)
+ devsw_detach(args->lkm_bdev, args->lkm_cdev);
+ args->lkm_bdevmaj = -1;
+ args->lkm_cdevmaj = -1;
+#endif
+ err = ipf_unload();
+ if (!err)
+ printf("IP Filter: unloaded from slot %d\n",
+ ipf_major);
+ break;
+ case LKM_E_STAT :
+ break;
+ default:
+ err = EIO;
+ break;
+ }
+ return err;
+}
+
+
+static int
+ipf_remove()
+{
+ char *name;
+ struct nameidata nd;
+ int error, i;
+
+ for (i = 0; (name = ipf_devfiles[i]); i++) {
+#if (__NetBSD_Version__ > 106009999)
+# if (__NetBSD_Version__ > 399001400)
+# if (__NetBSD_Version__ > 499001400)
+ NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_SYSSPACE,
+ name);
+# else
+ NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_SYSSPACE,
+ name, curlwp);
+# endif
+# else
+ NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_SYSSPACE,
+ name, curproc);
+# endif
+#else
+ NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
+#endif
+ if ((error = namei(&nd)))
+ return (error);
+#if (__NetBSD_Version__ > 399001400)
+# if (__NetBSD_Version__ > 399002000)
+# if (__NetBSD_Version__ < 499001400)
+ VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_cred, LEASE_WRITE);
+# endif
+# else
+ VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_proc->p_ucred, LEASE_WRITE);
+# endif
+#else
+ VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
+#endif
+#if !defined(__NetBSD_Version__) || (__NetBSD_Version__ < 106000000)
+ vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY);
+#endif
+#if (__NetBSD_Version__ >= 399002000)
+# if (__NetBSD_Version__ < 499001400)
+ VOP_LEASE(nd.ni_vp, curlwp, curlwp->l_cred, LEASE_WRITE);
+# endif
+#else
+# if (__NetBSD_Version__ > 399001400)
+ VOP_LEASE(nd.ni_vp, curlwp, curlwp->l_proc->p_ucred, LEASE_WRITE);
+# else
+ VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
+# endif
+#endif
+ (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
+ }
+ return 0;
+}
+
+
+static int
+ipf_unload()
+{
+ int error = 0;
+
+ /*
+ * Unloading - remove the filter rule check from the IP
+ * input/output stream.
+ */
+ if (ipfmain.ipf_refcnt)
+ error = EBUSY;
+ else if (ipfmain.ipf_running >= 0) {
+ error = ipfdetach(&ipfmain);
+ if (error == 0) {
+ ipf_destroy_all(&ipfmain);
+ ipf_unload_all();
+ }
+ }
+
+ if (error == 0) {
+ ipfmain.ipf_running = -2;
+ error = ipf_remove();
+ printf("%s unloaded\n", ipfilter_version);
+ }
+ return error;
+}
+
+
+static int
+ipf_load()
+{
+ struct nameidata nd;
+ struct vattr vattr;
+ int error = 0, fmode = S_IFCHR|0600, i;
+ char *name;
+
+ /*
+ * XXX Remove existing device nodes prior to creating new ones
+ * XXX using the assigned LKM device slot's major number. In a
+ * XXX perfect world we could use the ones specified by cdevsw[].
+ */
+ (void)ipf_remove();
+
+ bzero((char *)&ipfmain, sizeof(ipfmain));
+ error = ipf_load_all();
+ if (error != 0)
+ return error;
+ if (ipf_create_all(&ipfmain) == NULL) {
+ ipf_unload_all();
+ return EIO;
+ }
+
+ error = ipfattach(&ipfmain);
+ if (error != 0) {
+ (void) ipf_unload();
+ return error;
+ }
+
+ for (i = 0; (error == 0) && (name = ipf_devfiles[i]); i++) {
+#if (__NetBSD_Version__ > 399001400)
+# if (__NetBSD_Version__ > 499001400)
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name);
+# else
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curlwp);
+# endif
+#else
+ NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
+#endif
+ if ((error = namei(&nd)))
+ break;
+ if (nd.ni_vp != NULL) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ vrele(nd.ni_vp);
+ error = EEXIST;
+ break;
+ }
+ VATTR_NULL(&vattr);
+ vattr.va_type = VCHR;
+ vattr.va_mode = (fmode & 07777);
+ vattr.va_rdev = (ipf_major << 8) | i;
+#if (__NetBSD_Version__ > 399001400)
+# if (__NetBSD_Version__ >= 399002000)
+# if (__NetBSD_Version__ < 499001400)
+ VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_cred, LEASE_WRITE);
+# endif
+# else
+ VOP_LEASE(nd.ni_dvp, curlwp, curlwp->l_proc->p_ucred, LEASE_WRITE);
+# endif
+#else
+ VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
+#endif
+ error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
+ if (error == 0)
+ vput(nd.ni_vp);
+ }
+
+ if (error == 0) {
+ char *defpass;
+
+ if (FR_ISPASS(ipfmain.ipf_pass))
+ defpass = "pass";
+ else if (FR_ISBLOCK(ipfmain.ipf_pass))
+ defpass = "block";
+ else
+ defpass = "no-match -> block";
+
+ printf("%s initialized. Default = %s all, Logging = %s%s\n",
+ ipfilter_version, defpass,
+#ifdef IPFILTER_LOG
+ "enabled",
+#else
+ "disabled",
+#endif
+#ifdef IPFILTER_COMPILED
+ " (COMPILED)"
+#else
+ ""
+#endif
+ );
+ ipfmain.ipf_running = 1;
+ }
+ return error;
+}
OpenPOWER on IntegriCloud