1/*	$FreeBSD: releng/10.3/sys/contrib/ipfilter/netinet/mlfk_ipl.c 266829 2014-05-29 02:55:07Z cy $	*/
2
3/*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * $FreeBSD: releng/10.3/sys/contrib/ipfilter/netinet/mlfk_ipl.c 266829 2014-05-29 02:55:07Z cy $
7 * See the IPFILTER.LICENCE file for details on licencing.
8 */
9
10
11#include <sys/param.h>
12#include <sys/systm.h>
13#include <sys/kernel.h>
14#include <sys/module.h>
15#include <sys/conf.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>
21#endif
22#include <net/if.h>
23#include <netinet/in_systm.h>
24#include <netinet/in.h>
25
26
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"
35
36extern ipf_main_softc_t ipfmain;
37
38#if __FreeBSD_version >= 502116
39static struct cdev *ipf_devs[IPL_LOGSIZE];
40#else
41static dev_t ipf_devs[IPL_LOGSIZE];
42#endif
43
44static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
45static int ipf_modload(void);
46static int ipf_modunload(void);
47static int ipf_fbsd_sysctl_create(ipf_main_softc_t*);
48static int ipf_fbsd_sysctl_destroy(ipf_main_softc_t*);
49
50#if (__FreeBSD_version >= 500024)
51# if (__FreeBSD_version >= 502116)
52static	int	ipfopen __P((struct cdev*, int, int, struct thread *));
53static	int	ipfclose __P((struct cdev*, int, int, struct thread *));
54# else
55static	int	ipfopen __P((dev_t, int, int, struct thread *));
56static	int	ipfclose __P((dev_t, int, int, struct thread *));
57# endif /* __FreeBSD_version >= 502116 */
58#else
59static	int	ipfopen __P((dev_t, int, int, struct proc *));
60static	int	ipfclose __P((dev_t, int, int, struct proc *));
61#endif
62#if (__FreeBSD_version >= 502116)
63static	int	ipfread __P((struct cdev*, struct uio *, int));
64static	int	ipfwrite __P((struct cdev*, struct uio *, int));
65#else
66static	int	ipfread __P((dev_t, struct uio *, int));
67static	int	ipfwrite __P((dev_t, struct uio *, int));
68#endif /* __FreeBSD_version >= 502116 */
69
70
71SYSCTL_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)
78static struct sysctl_ctx_list ipf_clist;
79#define	CTLFLAG_OFF	0x00800000	/* IPFilter must be disabled */
80#define	CTLFLAG_RWO	(CTLFLAG_RW|CTLFLAG_OFF)
81SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
82SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipfmain.ipf_flags, 0, "IPF flags");
83SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipfmain.ipf_pass, 0, "default pass/block");
84SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipfmain.ipf_active, 0, "IPF is active");
85SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
86	   &ipfmain.ipf_tcpidletimeout, 0, "TCP idle timeout in seconds");
87SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
88	   &ipfmain.ipf_tcphalfclosed, 0, "timeout for half closed TCP sessions");
89SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
90	   &ipfmain.ipf_tcpclosewait, 0, "timeout for TCP sessions in closewait status");
91SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
92	   &ipfmain.ipf_tcplastack, 0, "timeout for TCP sessions in last ack status");
93SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
94	   &ipfmain.ipf_tcptimeout, 0, "");
95SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
96	   &ipfmain.ipf_tcpclosed, 0, "");
97SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
98	   &ipfmain.ipf_udptimeout, 0, "UDP timeout");
99SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
100	   &ipfmain.ipf_udpacktimeout, 0, "");
101SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
102	   &ipfmain.ipf_icmptimeout, 0, "ICMP timeout");
103SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
104	   &ipfmain.ipf_running, 0, "IPF is running");
105SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipfmain.ipf_chksrc, 0, "");
106SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipfmain.ipf_minttl, 0, "");
107
108#define CDEV_MAJOR 79
109#include <sys/poll.h>
110#if __FreeBSD_version >= 500043
111# include <sys/select.h>
112static int ipfpoll(struct cdev *dev, int events, struct thread *td);
113
114static struct cdevsw ipf_cdevsw = {
115#if __FreeBSD_version >= 502103
116	.d_version =	D_VERSION,
117	.d_flags =	0,	/* D_NEEDGIANT - Should be SMP safe */
118#endif
119	.d_open =	ipfopen,
120	.d_close =	ipfclose,
121	.d_read =	ipfread,
122	.d_write =	ipfwrite,
123	.d_ioctl =	ipfioctl,
124	.d_poll =	ipfpoll,
125	.d_name =	"ipf",
126#if __FreeBSD_version < 600000
127	.d_maj =	CDEV_MAJOR,
128#endif
129};
130#else
131static int ipfpoll(dev_t dev, int events, struct proc *td);
132
133static struct cdevsw ipf_cdevsw = {
134	/* open */	ipfopen,
135	/* close */	ipfclose,
136	/* read */	ipfread,
137	/* write */	ipfwrite,
138	/* ioctl */	ipfioctl,
139	/* poll */	ipfpoll,
140	/* mmap */	nommap,
141	/* strategy */	nostrategy,
142	/* name */	"ipf",
143	/* maj */	CDEV_MAJOR,
144	/* dump */	nodump,
145	/* psize */	nopsize,
146	/* flags */	0,
147# if (__FreeBSD_version < 500043)
148	/* bmaj */	-1,
149# endif
150# if (__FreeBSD_version >= 430000)
151	/* kqfilter */	NULL
152# endif
153};
154#endif
155
156static char *ipf_devfiles[] = {	IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
157				IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
158
159static int
160ipfilter_modevent(module_t mod, int type, void *unused)
161{
162	int error = 0;
163
164	switch (type)
165	{
166	case MOD_LOAD :
167		error = ipf_modload();
168		break;
169
170	case MOD_UNLOAD :
171		error = ipf_modunload();
172		break;
173	default:
174		error = EINVAL;
175		break;
176	}
177	return error;
178}
179
180
181static int
182ipf_modload()
183{
184	char *defpass, *c, *str;
185	int i, j, error;
186
187	if (ipf_load_all() != 0)
188		return EIO;
189
190	if (ipf_create_all(&ipfmain) == NULL)
191		return EIO;
192
193	if (ipf_fbsd_sysctl_create(&ipfmain) != 0)
194		return EIO;
195
196	error = ipfattach(&ipfmain);
197	if (error)
198		return error;
199
200	for (i = 0; i < IPL_LOGSIZE; i++)
201		ipf_devs[i] = NULL;
202
203	for (i = 0; (str = ipf_devfiles[i]); i++) {
204		c = NULL;
205		for(j = strlen(str); j > 0; j--)
206			if (str[j] == '/') {
207				c = str + j + 1;
208				break;
209			}
210		if (!c)
211			c = str;
212		ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
213	}
214
215	error = ipf_pfil_hook();
216	if (error != 0)
217		return error;
218	ipf_event_reg();
219
220	if (FR_ISPASS(ipfmain.ipf_pass))
221		defpass = "pass";
222	else if (FR_ISBLOCK(ipfmain.ipf_pass))
223		defpass = "block";
224	else
225		defpass = "no-match -> block";
226
227	printf("%s initialized.  Default = %s all, Logging = %s%s\n",
228		ipfilter_version, defpass,
229#ifdef IPFILTER_LOG
230		"enabled",
231#else
232		"disabled",
233#endif
234#ifdef IPFILTER_COMPILED
235		" (COMPILED)"
236#else
237		""
238#endif
239		);
240	return 0;
241}
242
243
244static int
245ipf_modunload()
246{
247	int error, i;
248
249	if (ipfmain.ipf_refcnt)
250		return EBUSY;
251
252	if (ipf_fbsd_sysctl_destroy(&ipfmain) != 0)
253		return EIO;
254
255	error = ipf_pfil_unhook();
256	if (error != 0)
257		return error;
258
259	if (ipfmain.ipf_running >= 0) {
260		error = ipfdetach(&ipfmain);
261		if (error != 0)
262			return error;
263
264		ipf_fbsd_sysctl_destroy(&ipfmain);
265		ipf_destroy_all(&ipfmain);
266		ipf_unload_all();
267	} else
268		error = 0;
269
270	ipfmain.ipf_running = -2;
271
272	for (i = 0; ipf_devfiles[i]; i++) {
273		if (ipf_devs[i] != NULL)
274			destroy_dev(ipf_devs[i]);
275	}
276
277	printf("%s unloaded\n", ipfilter_version);
278
279	return error;
280}
281
282
283static moduledata_t ipfiltermod = {
284	"ipfilter",
285	ipfilter_modevent,
286	0
287};
288
289
290DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
291#ifdef	MODULE_VERSION
292MODULE_VERSION(ipfilter, 1);
293#endif
294
295
296#ifdef SYSCTL_IPF
297int
298sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
299{
300	int error = 0;
301
302	if (arg1)
303		error = SYSCTL_OUT(req, arg1, sizeof(int));
304	else
305		error = SYSCTL_OUT(req, &arg2, sizeof(int));
306
307	if (error || !req->newptr)
308		return (error);
309
310	if (!arg1)
311		error = EPERM;
312	else {
313		if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0))
314			error = EBUSY;
315		else
316			error = SYSCTL_IN(req, arg1, sizeof(int));
317	}
318	return (error);
319}
320#endif
321
322
323static int
324#if __FreeBSD_version >= 500043
325ipfpoll(struct cdev *dev, int events, struct thread *td)
326#else
327ipfpoll(dev_t dev, int events, struct proc *td)
328#endif
329{
330	int unit = GET_MINOR(dev);
331	int revents;
332
333	if (unit < 0 || unit > IPL_LOGMAX)
334		return 0;
335
336	revents = 0;
337
338	switch (unit)
339	{
340	case IPL_LOGIPF :
341	case IPL_LOGNAT :
342	case IPL_LOGSTATE :
343#ifdef IPFILTER_LOG
344		if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit))
345			revents |= events & (POLLIN | POLLRDNORM);
346#endif
347		break;
348	case IPL_LOGAUTH :
349		if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain))
350			revents |= events & (POLLIN | POLLRDNORM);
351		break;
352	case IPL_LOGSYNC :
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);
357		break;
358	case IPL_LOGSCAN :
359	case IPL_LOGLOOKUP :
360	default :
361		break;
362	}
363
364	if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
365		selrecord(td, &ipfmain.ipf_selwait[unit]);
366
367	return revents;
368}
369
370
371/*
372 * routines below for saving IP headers to buffer
373 */
374static int ipfopen(dev, flags
375#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
376, devtype, p)
377	int devtype;
378# if (__FreeBSD_version >= 500024)
379	struct thread *p;
380# else
381	struct proc *p;
382# endif /* __FreeBSD_version >= 500024 */
383#else
384)
385#endif
386#if (__FreeBSD_version >= 502116)
387	struct cdev *dev;
388#else
389	dev_t dev;
390#endif
391	int flags;
392{
393	int unit = GET_MINOR(dev);
394	int error;
395
396	if (IPL_LOGMAX < unit)
397		error = ENXIO;
398	else {
399		switch (unit)
400		{
401		case IPL_LOGIPF :
402		case IPL_LOGNAT :
403		case IPL_LOGSTATE :
404		case IPL_LOGAUTH :
405		case IPL_LOGLOOKUP :
406		case IPL_LOGSYNC :
407#ifdef IPFILTER_SCAN
408		case IPL_LOGSCAN :
409#endif
410			error = 0;
411			break;
412		default :
413			error = ENXIO;
414			break;
415		}
416	}
417	return error;
418}
419
420
421static int ipfclose(dev, flags
422#if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
423, devtype, p)
424	int devtype;
425# if (__FreeBSD_version >= 500024)
426	struct thread *p;
427# else
428	struct proc *p;
429# endif /* __FreeBSD_version >= 500024 */
430#else
431)
432#endif
433#if (__FreeBSD_version >= 502116)
434	struct cdev *dev;
435#else
436	dev_t dev;
437#endif
438	int flags;
439{
440	int	unit = GET_MINOR(dev);
441
442	if (IPL_LOGMAX < unit)
443		unit = ENXIO;
444	else
445		unit = 0;
446	return unit;
447}
448
449/*
450 * ipfread/ipflog
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
453 * the filter lists.
454 */
455#if (BSD >= 199306)
456static int ipfread(dev, uio, ioflag)
457	int ioflag;
458#else
459static int ipfread(dev, uio)
460#endif
461#if (__FreeBSD_version >= 502116)
462	struct cdev *dev;
463#else
464	dev_t dev;
465#endif
466	struct uio *uio;
467{
468	int	unit = GET_MINOR(dev);
469
470	if (unit < 0)
471		return ENXIO;
472
473	if (ipfmain.ipf_running < 1)
474		return EIO;
475
476	if (unit == IPL_LOGSYNC)
477		return ipf_sync_read(&ipfmain, uio);
478
479#ifdef IPFILTER_LOG
480	return ipf_log_read(&ipfmain, unit, uio);
481#else
482	return ENXIO;
483#endif
484}
485
486
487/*
488 * ipfwrite
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
491 * the filter lists.
492 */
493#if (BSD >= 199306)
494static int ipfwrite(dev, uio, ioflag)
495	int ioflag;
496#else
497static int ipfwrite(dev, uio)
498#endif
499#if (__FreeBSD_version >= 502116)
500	struct cdev *dev;
501#else
502	dev_t dev;
503#endif
504	struct uio *uio;
505{
506
507	if (ipfmain.ipf_running < 1)
508		return EIO;
509
510	if (GET_MINOR(dev) == IPL_LOGSYNC)
511		return ipf_sync_write(&ipfmain, uio);
512	return ENXIO;
513}
514
515static int
516ipf_fbsd_sysctl_create(main_softc)
517	ipf_main_softc_t *main_softc;
518{
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;
523
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;
528
529	sysctl_ctx_init(&ipf_clist);
530
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, "");
555	return 0;
556}
557
558static int
559ipf_fbsd_sysctl_destroy(main_softc)
560	ipf_main_softc_t *main_softc;
561{
562	if (sysctl_ctx_free(&ipf_clist)) {
563		printf("sysctl_ctx_free failed");
564		return(ENOTEMPTY);
565	}
566	return 0;
567}
568
569