4 * Copyright (C) 2012 by Darren Reed.
7 * See the IPFILTER.LICENCE file for details on licencing.
11 #include <sys/param.h>
12 #include <sys/systm.h>
13 #include <sys/kernel.h>
14 #include <sys/module.h>
16 #include <sys/socket.h>
17 #include <sys/sysctl.h>
18 #include <sys/select.h>
19 #if __FreeBSD_version >= 500000
20 # include <sys/selinfo.h>
23 #include <netinet/in_systm.h>
24 #include <netinet/in.h>
27 #include "netinet/ipl.h"
28 #include "netinet/ip_compat.h"
29 #include "netinet/ip_fil.h"
30 #include "netinet/ip_state.h"
31 #include "netinet/ip_nat.h"
32 #include "netinet/ip_auth.h"
33 #include "netinet/ip_frag.h"
34 #include "netinet/ip_sync.h"
36 extern ipf_main_softc_t ipfmain;
38 #if __FreeBSD_version >= 502116
39 static struct cdev *ipf_devs[IPL_LOGSIZE];
41 static dev_t ipf_devs[IPL_LOGSIZE];
44 static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
45 static int ipf_modload(void);
46 static int ipf_modunload(void);
47 static int ipf_fbsd_sysctl_create(ipf_main_softc_t*);
48 static int ipf_fbsd_sysctl_destroy(ipf_main_softc_t*);
50 #if (__FreeBSD_version >= 500024)
51 # if (__FreeBSD_version >= 502116)
52 static int ipfopen __P((struct cdev*, int, int, struct thread *));
53 static int ipfclose __P((struct cdev*, int, int, struct thread *));
55 static int ipfopen __P((dev_t, int, int, struct thread *));
56 static int ipfclose __P((dev_t, int, int, struct thread *));
57 # endif /* __FreeBSD_version >= 502116 */
59 static int ipfopen __P((dev_t, int, int, struct proc *));
60 static int ipfclose __P((dev_t, int, int, struct proc *));
62 #if (__FreeBSD_version >= 502116)
63 static int ipfread __P((struct cdev*, struct uio *, int));
64 static int ipfwrite __P((struct cdev*, struct uio *, int));
66 static int ipfread __P((dev_t, struct uio *, int));
67 static int ipfwrite __P((dev_t, struct uio *, int));
68 #endif /* __FreeBSD_version >= 502116 */
71 SYSCTL_DECL(_net_inet);
72 #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
73 SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
74 ptr, val, sysctl_ipf_int, "I", descr);
75 #define SYSCTL_DYN_IPF(parent, nbr, name, access,ptr, val, descr) \
76 SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
77 CTLFLAG_DYN|CTLTYPE_INT|access, ptr, val, sysctl_ipf_int, "I", descr)
78 static struct sysctl_ctx_list ipf_clist;
79 #define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */
80 #define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF)
81 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
82 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipfmain.ipf_flags, 0, "IPF flags");
83 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipfmain.ipf_pass, 0, "default pass/block");
84 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipfmain.ipf_active, 0, "IPF is active");
85 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
86 &ipfmain.ipf_tcpidletimeout, 0, "TCP idle timeout in seconds");
87 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
88 &ipfmain.ipf_tcphalfclosed, 0, "timeout for half closed TCP sessions");
89 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
90 &ipfmain.ipf_tcpclosewait, 0, "timeout for TCP sessions in closewait status");
91 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
92 &ipfmain.ipf_tcplastack, 0, "timeout for TCP sessions in last ack status");
93 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
94 &ipfmain.ipf_tcptimeout, 0, "");
95 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
96 &ipfmain.ipf_tcpclosed, 0, "");
97 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
98 &ipfmain.ipf_udptimeout, 0, "UDP timeout");
99 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
100 &ipfmain.ipf_udpacktimeout, 0, "");
101 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
102 &ipfmain.ipf_icmptimeout, 0, "ICMP timeout");
103 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
104 &ipfmain.ipf_running, 0, "IPF is running");
105 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipfmain.ipf_chksrc, 0, "");
106 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipfmain.ipf_minttl, 0, "");
108 #define CDEV_MAJOR 79
109 #include <sys/poll.h>
110 #if __FreeBSD_version >= 500043
111 # include <sys/select.h>
112 static int ipfpoll(struct cdev *dev, int events, struct thread *td);
114 static struct cdevsw ipf_cdevsw = {
115 #if __FreeBSD_version >= 502103
116 .d_version = D_VERSION,
117 .d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */
126 #if __FreeBSD_version < 600000
131 static int ipfpoll(dev_t dev, int events, struct proc *td);
133 static struct cdevsw ipf_cdevsw = {
135 /* close */ ipfclose,
137 /* write */ ipfwrite,
138 /* ioctl */ ipfioctl,
141 /* strategy */ nostrategy,
143 /* maj */ CDEV_MAJOR,
147 # if (__FreeBSD_version < 500043)
150 # if (__FreeBSD_version >= 430000)
156 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
157 IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
160 ipfilter_modevent(module_t mod, int type, void *unused)
167 error = ipf_modload();
171 error = ipf_modunload();
184 char *defpass, *c, *str;
187 if (ipf_load_all() != 0)
190 if (ipf_create_all(&ipfmain) == NULL)
193 if (ipf_fbsd_sysctl_create(&ipfmain) != 0)
196 error = ipfattach(&ipfmain);
200 for (i = 0; i < IPL_LOGSIZE; i++)
203 for (i = 0; (str = ipf_devfiles[i]); i++) {
205 for(j = strlen(str); j > 0; j--)
212 ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
215 error = ipf_pfil_hook();
220 if (FR_ISPASS(ipfmain.ipf_pass))
222 else if (FR_ISBLOCK(ipfmain.ipf_pass))
225 defpass = "no-match -> block";
227 printf("%s initialized. Default = %s all, Logging = %s%s\n",
228 ipfilter_version, defpass,
234 #ifdef IPFILTER_COMPILED
249 if (ipfmain.ipf_refcnt)
252 if (ipf_fbsd_sysctl_destroy(&ipfmain) != 0)
255 error = ipf_pfil_unhook();
259 if (ipfmain.ipf_running >= 0) {
260 error = ipfdetach(&ipfmain);
264 ipf_fbsd_sysctl_destroy(&ipfmain);
265 ipf_destroy_all(&ipfmain);
270 ipfmain.ipf_running = -2;
272 for (i = 0; ipf_devfiles[i]; i++) {
273 if (ipf_devs[i] != NULL)
274 destroy_dev(ipf_devs[i]);
277 printf("%s unloaded\n", ipfilter_version);
283 static moduledata_t ipfiltermod = {
290 DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
291 #ifdef MODULE_VERSION
292 MODULE_VERSION(ipfilter, 1);
298 sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
303 error = SYSCTL_OUT(req, arg1, sizeof(int));
305 error = SYSCTL_OUT(req, &arg2, sizeof(int));
307 if (error || !req->newptr)
313 if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0))
316 error = SYSCTL_IN(req, arg1, sizeof(int));
324 #if __FreeBSD_version >= 500043
325 ipfpoll(struct cdev *dev, int events, struct thread *td)
327 ipfpoll(dev_t dev, int events, struct proc *td)
330 int unit = GET_MINOR(dev);
333 if (unit < 0 || unit > IPL_LOGMAX)
344 if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit))
345 revents |= events & (POLLIN | POLLRDNORM);
349 if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain))
350 revents |= events & (POLLIN | POLLRDNORM);
353 if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain))
354 revents |= events & (POLLIN | POLLRDNORM);
355 if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain))
356 revents |= events & (POLLOUT | POLLWRNORM);
364 if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
365 selrecord(td, &ipfmain.ipf_selwait[unit]);
372 * routines below for saving IP headers to buffer
374 static int ipfopen(dev, flags
375 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
378 # if (__FreeBSD_version >= 500024)
382 # endif /* __FreeBSD_version >= 500024 */
386 #if (__FreeBSD_version >= 502116)
393 int unit = GET_MINOR(dev);
396 if (IPL_LOGMAX < unit)
421 static int ipfclose(dev, flags
422 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
425 # if (__FreeBSD_version >= 500024)
429 # endif /* __FreeBSD_version >= 500024 */
433 #if (__FreeBSD_version >= 502116)
440 int unit = GET_MINOR(dev);
442 if (IPL_LOGMAX < unit)
451 * both of these must operate with at least splnet() lest they be
452 * called during packet processing and cause an inconsistancy to appear in
456 static int ipfread(dev, uio, ioflag)
459 static int ipfread(dev, uio)
461 #if (__FreeBSD_version >= 502116)
468 int unit = GET_MINOR(dev);
473 if (ipfmain.ipf_running < 1)
476 if (unit == IPL_LOGSYNC)
477 return ipf_sync_read(&ipfmain, uio);
480 return ipf_log_read(&ipfmain, unit, uio);
489 * both of these must operate with at least splnet() lest they be
490 * called during packet processing and cause an inconsistancy to appear in
494 static int ipfwrite(dev, uio, ioflag)
497 static int ipfwrite(dev, uio)
499 #if (__FreeBSD_version >= 502116)
507 if (ipfmain.ipf_running < 1)
510 if (GET_MINOR(dev) == IPL_LOGSYNC)
511 return ipf_sync_write(&ipfmain, uio);
516 ipf_fbsd_sysctl_create(main_softc)
517 ipf_main_softc_t *main_softc;
519 ipf_nat_softc_t *nat_softc;
520 ipf_state_softc_t *state_softc;
521 ipf_auth_softc_t *auth_softc;
522 ipf_frag_softc_t *frag_softc;
524 nat_softc = main_softc->ipf_nat_soft;
525 state_softc = main_softc->ipf_state_soft;
526 auth_softc = main_softc->ipf_auth_soft;
527 frag_softc = main_softc->ipf_frag_soft;
529 sysctl_ctx_init(&ipf_clist);
531 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO,
532 &nat_softc->ipf_nat_defage, 0, "");
533 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO,
534 &state_softc->ipf_state_size, 0, "");
535 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO,
536 &state_softc->ipf_state_max, 0, "");
537 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO,
538 &nat_softc->ipf_nat_table_max, 0, "");
539 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO,
540 &nat_softc->ipf_nat_table_sz, 0, "");
541 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO,
542 &nat_softc->ipf_nat_maprules_sz, 0, "");
543 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO,
544 &nat_softc->ipf_nat_rdrrules_sz, 0, "");
545 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO,
546 &nat_softc->ipf_nat_hostmap_sz, 0, "");
547 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO,
548 &auth_softc->ipf_auth_size, 0, "");
549 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD,
550 &auth_softc->ipf_auth_used, 0, "");
551 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW,
552 &auth_softc->ipf_auth_defaultage, 0, "");
553 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW,
554 &frag_softc->ipfr_ttl, 0, "");
559 ipf_fbsd_sysctl_destroy(main_softc)
560 ipf_main_softc_t *main_softc;
562 if (sysctl_ctx_free(&ipf_clist)) {
563 printf("sysctl_ctx_free failed");