4 * Copyright (C) 2012 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
10 #include <sys/param.h>
11 #include <sys/systm.h>
17 #include <sys/kernel.h>
18 #include <sys/vnode.h>
19 #include <sys/namei.h>
20 #include <sys/malloc.h>
21 #include <sys/mount.h>
25 #include <netinet/in_systm.h>
26 #include <netinet/in.h>
27 #include <netinet/ip.h>
28 #include <net/route.h>
29 #include <netinet/ip_var.h>
30 #include <netinet/tcp.h>
31 #include <netinet/tcpip.h>
34 #include "ip_compat.h"
37 #define vn_lock(v,f) VOP_LOCK(v)
39 #if !defined(VOP_LEASE) && defined(LEASE_CHECK)
40 #define VOP_LEASE LEASE_CHECK
44 extern int lkmenodev __P((void));
47 int if_ipf_lkmentry __P((struct lkm_table *, int, int));
49 int if_ipf __P((struct lkm_table *, int, int));
51 static int ipf_unload __P((void));
52 static int ipf_load __P((void));
53 static int ipf_remove __P((void));
54 static int ipfaction __P((struct lkm_table *, int));
55 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
56 IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
57 IPLOOKUP_NAME, NULL };
60 struct cdevsw ipfdevsw =
65 (void *)nullop, /* write */
67 (void *)nullop, /* stop */
68 (void *)NULL, /* tty */
69 (void *)nullop, /* select */
70 (void *)nullop, /* mmap */
76 MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipfdevsw);
78 extern int vd_unuseddev __P((void));
79 extern struct cdevsw cdevsw[];
84 int if_ipf_lkmentry (lkmtp, cmd, ver)
86 int if_ipf(lkmtp, cmd, ver)
88 struct lkm_table *lkmtp;
91 DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
94 int lkmexists __P((struct lkm_table *)); /* defined in /sys/kern/kern_lkm.c */
96 static int ipfaction(lkmtp, cmd)
97 struct lkm_table *lkmtp;
101 struct lkm_dev *args = lkmtp->private.lkm_dev;
107 if (lkmexists(lkmtp))
110 for (i = 0; i < nchrdev; i++)
111 if (cdevsw[i].d_open == (dev_type_open((*)))lkmenodev ||
112 cdevsw[i].d_open == ipfopen)
115 printf("IP Filter: No free cdevsw slots\n");
120 args->lkm_offset = i; /* slot in cdevsw[] */
121 printf("IP Filter: loaded into slot %d\n", ipf_major);
126 printf("IP Filter: unloaded from slot %d\n",
139 static int ipf_remove()
145 for (i = 0; (name = ipf_devfiles[i]); i++) {
146 #if OpenBSD >= 200311
147 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE,
150 NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
152 if ((error = namei(&nd)))
154 VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
156 VOP_LOCK(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
157 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
159 (void)uvm_vnp_uncache(nd.ni_vp);
161 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
162 VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
164 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
170 static int ipf_unload()
175 * Unloading - remove the filter rule check from the IP
176 * input/output stream.
180 else if (ipf_running >= 0)
185 error = ipf_remove();
186 printf("%s unloaded\n", ipfilter_version);
192 static int ipf_load()
196 int error = 0, fmode = S_IFCHR|0600, i;
200 * XXX Remove existing device nodes prior to creating new ones
201 * XXX using the assigned LKM device slot's major number. In a
202 * XXX perfect world we could use the ones specified by cdevsw[].
208 for (i = 0; (error == 0) && (name = ipf_devfiles[i]); i++) {
209 NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
210 if ((error = namei(&nd)))
212 if (nd.ni_vp != NULL) {
213 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
214 if (nd.ni_dvp == nd.ni_vp)
223 vattr.va_type = VCHR;
224 vattr.va_mode = (fmode & 07777);
225 vattr.va_rdev = (ipf_major << 8) | i;
226 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
227 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
233 if (FR_ISPASS(ipf_pass))
235 else if (FR_ISBLOCK(ipf_pass))
238 defpass = "no-match -> block";
240 printf("%s initialized. Default = %s all, Logging = %s%s\n",
241 ipfilter_version, defpass,
247 #ifdef IPFILTER_COMPILED
260 * routines below for saving IP headers to buffer
263 ipfopen(dev, flags, devtype, p)
269 u_int min = GET_MINOR(dev);
272 if (IPL_LOGMAX < min) {
298 ipfclose(dev, flags, devtype, p)
304 u_int min = GET_MINOR(dev);
306 if (IPL_LOGMAX < min)
316 * both of these must operate with at least splnet() lest they be
317 * called during packet processing and cause an inconsistancy to appear in
321 ipfread(dev, uio, ioflag)
323 register struct uio *uio;
330 if (GET_MINOR(dev) == IPL_LOGSYNC)
331 return ipfsync_read(uio);
334 return ipflog_read(GET_MINOR(dev), uio);
343 * both of these must operate with at least splnet() lest they be
344 * called during packet processing and cause an inconsistancy to appear in
349 ipfwrite(dev, uio, ioflag)
355 register struct uio *uio;
361 if (GET_MINOR(dev) == IPL_LOGSYNC)
362 return ipfsync_write(uio);