4 * Copyright (C) 2012 by Darren Reed.
7 * See the IPFILTER.LICENCE file for details on licencing.
10 #if defined(KERNEL) || defined(_KERNEL)
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/kernel.h>
20 #include <sys/module.h>
22 #include <sys/socket.h>
23 #include <sys/sysctl.h>
24 #include <sys/select.h>
26 # include <sys/selinfo.h>
27 # include <sys/jail.h>
29 # include <net/vnet.h>
31 # define CURVNET_SET(arg)
32 # define CURVNET_RESTORE()
33 # define VNET_DEFINE(_t, _v) _t _v
34 # define VNET_DECLARE(_t, _v) extern _t _v
35 # define VNET(arg) arg
39 #include <netinet/in_systm.h>
40 #include <netinet/in.h>
43 #include "netinet/ipl.h"
44 #include "netinet/ip_compat.h"
45 #include "netinet/ip_fil.h"
46 #include "netinet/ip_state.h"
47 #include "netinet/ip_nat.h"
48 #include "netinet/ip_auth.h"
49 #include "netinet/ip_frag.h"
50 #include "netinet/ip_sync.h"
52 VNET_DECLARE(ipf_main_softc_t, ipfmain);
53 #define V_ipfmain VNET(ipfmain)
56 static struct cdev *ipf_devs[IPL_LOGSIZE];
58 static dev_t ipf_devs[IPL_LOGSIZE];
61 static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
62 static int sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS );
63 static int sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS );
64 static int sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS );
65 static int sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS );
66 static int ipf_modload(void);
67 static int ipf_modunload(void);
68 static int ipf_fbsd_sysctl_create(void);
69 static int ipf_fbsd_sysctl_destroy(void);
72 static int ipfopen(struct cdev*, int, int, struct thread *);
73 static int ipfclose(struct cdev*, int, int, struct thread *);
74 static int ipfread(struct cdev*, struct uio *, int);
75 static int ipfwrite(struct cdev*, struct uio *, int);
77 static int ipfopen(dev_t, int, int, struct proc *);
78 static int ipfclose(dev_t, int, int, struct proc *);
79 static int ipfread(dev_t, struct uio *, int);
80 static int ipfwrite(dev_t, struct uio *, int);
84 #define IPF_LARGE_NAT 1
86 #define IPF_LARGE_NAT 0
89 SYSCTL_DECL(_net_inet);
90 #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
91 SYSCTL_OID(parent, nbr, name, \
92 CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
93 ptr, val, sysctl_ipf_int, "I", descr)
94 #define SYSCTL_DYN_IPF_NAT(parent, nbr, name, access,ptr, val, descr) \
95 SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
96 CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE |access, \
97 ptr, val, sysctl_ipf_int_nat, "I", descr)
98 #define SYSCTL_DYN_IPF_STATE(parent, nbr, name, access,ptr, val, descr) \
99 SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
100 CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
101 ptr, val, sysctl_ipf_int_state, "I", descr)
102 #define SYSCTL_DYN_IPF_FRAG(parent, nbr, name, access,ptr, val, descr) \
103 SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
104 CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
105 ptr, val, sysctl_ipf_int_frag, "I", descr)
106 #define SYSCTL_DYN_IPF_AUTH(parent, nbr, name, access,ptr, val, descr) \
107 SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
108 CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_MPSAFE | access, \
109 ptr, val, sysctl_ipf_int_auth, "I", descr)
110 static struct sysctl_ctx_list ipf_clist;
111 #define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */
112 #define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF)
113 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
115 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_flags), 0, "IPF flags");
116 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_pass), 0, "default pass/block");
117 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &VNET_NAME(ipfmain.ipf_active), 0, "IPF is active");
118 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
119 &VNET_NAME(ipfmain.ipf_tcpidletimeout), 0, "TCP idle timeout in seconds");
120 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
121 &VNET_NAME(ipfmain.ipf_tcphalfclosed), 0, "timeout for half closed TCP sessions");
122 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
123 &VNET_NAME(ipfmain.ipf_tcpclosewait), 0, "timeout for TCP sessions in closewait status");
124 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
125 &VNET_NAME(ipfmain.ipf_tcplastack), 0, "timeout for TCP sessions in last ack status");
126 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
127 &VNET_NAME(ipfmain.ipf_tcptimeout), 0, "");
128 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
129 &VNET_NAME(ipfmain.ipf_tcpclosed), 0, "");
130 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
131 &VNET_NAME(ipfmain.ipf_udptimeout), 0, "UDP timeout");
132 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
133 &VNET_NAME(ipfmain.ipf_udpacktimeout), 0, "");
134 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
135 &VNET_NAME(ipfmain.ipf_icmptimeout), 0, "ICMP timeout");
136 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
137 &VNET_NAME(ipfmain.ipf_running), 0, "IPF is running");
138 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_chksrc), 0, "");
139 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_minttl), 0, "");
140 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, large_nat, CTLFLAG_RD, &VNET_NAME(ipfmain.ipf_large_nat), 0, "large_nat");
142 #define CDEV_MAJOR 79
143 #include <sys/poll.h>
145 # include <sys/select.h>
146 static int ipfpoll(struct cdev *dev, int events, struct thread *td);
148 static struct cdevsw ipf_cdevsw = {
149 .d_version = D_VERSION,
150 .d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */
160 static int ipfpoll(dev_t dev, int events, struct proc *td);
162 static struct cdevsw ipf_cdevsw = {
164 /* close */ ipfclose,
166 /* write */ ipfwrite,
167 /* ioctl */ ipfioctl,
170 /* strategy */ nostrategy,
172 /* maj */ CDEV_MAJOR,
179 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
180 IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
183 ipfilter_modevent(module_t mod, int type, void *unused)
190 error = ipf_modload();
194 error = ipf_modunload();
210 if (ipf_create_all(&V_ipfmain) == NULL)
213 error = ipfattach(&V_ipfmain);
215 ipf_destroy_all(&V_ipfmain);
219 if (FR_ISPASS(V_ipfmain.ipf_pass))
221 else if (FR_ISBLOCK(V_ipfmain.ipf_pass))
224 defpass = "no-match -> block";
226 if (IS_DEFAULT_VNET(curvnet)) {
227 printf("%s initialized. Default = %s all, Logging = %s%s\n",
228 ipfilter_version, defpass,
234 #ifdef IPFILTER_COMPILED
241 (void)ipf_pfil_hook();
245 VNET_SYSINIT(vnet_ipf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
246 vnet_ipf_init, NULL);
254 if (ipf_load_all() != 0)
257 if (ipf_fbsd_sysctl_create() != 0) {
261 for (i = 0; i < IPL_LOGSIZE; i++)
263 for (i = 0; (str = ipf_devfiles[i]); i++) {
265 for(j = strlen(str); j > 0; j--)
272 ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
275 error = ipf_pfil_hook();
284 vnet_ipf_uninit(void)
287 if (V_ipfmain.ipf_refcnt)
290 if (V_ipfmain.ipf_running >= 0) {
292 if (ipfdetach(&V_ipfmain) != 0)
295 V_ipfmain.ipf_running = -2;
297 ipf_destroy_all(&V_ipfmain);
298 if (!IS_DEFAULT_VNET(curvnet)) {
300 (void)ipf_pfil_unhook();
304 VNET_SYSUNINIT(vnet_ipf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
305 vnet_ipf_uninit, NULL);
314 ipf_fbsd_sysctl_destroy();
316 error = ipf_pfil_unhook();
320 for (i = 0; ipf_devfiles[i]; i++) {
321 if (ipf_devs[i] != NULL)
322 destroy_dev(ipf_devs[i]);
327 printf("%s unloaded\n", ipfilter_version);
333 static moduledata_t ipfiltermod = {
340 DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
341 #ifdef MODULE_VERSION
342 MODULE_VERSION(ipfilter, 1);
348 sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
353 error = SYSCTL_OUT(req, arg1, sizeof(int));
355 error = SYSCTL_OUT(req, &arg2, sizeof(int));
357 if (error || !req->newptr)
363 if ((oidp->oid_kind & CTLFLAG_OFF) && (V_ipfmain.ipf_running > 0))
366 error = SYSCTL_IN(req, arg1, sizeof(int));
374 * arg2 holds the offset of the relevant member in the virtualized
378 sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS )
380 ipf_nat_softc_t *nat_softc;
382 nat_softc = V_ipfmain.ipf_nat_soft;
383 arg1 = (void *)((uintptr_t)nat_softc + arg2);
385 return(sysctl_ipf_int(oidp, arg1, 0, req));
389 sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS )
391 ipf_state_softc_t *state_softc;
393 state_softc = V_ipfmain.ipf_state_soft;
394 arg1 = (void *)((uintptr_t)state_softc + arg2);
396 return(sysctl_ipf_int(oidp, arg1, 0, req));
400 sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS )
402 ipf_auth_softc_t *auth_softc;
404 auth_softc = V_ipfmain.ipf_auth_soft;
405 arg1 = (void *)((uintptr_t)auth_softc + arg2);
407 return(sysctl_ipf_int(oidp, arg1, 0, req));
411 sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS )
413 ipf_frag_softc_t *frag_softc;
415 frag_softc = V_ipfmain.ipf_frag_soft;
416 arg1 = (void *)((uintptr_t)frag_softc + arg2);
418 return(sysctl_ipf_int(oidp, arg1, 0, req));
425 ipfpoll(struct cdev *dev, int events, struct thread *td)
427 ipfpoll(dev_t dev, int events, struct proc *td)
430 int unit = GET_MINOR(dev);
433 if (unit < 0 || unit > IPL_LOGMAX)
438 CURVNET_SET(TD_TO_VNET(td));
445 if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&V_ipfmain, unit))
446 revents |= events & (POLLIN | POLLRDNORM);
450 if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&V_ipfmain))
451 revents |= events & (POLLIN | POLLRDNORM);
454 if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&V_ipfmain))
455 revents |= events & (POLLIN | POLLRDNORM);
456 if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&V_ipfmain))
457 revents |= events & (POLLOUT | POLLWRNORM);
465 if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
466 selrecord(td, &V_ipfmain.ipf_selwait[unit]);
474 * routines below for saving IP headers to buffer
478 ipfopen(struct cdev *dev, int flags, int devtype, struct thread *p)
480 ipfopen(dev_t dev, int flags)
483 int unit = GET_MINOR(dev);
486 if (IPL_LOGMAX < unit)
513 ipfclose(struct cdev *dev, int flags, int devtype, struct thread *p)
515 ipfclose(dev_t dev, int flags)
518 int unit = GET_MINOR(dev);
520 if (IPL_LOGMAX < unit)
529 * both of these must operate with at least splnet() lest they be
530 * called during packet processing and cause an inconsistancy to appear in
533 static int ipfread(dev, uio, ioflag)
543 int unit = GET_MINOR(dev);
548 CURVNET_SET(TD_TO_VNET(curthread));
549 if (V_ipfmain.ipf_running < 1) {
554 if (unit == IPL_LOGSYNC) {
555 error = ipf_sync_read(&V_ipfmain, uio);
561 error = ipf_log_read(&V_ipfmain, 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
576 static int ipfwrite(dev, uio, ioflag)
587 CURVNET_SET(TD_TO_VNET(curthread));
588 if (V_ipfmain.ipf_running < 1) {
593 if (GET_MINOR(dev) == IPL_LOGSYNC) {
594 error = ipf_sync_write(&V_ipfmain, uio);
602 ipf_fbsd_sysctl_create(void)
605 sysctl_ctx_init(&ipf_clist);
607 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO,
608 NULL, offsetof(ipf_nat_softc_t, ipf_nat_defage), "");
609 SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO,
610 NULL, offsetof(ipf_state_softc_t, ipf_state_size), "");
611 SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO,
612 NULL, offsetof(ipf_state_softc_t, ipf_state_max), "");
613 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO,
614 NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_max), "");
615 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO,
616 NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_sz), "");
617 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO,
618 NULL, offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz), "");
619 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO,
620 NULL, offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), "");
621 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO,
622 NULL, offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz), "");
623 SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO,
624 NULL, offsetof(ipf_auth_softc_t, ipf_auth_size), "");
625 SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD,
626 NULL, offsetof(ipf_auth_softc_t, ipf_auth_used), "");
627 SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW,
628 NULL, offsetof(ipf_auth_softc_t, ipf_auth_defaultage), "");
629 SYSCTL_DYN_IPF_FRAG(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW,
630 NULL, offsetof(ipf_frag_softc_t, ipfr_ttl), "");
635 ipf_fbsd_sysctl_destroy(void)
637 if (sysctl_ctx_free(&ipf_clist)) {
638 printf("sysctl_ctx_free failed");