MFC r1.28:
[dragonfly.git] / contrib / ipfilter / mlf_ipl.c
bloba165c792cde4fb0873a5d33a4fc7e52d2a454c8f
1 /*
2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6 /*
7 * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
8 * its own major char number! Way cool patch!
9 */
12 #include <sys/param.h>
14 #if defined(__FreeBSD__)
15 # ifndef __FreeBSD_version
16 # ifdef IPFILTER_LKM
17 # include <osreldate.h>
18 # else
19 # include <sys/osreldate.h>
20 # endif
21 # endif
22 # ifdef IPFILTER_LKM
23 # define ACTUALLY_LKM_NOT_KERNEL
24 # endif
25 #endif
26 #include <sys/systm.h>
27 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
28 # ifndef ACTUALLY_LKM_NOT_KERNEL
29 # include "opt_devfs.h"
30 # endif
31 # include <sys/conf.h>
32 # include <sys/kernel.h>
33 # ifdef DEVFS
34 # include <sys/devfsext.h>
35 # endif /*DEVFS*/
36 #endif
37 #include <sys/conf.h>
38 #include <sys/file.h>
39 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
40 # include <sys/lock.h>
41 #endif
42 #include <sys/stat.h>
43 #include <sys/proc.h>
44 #include <sys/uio.h>
45 #include <sys/kernel.h>
46 #include <sys/vnode.h>
47 #include <sys/namei.h>
48 #include <sys/malloc.h>
49 #include <sys/mount.h>
50 #include <sys/exec.h>
51 #include <sys/mbuf.h>
52 #if BSD >= 199506
53 # include <sys/sysctl.h>
54 #endif
55 #if (__FreeBSD_version >= 300000)
56 # include <sys/socket.h>
57 #endif
58 #include <net/if.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/in.h>
61 #include <netinet/ip.h>
62 #include <net/route.h>
63 #include <net/if.h>
64 #include <netinet/ip_var.h>
65 #include <netinet/tcp.h>
66 #include <netinet/tcpip.h>
67 #include <sys/sysent.h>
68 #include <sys/lkm.h>
69 #include "netinet/ipl.h"
70 #include "netinet/ip_compat.h"
71 #include "netinet/ip_fil.h"
72 #include "netinet/ip_state.h"
73 #include "netinet/ip_nat.h"
74 #include "netinet/ip_auth.h"
75 #include "netinet/ip_frag.h"
76 #include "netinet/ip_proxy.h"
79 #if !defined(VOP_LEASE) && defined(LEASE_CHECK)
80 #define VOP_LEASE LEASE_CHECK
81 #endif
83 #ifndef MIN
84 #define MIN(a,b) (((a)<(b))?(a):(b))
85 #endif
87 int xxxinit __P((struct lkm_table *, int, int));
89 #ifdef SYSCTL_INT
90 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
91 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, "");
92 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, "");
93 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
94 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, "");
95 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
96 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_minttllog, CTLFLAG_RW,
97 &fr_minttllog, 0, "");
98 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RW,
99 &fr_tcpidletimeout, 0, "");
100 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RW,
101 &fr_tcphalfclosed, 0, "");
102 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RW,
103 &fr_tcpclosewait, 0, "");
104 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RW,
105 &fr_tcplastack, 0, "");
106 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW,
107 &fr_tcptimeout, 0, "");
108 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW,
109 &fr_tcpclosed, 0, "");
110 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW,
111 &fr_udptimeout, 0, "");
112 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RW,
113 &fr_udpacktimeout, 0, "");
114 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW,
115 &fr_icmptimeout, 0, "");
116 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmpacktimeout, CTLFLAG_RW,
117 &fr_icmpacktimeout, 0, "");
118 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RW,
119 &fr_defnatage, 0, "");
120 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
121 &fr_ipfrttl, 0, "");
122 SYSCTL_INT(_net_inet_ipf, OID_AUTO, ipl_unreach, CTLFLAG_RW,
123 &ipl_unreach, 0, "");
124 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
125 &fr_running, 0, "");
126 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RD,
127 &fr_authsize, 0, "");
128 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
129 &fr_authused, 0, "");
130 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
131 &fr_defaultauthage, 0, "");
132 SYSCTL_INT(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW,
133 &ippr_ftp_pasvonly, 0, "");
134 #endif
136 #ifdef DEVFS
137 static void *ipf_devfs[IPL_LOGMAX + 1];
138 #endif
140 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
141 int ipl_major = 0;
143 static struct cdevsw ipldevsw =
145 iplopen, /* open */
146 iplclose, /* close */
147 iplread, /* read */
148 (void *)nullop, /* write */
149 iplioctl, /* ioctl */
150 (void *)nullop, /* stop */
151 (void *)nullop, /* reset */
152 (void *)NULL, /* tty */
153 (void *)nullop, /* select */
154 (void *)nullop, /* mmap */
155 NULL /* strategy */
158 MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
160 extern struct cdevsw cdevsw[];
161 extern int vd_unuseddev __P((void));
162 extern int nchrdev;
163 #else
165 static struct cdevsw ipl_cdevsw = {
166 iplopen, iplclose, iplread, nowrite, /* 79 */
167 iplioctl, nostop, noreset, nodevtotty,
168 #if (__FreeBSD_version >= 300000)
169 seltrue, nommap, nostrategy, "ipl",
170 #else
171 noselect, nommap, nostrategy, "ipl",
172 #endif
173 NULL, -1
175 #endif
177 static void ipl_drvinit __P((void *));
179 #ifdef ACTUALLY_LKM_NOT_KERNEL
180 static int if_ipl_unload __P((struct lkm_table *, int));
181 static int if_ipl_load __P((struct lkm_table *, int));
182 static int if_ipl_remove __P((void));
183 static int ipl_major = CDEV_MAJOR;
185 static int iplaction __P((struct lkm_table *, int));
186 static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, NULL };
188 extern int lkmenodev __P((void));
190 static int iplaction(lkmtp, cmd)
191 struct lkm_table *lkmtp;
192 int cmd;
194 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
195 int i = ipl_major;
196 struct lkm_dev *args = lkmtp->private.lkm_dev;
197 #endif
198 int err = 0;
200 switch (cmd)
202 case LKM_E_LOAD :
203 if (lkmexists(lkmtp))
204 return EEXIST;
206 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
207 for (i = 0; i < nchrdev; i++)
208 if (cdevsw[i].d_open == lkmenodev ||
209 cdevsw[i].d_open == iplopen)
210 break;
211 if (i == nchrdev) {
212 printf("IP Filter: No free cdevsw slots\n");
213 return ENODEV;
216 ipl_major = i;
217 args->lkm_offset = i; /* slot in cdevsw[] */
218 #endif
219 printf("IP Filter: loaded into slot %d\n", ipl_major);
220 err = if_ipl_load(lkmtp, cmd);
221 if (!err)
222 ipl_drvinit((void *)NULL);
223 return err;
224 break;
225 case LKM_E_UNLOAD :
226 err = if_ipl_unload(lkmtp, cmd);
227 if (!err) {
228 printf("IP Filter: unloaded from slot %d\n",
229 ipl_major);
230 #ifdef DEVFS
231 if (ipf_devfs[IPL_LOGIPF])
232 devfs_remove_dev(ipf_devfs[IPL_LOGIPF]);
233 if (ipf_devfs[IPL_LOGNAT])
234 devfs_remove_dev(ipf_devfs[IPL_LOGNAT]);
235 if (ipf_devfs[IPL_LOGSTATE])
236 devfs_remove_dev(ipf_devfs[IPL_LOGSTATE]);
237 if (ipf_devfs[IPL_LOGAUTH])
238 devfs_remove_dev(ipf_devfs[IPL_LOGAUTH]);
239 #endif
241 return err;
242 case LKM_E_STAT :
243 break;
244 default:
245 err = EIO;
246 break;
248 return 0;
252 static int if_ipl_remove __P((void))
254 char *name;
255 struct nameidata nd;
256 int error, i;
258 for (i = 0; (name = ipf_devfiles[i]); i++) {
259 NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
260 if ((error = namei(&nd)))
261 return (error);
262 VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
263 #if (__FreeBSD_version >= 300000)
264 VOP_LOCK(nd.ni_vp, LK_RETRY | LK_EXCLUSIVE, curproc);
265 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
266 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
268 if (nd.ni_dvp == nd.ni_vp)
269 vrele(nd.ni_dvp);
270 else
271 vput(nd.ni_dvp);
272 if (nd.ni_vp != NULLVP)
273 vput(nd.ni_vp);
274 #else
275 VOP_LOCK(nd.ni_vp);
276 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
277 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
278 #endif
281 return 0;
285 static int if_ipl_unload(lkmtp, cmd)
286 struct lkm_table *lkmtp;
287 int cmd;
289 int error = 0;
291 error = ipldetach();
292 if (!error)
293 error = if_ipl_remove();
294 return error;
298 static int if_ipl_load(lkmtp, cmd)
299 struct lkm_table *lkmtp;
300 int cmd;
302 struct nameidata nd;
303 struct vattr vattr;
304 int error = 0, fmode = S_IFCHR|0600, i;
305 char *name;
307 error = iplattach();
308 if (error)
309 return error;
310 (void) if_ipl_remove();
312 for (i = 0; (name = ipf_devfiles[i]); i++) {
313 NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
314 if ((error = namei(&nd)))
315 return error;
316 if (nd.ni_vp != NULL) {
317 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
318 if (nd.ni_dvp == nd.ni_vp)
319 vrele(nd.ni_dvp);
320 else
321 vput(nd.ni_dvp);
322 vrele(nd.ni_vp);
323 return (EEXIST);
325 VATTR_NULL(&vattr);
326 vattr.va_type = VCHR;
327 vattr.va_mode = (fmode & 07777);
328 vattr.va_rdev = (ipl_major << 8) | i;
329 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
330 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
331 #if (__FreeBSD_version >= 300000)
332 vput(nd.ni_dvp);
333 #endif
334 if (error)
335 return error;
337 return 0;
340 #endif /* actually LKM */
342 #if defined(__FreeBSD_version) && (__FreeBSD_version < 220000)
344 * strlen isn't present in 2.1.* kernels.
346 size_t strlen(string)
347 char *string;
349 register char *s;
351 for (s = string; *s; s++)
353 return (size_t)(s - string);
357 int xxxinit(lkmtp, cmd, ver)
358 struct lkm_table *lkmtp;
359 int cmd, ver;
361 DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
363 #else /* __FREEBSD_version >= 220000 */
364 # ifdef IPFILTER_LKM
365 # include <sys/exec.h>
367 # if (__FreeBSD_version >= 300000)
368 MOD_DEV(if_ipl, LM_DT_CHAR, CDEV_MAJOR, &ipl_cdevsw);
369 # else
370 MOD_DECL(if_ipl);
373 static struct lkm_dev _module = {
374 LM_DEV,
375 LKM_VERSION,
376 IPL_VERSION,
377 CDEV_MAJOR,
378 LM_DT_CHAR,
379 { (void *)&ipl_cdevsw }
381 # endif
384 int if_ipl __P((struct lkm_table *, int, int));
387 int if_ipl(lkmtp, cmd, ver)
388 struct lkm_table *lkmtp;
389 int cmd, ver;
391 # if (__FreeBSD_version >= 300000)
392 MOD_DISPATCH(if_ipl, lkmtp, cmd, ver, iplaction, iplaction, iplaction);
393 # else
394 DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
395 # endif
397 # endif /* IPFILTER_LKM */
398 static int ipl_devsw_installed = 0;
400 static void ipl_drvinit __P((void *unused))
402 dev_t dev;
403 # ifdef DEVFS
404 void **tp = ipf_devfs;
405 # endif
407 if (!ipl_devsw_installed ) {
408 dev = makedev(CDEV_MAJOR, 0);
409 cdevsw_add(&dev, &ipl_cdevsw, NULL);
410 ipl_devsw_installed = 1;
412 # ifdef DEVFS
413 tp[IPL_LOGIPF] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGIPF,
414 DV_CHR, 0, 0, 0600, "ipf");
415 tp[IPL_LOGNAT] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGNAT,
416 DV_CHR, 0, 0, 0600, "ipnat");
417 tp[IPL_LOGSTATE] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGSTATE,
418 DV_CHR, 0, 0, 0600,
419 "ipstate");
420 tp[IPL_LOGAUTH] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGAUTH,
421 DV_CHR, 0, 0, 0600,
422 "ipauth");
423 # endif
427 # if defined(IPFILTER_LKM) || \
428 defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
429 SYSINIT(ipldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipl_drvinit,NULL)
430 # endif /* IPFILTER_LKM */
431 #endif /* _FreeBSD_version */