2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
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!
12 #include <sys/param.h>
14 #if defined(__FreeBSD__)
15 # ifndef __FreeBSD_version
17 # include <osreldate.h>
19 # include <sys/osreldate.h>
23 # define ACTUALLY_LKM_NOT_KERNEL
26 #include <sys/systm.h>
27 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
28 # ifndef ACTUALLY_LKM_NOT_KERNEL
29 # include "opt_devfs.h"
31 # include <sys/conf.h>
32 # include <sys/kernel.h>
34 # include <sys/devfsext.h>
39 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
40 # include <sys/lock.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>
53 # include <sys/sysctl.h>
55 #if (__FreeBSD_version >= 300000)
56 # include <sys/socket.h>
59 #include <netinet/in_systm.h>
60 #include <netinet/in.h>
61 #include <netinet/ip.h>
62 #include <net/route.h>
64 #include <netinet/ip_var.h>
65 #include <netinet/tcp.h>
66 #include <netinet/tcpip.h>
67 #include <sys/sysent.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
84 #define MIN(a,b) (((a)<(b))?(a):(b))
87 int xxxinit __P((struct lkm_table *, int, 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,
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,
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, "");
137 static void *ipf_devfs[IPL_LOGMAX + 1];
140 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
143 static struct cdevsw ipldevsw =
146 iplclose, /* close */
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 */
158 MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
160 extern struct cdevsw cdevsw[];
161 extern int vd_unuseddev __P((void));
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",
171 noselect, nommap, nostrategy, "ipl",
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;
194 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
196 struct lkm_dev *args = lkmtp->private.lkm_dev;
203 if (lkmexists(lkmtp))
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)
212 printf("IP Filter: No free cdevsw slots\n");
217 args->lkm_offset = i; /* slot in cdevsw[] */
219 printf("IP Filter: loaded into slot %d\n", ipl_major);
220 err = if_ipl_load(lkmtp, cmd);
222 ipl_drvinit((void *)NULL);
226 err = if_ipl_unload(lkmtp, cmd);
228 printf("IP Filter: unloaded from slot %d\n",
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]);
252 static int if_ipl_remove __P((void))
258 for (i = 0; (name = ipf_devfiles[i]); i++) {
259 NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
260 if ((error = namei(&nd)))
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)
272 if (nd.ni_vp != NULLVP)
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);
285 static int if_ipl_unload(lkmtp, cmd)
286 struct lkm_table *lkmtp;
293 error = if_ipl_remove();
298 static int if_ipl_load(lkmtp, cmd)
299 struct lkm_table *lkmtp;
304 int error = 0, fmode = S_IFCHR|0600, i;
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)))
316 if (nd.ni_vp != NULL) {
317 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
318 if (nd.ni_dvp == nd.ni_vp)
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)
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)
351 for (s = string; *s; s++)
353 return (size_t)(s - string);
357 int xxxinit(lkmtp, cmd, ver)
358 struct lkm_table *lkmtp;
361 DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
363 #else /* __FREEBSD_version >= 220000 */
365 # include <sys/exec.h>
367 # if (__FreeBSD_version >= 300000)
368 MOD_DEV(if_ipl, LM_DT_CHAR, CDEV_MAJOR, &ipl_cdevsw);
373 static struct lkm_dev _module = {
379 { (void *)&ipl_cdevsw }
384 int if_ipl __P((struct lkm_table *, int, int));
387 int if_ipl(lkmtp, cmd, ver)
388 struct lkm_table *lkmtp;
391 # if (__FreeBSD_version >= 300000)
392 MOD_DISPATCH(if_ipl, lkmtp, cmd, ver, iplaction, iplaction, iplaction);
394 DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
397 # endif /* IPFILTER_LKM */
398 static int ipl_devsw_installed = 0;
400 static void ipl_drvinit __P((void *unused))
404 void **tp = ipf_devfs;
407 if (!ipl_devsw_installed ) {
408 dev = makedev(CDEV_MAJOR, 0);
409 cdevsw_add(&dev, &ipl_cdevsw, NULL);
410 ipl_devsw_installed = 1;
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,
420 tp[IPL_LOGAUTH] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGAUTH,
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 */