Don't be terse.
[netbsd-mini2440.git] / dist / ipf / mlo_ipl.c
blob8c910a4d07cad8bd2bf543209715126ae7aec87a
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 1993-2001 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 */
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/conf.h>
13 #include <sys/file.h>
14 #include <sys/stat.h>
15 #include <sys/proc.h>
16 #include <sys/uio.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>
22 #include <sys/exec.h>
23 #include <sys/mbuf.h>
24 #include <net/if.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>
32 #include <sys/lkm.h>
33 #include "ipl.h"
34 #include "ip_compat.h"
35 #include "ip_fil.h"
37 #define vn_lock(v,f) VOP_LOCK(v)
39 #if !defined(VOP_LEASE) && defined(LEASE_CHECK)
40 #define VOP_LEASE LEASE_CHECK
41 #endif
44 extern int lkmenodev __P((void));
46 #if OpenBSD >= 200311
47 int if_ipl_lkmentry __P((struct lkm_table *, int, int));
48 #else
49 int if_ipl __P((struct lkm_table *, int, int));
50 #endif
51 static int ipl_unload __P((void));
52 static int ipl_load __P((void));
53 static int ipl_remove __P((void));
54 static int iplaction __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 ipldevsw =
62 iplopen, /* open */
63 iplclose, /* close */
64 iplread, /* read */
65 iplwrite, /* write */
66 iplioctl, /* ioctl */
67 (void *)nullop, /* stop */
68 (void *)NULL, /* tty */
69 (void *)nullop, /* select */
70 (void *)nullop, /* mmap */
71 NULL /* strategy */
74 int ipl_major = 0;
76 MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
78 extern int vd_unuseddev __P((void));
79 extern struct cdevsw cdevsw[];
80 extern int nchrdev;
83 #if OpenBSD >= 200311
84 int if_ipl_lkmentry (lkmtp, cmd, ver)
85 #else
86 int if_ipl(lkmtp, cmd, ver)
87 #endif
88 struct lkm_table *lkmtp;
89 int cmd, ver;
91 DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
94 int lkmexists __P((struct lkm_table *)); /* defined in /sys/kern/kern_lkm.c */
96 static int iplaction(lkmtp, cmd)
97 struct lkm_table *lkmtp;
98 int cmd;
100 int i;
101 struct lkm_dev *args = lkmtp->private.lkm_dev;
102 int err = 0;
104 switch (cmd)
106 case LKM_E_LOAD :
107 if (lkmexists(lkmtp))
108 return EEXIST;
110 for (i = 0; i < nchrdev; i++)
111 if (cdevsw[i].d_open == (dev_type_open((*)))lkmenodev ||
112 cdevsw[i].d_open == iplopen)
113 break;
114 if (i == nchrdev) {
115 printf("IP Filter: No free cdevsw slots\n");
116 return ENODEV;
119 ipl_major = i;
120 args->lkm_offset = i; /* slot in cdevsw[] */
121 printf("IP Filter: loaded into slot %d\n", ipl_major);
122 return ipl_load();
123 case LKM_E_UNLOAD :
124 err = ipl_unload();
125 if (!err)
126 printf("IP Filter: unloaded from slot %d\n",
127 ipl_major);
128 break;
129 case LKM_E_STAT :
130 break;
131 default:
132 err = EIO;
133 break;
135 return err;
139 static int ipl_remove()
141 struct nameidata nd;
142 int error, i;
143 char *name;
145 for (i = 0; (name = ipf_devfiles[i]); i++) {
146 #if OpenBSD >= 200311
147 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE,
148 name, curproc);
149 #else
150 NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
151 #endif
152 if ((error = namei(&nd)))
153 return (error);
154 VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
155 #if OpenBSD < 200311
156 VOP_LOCK(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
157 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
158 #else
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);
163 #endif
164 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
166 return 0;
170 static int ipl_unload()
172 int error = 0;
175 * Unloading - remove the filter rule check from the IP
176 * input/output stream.
178 if (fr_refcnt)
179 error = EBUSY;
180 else if (fr_running >= 0)
181 error = ipfdetach();
183 if (error == 0) {
184 fr_running = -2;
185 error = ipl_remove();
186 printf("%s unloaded\n", ipfilter_version);
188 return error;
192 static int ipl_load()
194 struct nameidata nd;
195 struct vattr vattr;
196 int error = 0, fmode = S_IFCHR|0600, i;
197 char *name;
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[].
204 (void)ipl_remove();
206 error = ipfattach();
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)))
211 break;
212 if (nd.ni_vp != NULL) {
213 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
214 if (nd.ni_dvp == nd.ni_vp)
215 vrele(nd.ni_dvp);
216 else
217 vput(nd.ni_dvp);
218 vrele(nd.ni_vp);
219 error = EEXIST;
220 break;
222 VATTR_NULL(&vattr);
223 vattr.va_type = VCHR;
224 vattr.va_mode = (fmode & 07777);
225 vattr.va_rdev = (ipl_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);
230 if (error == 0) {
231 char *defpass;
233 if (FR_ISPASS(fr_pass))
234 defpass = "pass";
235 else if (FR_ISBLOCK(fr_pass))
236 defpass = "block";
237 else
238 defpass = "no-match -> block";
240 printf("%s initialized. Default = %s all, Logging = %s%s\n",
241 ipfilter_version, defpass,
242 #ifdef IPFILTER_LOG
243 "enabled",
244 #else
245 "disabled",
246 #endif
247 #ifdef IPFILTER_COMPILED
248 " (COMPILED)"
249 #else
251 #endif
253 fr_running = 1;
255 return error;