4 * Copyright (C) 2012 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
10 * its own major char number! Way cool patch!
14 #include <sys/param.h>
17 # ifndef __FreeBSD_cc_version
18 # include <osreldate.h>
20 # if __FreeBSD_cc_version < 430000
21 # include <osreldate.h>
24 # define ACTUALLY_LKM_NOT_KERNEL
26 # ifndef __FreeBSD_cc_version
27 # include <sys/osreldate.h>
29 # if __FreeBSD_cc_version < 430000
30 # include <sys/osreldate.h>
34 #include <sys/systm.h>
35 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
36 # ifndef ACTUALLY_LKM_NOT_KERNEL
37 # include "opt_devfs.h"
39 # include <sys/conf.h>
40 # include <sys/kernel.h>
42 # include <sys/devfsext.h>
47 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
48 # include <sys/lock.h>
52 #include <sys/kernel.h>
53 #include <sys/vnode.h>
54 #include <sys/namei.h>
55 #include <sys/malloc.h>
56 #include <sys/mount.h>
60 # include <sys/sysctl.h>
62 #if (__FreeBSD_version >= 300000)
63 # include <sys/socket.h>
66 #include <netinet/in_systm.h>
67 #include <netinet/in.h>
68 #include <netinet/ip.h>
69 #include <net/route.h>
70 #include <netinet/ip_var.h>
71 #include <netinet/tcp.h>
72 #include <netinet/tcpip.h>
73 #include <sys/sysent.h>
75 #include "netinet/ipl.h"
76 #include "netinet/ip_compat.h"
77 #include "netinet/ip_fil.h"
78 #include "netinet/ip_state.h"
79 #include "netinet/ip_nat.h"
80 #include "netinet/ip_auth.h"
81 #include "netinet/ip_frag.h"
84 #if !defined(VOP_LEASE) && defined(LEASE_CHECK)
85 #define VOP_LEASE LEASE_CHECK
88 int xxxinit __P((struct lkm_table *, int, int));
91 int sysctl_ipf_int SYSCTL_HANDLER_ARGS;
92 # define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
93 SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
94 ptr, val, sysctl_ipf_int, "I", descr);
95 # define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */
96 # define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF)
97 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
98 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipf_flags, 0, "");
99 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipf_pass, 0, "");
100 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipf_active, 0, "");
101 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipf_chksrc, 0, "");
102 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipf_minttl, 0, "");
103 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
104 &ipf_tcpidletimeout, 0, "");
105 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
106 &ipf_tcphalfclosed, 0, "");
107 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
108 &ipf_tcpclosewait, 0, "");
109 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
110 &ipf_tcplastack, 0, "");
111 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
112 &ipf_tcptimeout, 0, "");
113 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
114 &ipf_tcpclosed, 0, "");
115 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
116 &ipf_udptimeout, 0, "");
117 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
118 &ipf_icmptimeout, 0, "");
119 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
120 &ipf_defnatage, 0, "");
121 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
122 &ipf_ipfrttl, 0, "");
123 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD,
124 &ipf_running, 0, "");
125 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
126 &ipf_statesize, 0, "");
127 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
128 &ipf_statemax, 0, "");
129 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
130 &ipf_authsize, 0, "");
131 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
132 &ipf_authused, 0, "");
133 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
134 &ipf_defaultauthage, 0, "");
135 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW,
136 &ippr_ftp_pasvonly, 0, "");
140 static void *ipf_devfs[IPL_LOGSIZE];
143 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
146 static struct cdevsw ipfdevsw =
149 ipfclose, /* close */
151 (void *)nullop, /* write */
152 ipfioctl, /* ioctl */
153 (void *)nullop, /* stop */
154 (void *)nullop, /* reset */
155 (void *)NULL, /* tty */
156 (void *)nullop, /* select */
157 (void *)nullop, /* mmap */
161 MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipfdevsw);
163 extern struct cdevsw cdevsw[];
164 extern int vd_unuseddev __P((void));
168 static struct cdevsw ipf_cdevsw = {
169 ipfopen, ipfclose, ipfread, nowrite, /* 79 */
170 ipfioctl, nostop, noreset, nodevtotty,
171 #if (__FreeBSD_version >= 300000)
172 seltrue, nommap, nostrategy, "ipf",
174 noselect, nommap, nostrategy, "ipf",
180 static void ipf_drvinit __P((void *));
182 #ifdef ACTUALLY_LKM_NOT_KERNEL
183 static int if_ipf_unload __P((struct lkm_table *, int));
184 static int if_ipf_load __P((struct lkm_table *, int));
185 static int if_ipf_remove __P((void));
186 static int ipf_major = CDEV_MAJOR;
188 static int ipfaction __P((struct lkm_table *, int));
189 static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH,
190 IPL_SCAN, IPL_SYNC, IPL_POOL, NULL };
192 extern int lkmenodev __P((void));
194 static int ipfaction(lkmtp, cmd)
195 struct lkm_table *lkmtp;
198 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
200 struct lkm_dev *args = lkmtp->private.lkm_dev;
207 if (lkmexists(lkmtp))
210 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
211 for (i = 0; i < nchrdev; i++)
212 if (cdevsw[i].d_open == lkmenodev ||
213 cdevsw[i].d_open == ipfopen)
216 printf("IP Filter: No free cdevsw slots\n");
221 args->lkm_offset = i; /* slot in cdevsw[] */
223 printf("IP Filter: loaded into slot %d\n", ipf_major);
224 err = if_ipf_load(lkmtp, cmd);
226 ipf_drvinit((void *)NULL);
230 err = if_ipf_unload(lkmtp, cmd);
232 printf("IP Filter: unloaded from slot %d\n",
235 if (ipf_devfs[IPL_LOGIPF])
236 devfs_remove_dev(ipf_devfs[IPL_LOGIPF]);
237 if (ipf_devfs[IPL_LOGNAT])
238 devfs_remove_dev(ipf_devfs[IPL_LOGNAT]);
239 if (ipf_devfs[IPL_LOGSTATE])
240 devfs_remove_dev(ipf_devfs[IPL_LOGSTATE]);
241 if (ipf_devfs[IPL_LOGAUTH])
242 devfs_remove_dev(ipf_devfs[IPL_LOGAUTH]);
243 if (ipf_devfs[IPL_LOGSCAN])
244 devfs_remove_dev(ipf_devfs[IPL_LOGSCAN]);
245 if (ipf_devfs[IPL_LOGSYNC])
246 devfs_remove_dev(ipf_devfs[IPL_LOGSYNC]);
247 if (ipf_devfs[IPL_LOGLOOKUP])
248 devfs_remove_dev(ipf_devfs[IPL_LOGLOOKUP]);
262 static int if_ipf_remove __P((void))
268 for (i = 0; (name = ipf_devfiles[i]); i++) {
269 NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
270 if ((error = namei(&nd)))
272 VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
273 #if (__FreeBSD_version >= 300000)
274 VOP_LOCK(nd.ni_vp, LK_RETRY | LK_EXCLUSIVE, curproc);
275 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
276 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
278 if (nd.ni_dvp == nd.ni_vp)
282 if (nd.ni_vp != NULLVP)
286 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
287 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
295 static int if_ipf_unload(lkmtp, cmd)
296 struct lkm_table *lkmtp;
303 error = if_ipf_remove();
308 static int if_ipf_load(lkmtp, cmd)
309 struct lkm_table *lkmtp;
314 int error = 0, fmode = S_IFCHR|0600, i;
320 (void) if_ipf_remove();
322 for (i = 0; (name = ipf_devfiles[i]); i++) {
323 NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
324 if ((error = namei(&nd)))
326 if (nd.ni_vp != NULL) {
327 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
328 if (nd.ni_dvp == nd.ni_vp)
336 vattr.va_type = VCHR;
337 vattr.va_mode = (fmode & 07777);
338 vattr.va_rdev = (ipf_major << 8) | i;
339 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
340 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
341 #if (__FreeBSD_version >= 300000)
350 #endif /* actually LKM */
352 #if defined(__FreeBSD_version) && (__FreeBSD_version < 220000)
354 * strlen isn't present in 2.1.* kernels.
356 size_t strlen(string)
361 for (s = string; *s; s++)
363 return (size_t)(s - string);
367 int xxxinit(lkmtp, cmd, ver)
368 struct lkm_table *lkmtp;
371 DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
373 #else /* __FREEBSD_version >= 220000 */
375 # include <sys/exec.h>
377 # if (__FreeBSD_version >= 300000)
378 MOD_DEV(if_ipf, LM_DT_CHAR, CDEV_MAJOR, &ipf_cdevsw);
383 static struct lkm_dev _module = {
389 { (void *)&ipf_cdevsw }
394 int if_ipf __P((struct lkm_table *, int, int));
397 int if_ipf(lkmtp, cmd, ver)
398 struct lkm_table *lkmtp;
401 # if (__FreeBSD_version >= 300000)
402 MOD_DISPATCH(if_ipf, lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
404 DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction);
407 # endif /* IPFILTER_LKM */
408 static ipf_devsw_installed = 0;
410 static void ipf_drvinit __P((void *unused))
414 void **tp = ipf_devfs;
417 if (!ipf_devsw_installed ) {
418 dev = makedev(CDEV_MAJOR, 0);
419 cdevsw_add(&dev, &ipf_cdevsw, NULL);
420 ipf_devsw_installed = 1;
423 tp[IPL_LOGIPF] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGIPF,
424 DV_CHR, 0, 0, 0600, "ipf");
425 tp[IPL_LOGNAT] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGNAT,
426 DV_CHR, 0, 0, 0600, "ipnat");
427 tp[IPL_LOGSTATE] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGSTATE,
430 tp[IPL_LOGAUTH] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGAUTH,
440 sysctl_ipf_int SYSCTL_HANDLER_ARGS
445 error = SYSCTL_OUT(req, arg1, sizeof(int));
447 error = SYSCTL_OUT(req, &arg2, sizeof(int));
449 if (error || !req->newptr)
455 if ((oidp->oid_kind & CTLFLAG_OFF) && (ipf_running > 0))
458 error = SYSCTL_IN(req, arg1, sizeof(int));
465 # if defined(IPFILTER_LKM) || \
466 defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
467 SYSINIT(ipfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipf_drvinit,NULL)
468 # endif /* IPFILTER_LKM */
469 #endif /* _FreeBSD_version */
473 * routines below for saving IP headers to buffer
475 int ipfopen(dev, flags
476 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
479 # if (__FreeBSD_version >= 500024)
483 # endif /* __FreeBSD_version >= 500024 */
487 #if (__FreeBSD_version >= 502116)
494 u_int unit = GET_MINOR(dev);
496 if (IPL_LOGMAX < unit)
504 int ipfclose(dev, flags
505 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
508 # if (__FreeBSD_version >= 500024)
512 # endif /* __FreeBSD_version >= 500024 */
516 #if (__FreeBSD_version >= 502116)
523 u_int unit = GET_MINOR(dev);
525 if (IPL_LOGMAX < unit)
534 * both of these must operate with at least splnet() lest they be
535 * called during packet processing and cause an inconsistancy to appear in
539 int ipfread(dev, uio, ioflag)
542 int ipfread(dev, uio)
544 #if (__FreeBSD_version >= 502116)
549 register struct uio *uio;
551 u_int unit = GET_MINOR(dev);
559 if (unit == IPL_LOGSYNC)
560 return ipfsync_read(uio);
563 return ipflog_read(unit, uio);
572 * both of these must operate with at least splnet() lest they be
573 * called during packet processing and cause an inconsistancy to appear in
577 int ipfwrite(dev, uio, ioflag)
580 int ipfwrite(dev, uio)
582 #if (__FreeBSD_version >= 502116)
587 register struct uio *uio;
593 if (GET_MINOR(dev) == IPL_LOGSYNC)
594 return ipfsync_write(uio);