diff options
author | ngie <ngie@FreeBSD.org> | 2015-10-05 03:26:51 +0000 |
---|---|---|
committer | ngie <ngie@FreeBSD.org> | 2015-10-05 03:26:51 +0000 |
commit | e1dd16d965b177f109afb771e59432e36f335d0a (patch) | |
tree | 15db092a5401cf329f1bff9d3bf700d1fde0f121 /contrib/ipfilter/mln_ipl.c | |
parent | 115d008392113efc6f844baa7cc407e9eaae63db (diff) | |
download | FreeBSD-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.c | 355 |
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; +} |