1 /*	$FreeBSD$	*/
2 
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * $FreeBSD$
7  * See the IPFILTER.LICENCE file for details on licencing.
8  */
9 
10 #if defined(KERNEL) || defined(_KERNEL)
11 # undef KERNEL
12 # undef _KERNEL
13 # define	KERNEL  1
14 # define	_KERNEL 1
15 #endif
16 
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/kernel.h>
20 #include <sys/module.h>
21 #include <sys/conf.h>
22 #include <sys/socket.h>
23 #include <sys/sysctl.h>
24 #include <sys/select.h>
25 #ifdef __FreeBSD_version
26 # include <sys/selinfo.h>
27 # include <sys/jail.h>
28 # ifdef _KERNEL
29 #  include <net/vnet.h>
30 # else
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
36 # endif
37 #endif
38 #include <net/if.h>
39 #include <netinet/in_systm.h>
40 #include <netinet/in.h>
41 
42 
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"
51 
52 VNET_DECLARE(ipf_main_softc_t, ipfmain);
53 #define	V_ipfmain		VNET(ipfmain)
54 
55 #ifdef __FreeBSD_version
56 static struct cdev *ipf_devs[IPL_LOGSIZE];
57 #else
58 static dev_t ipf_devs[IPL_LOGSIZE];
59 #endif
60 
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);
70 
71 #ifdef __FreeBSD_version
72 static	int	ipfopen __P((struct cdev*, int, int, struct thread *));
73 static	int	ipfclose __P((struct cdev*, int, int, struct thread *));
74 static	int	ipfread __P((struct cdev*, struct uio *, int));
75 static	int	ipfwrite __P((struct cdev*, struct uio *, int));
76 #else
77 static	int	ipfopen __P((dev_t, int, int, struct proc *));
78 static	int	ipfclose __P((dev_t, int, int, struct proc *));
79 static	int	ipfread __P((dev_t, struct uio *, int));
80 static	int	ipfwrite __P((dev_t, struct uio *, int));
81 #endif
82 
83 
84 SYSCTL_DECL(_net_inet);
85 #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
86 	SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|CTLFLAG_VNET|access, \
87 		   ptr, val, sysctl_ipf_int, "I", descr)
88 #define SYSCTL_DYN_IPF_NAT(parent, nbr, name, access,ptr, val, descr) \
89 	SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
90 	CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_nat, "I", descr)
91 #define SYSCTL_DYN_IPF_STATE(parent, nbr, name, access,ptr, val, descr) \
92 	SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
93 	CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_state, "I", descr)
94 #define SYSCTL_DYN_IPF_FRAG(parent, nbr, name, access,ptr, val, descr) \
95 	SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
96 	CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_frag, "I", descr)
97 #define SYSCTL_DYN_IPF_AUTH(parent, nbr, name, access,ptr, val, descr) \
98 	SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \
99 	CTLFLAG_DYN|CTLTYPE_INT|CTLFLAG_VNET|access, ptr, val, sysctl_ipf_int_auth, "I", descr)
100 static struct sysctl_ctx_list ipf_clist;
101 #define	CTLFLAG_OFF	0x00800000	/* IPFilter must be disabled */
102 #define	CTLFLAG_RWO	(CTLFLAG_RW|CTLFLAG_OFF)
103 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
104 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_flags), 0, "IPF flags");
105 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_pass), 0, "default pass/block");
106 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &VNET_NAME(ipfmain.ipf_active), 0, "IPF is active");
107 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
108 	   &VNET_NAME(ipfmain.ipf_tcpidletimeout), 0, "TCP idle timeout in seconds");
109 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
110 	   &VNET_NAME(ipfmain.ipf_tcphalfclosed), 0, "timeout for half closed TCP sessions");
111 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
112 	   &VNET_NAME(ipfmain.ipf_tcpclosewait), 0, "timeout for TCP sessions in closewait status");
113 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
114 	   &VNET_NAME(ipfmain.ipf_tcplastack), 0, "timeout for TCP sessions in last ack status");
115 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
116 	   &VNET_NAME(ipfmain.ipf_tcptimeout), 0, "");
117 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
118 	   &VNET_NAME(ipfmain.ipf_tcpclosed), 0, "");
119 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
120 	   &VNET_NAME(ipfmain.ipf_udptimeout), 0, "UDP timeout");
121 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
122 	   &VNET_NAME(ipfmain.ipf_udpacktimeout), 0, "");
123 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
124 	   &VNET_NAME(ipfmain.ipf_icmptimeout), 0, "ICMP timeout");
125 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
126 	   &VNET_NAME(ipfmain.ipf_running), 0, "IPF is running");
127 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_chksrc), 0, "");
128 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_minttl), 0, "");
129 
130 #define CDEV_MAJOR 79
131 #include <sys/poll.h>
132 #ifdef __FreeBSD_version
133 # include <sys/select.h>
134 static int ipfpoll(struct cdev *dev, int events, struct thread *td);
135 
136 static struct cdevsw ipf_cdevsw = {
137 	.d_version =	D_VERSION,
138 	.d_flags =	0,	/* D_NEEDGIANT - Should be SMP safe */
139 	.d_open =	ipfopen,
140 	.d_close =	ipfclose,
141 	.d_read =	ipfread,
142 	.d_write =	ipfwrite,
143 	.d_ioctl =	ipfioctl,
144 	.d_poll =	ipfpoll,
145 	.d_name =	"ipf",
146 };
147 #else
148 static int ipfpoll(dev_t dev, int events, struct proc *td);
149 
150 static struct cdevsw ipf_cdevsw = {
151 	/* open */	ipfopen,
152 	/* close */	ipfclose,
153 	/* read */	ipfread,
154 	/* write */	ipfwrite,
155 	/* ioctl */	ipfioctl,
156 	/* poll */	ipfpoll,
157 	/* mmap */	nommap,
158 	/* strategy */	nostrategy,
159 	/* name */	"ipf",
160 	/* maj */	CDEV_MAJOR,
161 	/* dump */	nodump,
162 	/* psize */	nopsize,
163 	/* flags */	0,
164 };
165 #endif
166 
167 static char *ipf_devfiles[] = {	IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
168 				IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
169 
170 static int
ipfilter_modevent(module_t mod,int type,void * unused)171 ipfilter_modevent(module_t mod, int type, void *unused)
172 {
173 	int error = 0;
174 
175 	switch (type)
176 	{
177 	case MOD_LOAD :
178 		error = ipf_modload();
179 		break;
180 
181 	case MOD_UNLOAD :
182 		error = ipf_modunload();
183 		break;
184 	default:
185 		error = EINVAL;
186 		break;
187 	}
188 	return error;
189 }
190 
191 
192 static void
vnet_ipf_init(void)193 vnet_ipf_init(void)
194 {
195 	char *defpass;
196 	int error;
197 
198 	if (ipf_create_all(&V_ipfmain) == NULL)
199 		return;
200 
201 	error = ipfattach(&V_ipfmain);
202 	if (error) {
203 		ipf_destroy_all(&V_ipfmain);
204 		return;
205 	}
206 
207 	if (FR_ISPASS(V_ipfmain.ipf_pass))
208 		defpass = "pass";
209 	else if (FR_ISBLOCK(V_ipfmain.ipf_pass))
210 		defpass = "block";
211 	else
212 		defpass = "no-match -> block";
213 
214 	if (IS_DEFAULT_VNET(curvnet)) {
215 	    printf("%s initialized.  Default = %s all, Logging = %s%s\n",
216 		ipfilter_version, defpass,
217 #ifdef IPFILTER_LOG
218 		"enabled",
219 #else
220 		"disabled",
221 #endif
222 #ifdef IPFILTER_COMPILED
223 		" (COMPILED)"
224 #else
225 		""
226 #endif
227 		);
228 	} else {
229 		(void)ipf_pfil_hook();
230 		ipf_event_reg();
231 	}
232 }
233 VNET_SYSINIT(vnet_ipf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
234     vnet_ipf_init, NULL);
235 
236 static int
ipf_modload()237 ipf_modload()
238 {
239 	char *c, *str;
240 	int i, j, error;
241 
242 	if (ipf_load_all() != 0)
243 		return EIO;
244 
245 	if (ipf_fbsd_sysctl_create() != 0) {
246 		return EIO;
247 	}
248 
249 	for (i = 0; i < IPL_LOGSIZE; i++)
250 		ipf_devs[i] = NULL;
251 	for (i = 0; (str = ipf_devfiles[i]); i++) {
252 		c = NULL;
253 		for(j = strlen(str); j > 0; j--)
254 			if (str[j] == '/') {
255 				c = str + j + 1;
256 				break;
257 			}
258 		if (!c)
259 			c = str;
260 		ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
261 	}
262 
263 	error = ipf_pfil_hook();
264 	if (error != 0)
265 		return error;
266 	ipf_event_reg();
267 
268 	return 0;
269 }
270 
271 static void
vnet_ipf_uninit(void)272 vnet_ipf_uninit(void)
273 {
274 
275 	if (V_ipfmain.ipf_refcnt)
276 		return;
277 
278 	if (V_ipfmain.ipf_running >= 0) {
279 
280 		if (ipfdetach(&V_ipfmain) != 0)
281 			return;
282 
283 		V_ipfmain.ipf_running = -2;
284 
285 		ipf_destroy_all(&V_ipfmain);
286 		if (!IS_DEFAULT_VNET(curvnet)) {
287 			ipf_event_dereg();
288 			(void)ipf_pfil_unhook();
289 		}
290 	}
291 }
292 VNET_SYSUNINIT(vnet_ipf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
293     vnet_ipf_uninit, NULL);
294 
295 static int
ipf_modunload()296 ipf_modunload()
297 {
298 	int error, i;
299 
300 	ipf_event_dereg();
301 
302 	ipf_fbsd_sysctl_destroy();
303 
304 	error = ipf_pfil_unhook();
305 	if (error != 0)
306 		return error;
307 
308 	for (i = 0; ipf_devfiles[i]; i++) {
309 		if (ipf_devs[i] != NULL)
310 			destroy_dev(ipf_devs[i]);
311 	}
312 
313 	ipf_unload_all();
314 
315 	printf("%s unloaded\n", ipfilter_version);
316 
317 	return (0);
318 }
319 
320 
321 static moduledata_t ipfiltermod = {
322 	"ipfilter",
323 	ipfilter_modevent,
324 	0
325 };
326 
327 
328 DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
329 #ifdef	MODULE_VERSION
330 MODULE_VERSION(ipfilter, 1);
331 #endif
332 
333 
334 #ifdef SYSCTL_IPF
335 int
sysctl_ipf_int(SYSCTL_HANDLER_ARGS)336 sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
337 {
338 	int error = 0;
339 
340 	if (arg1)
341 		error = SYSCTL_OUT(req, arg1, sizeof(int));
342 	else
343 		error = SYSCTL_OUT(req, &arg2, sizeof(int));
344 
345 	if (error || !req->newptr)
346 		return (error);
347 
348 	if (!arg1)
349 		error = EPERM;
350 	else {
351 		if ((oidp->oid_kind & CTLFLAG_OFF) && (V_ipfmain.ipf_running > 0))
352 			error = EBUSY;
353 		else
354 			error = SYSCTL_IN(req, arg1, sizeof(int));
355 	}
356 	return (error);
357 }
358 
359 /*
360  * In the VIMAGE case kern_sysctl.c already adds the vnet base address given
361  * we set CTLFLAG_VNET to get proper access checks.  Have to undo this.
362  * Then we add the given offset to the specific malloced struct hanging off
363  * virtualized ipmain struct.
364  */
365 static int
sysctl_ipf_int_nat(SYSCTL_HANDLER_ARGS)366 sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS )
367 {
368 
369 	if (arg1) {
370 		ipf_nat_softc_t *nat_softc;
371 
372 		nat_softc = V_ipfmain.ipf_nat_soft;
373 #ifdef VIMAGE
374 		arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base);
375 #endif
376 		arg1 = (void *)((uintptr_t)nat_softc + (uintptr_t)arg1);
377 	}
378 
379 	return (sysctl_ipf_int(oidp, arg1, arg2, req));
380 }
381 
382 static int
sysctl_ipf_int_state(SYSCTL_HANDLER_ARGS)383 sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS )
384 {
385 
386 	if (arg1) {
387 		ipf_state_softc_t *state_softc;
388 
389 		state_softc = V_ipfmain.ipf_state_soft;
390 #ifdef VIMAGE
391 		arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base);
392 #endif
393 		arg1 = (void *)((uintptr_t)state_softc + (uintptr_t)arg1);
394 	}
395 
396 	return (sysctl_ipf_int(oidp, arg1, arg2, req));
397 }
398 
399 static int
sysctl_ipf_int_auth(SYSCTL_HANDLER_ARGS)400 sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS )
401 {
402 
403 	if (arg1) {
404 		ipf_auth_softc_t *auth_softc;
405 
406 		auth_softc = V_ipfmain.ipf_auth_soft;
407 #ifdef VIMAGE
408 		arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base);
409 #endif
410 		arg1 = (void *)((uintptr_t)auth_softc + (uintptr_t)arg1);
411 	}
412 
413 	return (sysctl_ipf_int(oidp, arg1, arg2, req));
414 }
415 
416 static int
sysctl_ipf_int_frag(SYSCTL_HANDLER_ARGS)417 sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS )
418 {
419 
420 	if (arg1) {
421 		ipf_frag_softc_t *frag_softc;
422 
423 		frag_softc = V_ipfmain.ipf_frag_soft;
424 #ifdef VIMAGE
425 		arg1 = (void *)((uintptr_t)arg1 - curvnet->vnet_data_base);
426 #endif
427 		arg1 = (void *)((uintptr_t)frag_softc + (uintptr_t)arg1);
428 	}
429 
430 	return (sysctl_ipf_int(oidp, arg1, arg2, req));
431 }
432 #endif
433 
434 
435 static int
436 #ifdef __FreeBSD_version
ipfpoll(struct cdev * dev,int events,struct thread * td)437 ipfpoll(struct cdev *dev, int events, struct thread *td)
438 #else
439 ipfpoll(dev_t dev, int events, struct proc *td)
440 #endif
441 {
442 	int unit = GET_MINOR(dev);
443 	int revents;
444 
445 	if (unit < 0 || unit > IPL_LOGMAX)
446 		return 0;
447 
448 	revents = 0;
449 
450 	CURVNET_SET(TD_TO_VNET(td));
451 	switch (unit)
452 	{
453 	case IPL_LOGIPF :
454 	case IPL_LOGNAT :
455 	case IPL_LOGSTATE :
456 #ifdef IPFILTER_LOG
457 		if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&V_ipfmain, unit))
458 			revents |= events & (POLLIN | POLLRDNORM);
459 #endif
460 		break;
461 	case IPL_LOGAUTH :
462 		if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&V_ipfmain))
463 			revents |= events & (POLLIN | POLLRDNORM);
464 		break;
465 	case IPL_LOGSYNC :
466 		if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&V_ipfmain))
467 			revents |= events & (POLLIN | POLLRDNORM);
468 		if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&V_ipfmain))
469 			revents |= events & (POLLOUT | POLLWRNORM);
470 		break;
471 	case IPL_LOGSCAN :
472 	case IPL_LOGLOOKUP :
473 	default :
474 		break;
475 	}
476 
477 	if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
478 		selrecord(td, &V_ipfmain.ipf_selwait[unit]);
479 	CURVNET_RESTORE();
480 
481 	return revents;
482 }
483 
484 
485 /*
486  * routines below for saving IP headers to buffer
487  */
ipfopen(dev,flags,devtype,p)488 static int ipfopen(dev, flags
489 #ifdef __FreeBSD_version
490 , devtype, p)
491 	int devtype;
492 	struct thread *p;
493 	struct cdev *dev;
494 #else
495 )
496 	dev_t dev;
497 #endif
498 	int flags;
499 {
500 	int unit = GET_MINOR(dev);
501 	int error;
502 
503 	if (IPL_LOGMAX < unit)
504 		error = ENXIO;
505 	else {
506 		switch (unit)
507 		{
508 		case IPL_LOGIPF :
509 		case IPL_LOGNAT :
510 		case IPL_LOGSTATE :
511 		case IPL_LOGAUTH :
512 		case IPL_LOGLOOKUP :
513 		case IPL_LOGSYNC :
514 #ifdef IPFILTER_SCAN
515 		case IPL_LOGSCAN :
516 #endif
517 			error = 0;
518 			break;
519 		default :
520 			error = ENXIO;
521 			break;
522 		}
523 	}
524 	return error;
525 }
526 
527 
ipfclose(dev,flags,devtype,p)528 static int ipfclose(dev, flags
529 #ifdef __FreeBSD_version
530 , devtype, p)
531 	int devtype;
532 	struct thread *p;
533 	struct cdev *dev;
534 #else
535 )
536 	dev_t dev;
537 #endif
538 	int flags;
539 {
540 	int	unit = GET_MINOR(dev);
541 
542 	if (IPL_LOGMAX < unit)
543 		unit = ENXIO;
544 	else
545 		unit = 0;
546 	return unit;
547 }
548 
549 /*
550  * ipfread/ipflog
551  * both of these must operate with at least splnet() lest they be
552  * called during packet processing and cause an inconsistancy to appear in
553  * the filter lists.
554  */
555 #if (BSD >= 199306)
ipfread(dev,uio,ioflag)556 static int ipfread(dev, uio, ioflag)
557 	int ioflag;
558 #else
559 static int ipfread(dev, uio)
560 #endif
561 #ifdef __FreeBSD_version
562 	struct cdev *dev;
563 #else
564 	dev_t dev;
565 #endif
566 	struct uio *uio;
567 {
568 	int error;
569 	int	unit = GET_MINOR(dev);
570 
571 	if (unit < 0)
572 		return ENXIO;
573 
574 	CURVNET_SET(TD_TO_VNET(curthread));
575 	if (V_ipfmain.ipf_running < 1) {
576 		CURVNET_RESTORE();
577 		return EIO;
578 	}
579 
580 	if (unit == IPL_LOGSYNC) {
581 		error = ipf_sync_read(&V_ipfmain, uio);
582 		CURVNET_RESTORE();
583 		return error;
584 	}
585 
586 #ifdef IPFILTER_LOG
587 	error = ipf_log_read(&V_ipfmain, unit, uio);
588 #else
589 	error = ENXIO;
590 #endif
591 	CURVNET_RESTORE();
592 	return error;
593 }
594 
595 
596 /*
597  * ipfwrite
598  * both of these must operate with at least splnet() lest they be
599  * called during packet processing and cause an inconsistancy to appear in
600  * the filter lists.
601  */
602 #if (BSD >= 199306)
ipfwrite(dev,uio,ioflag)603 static int ipfwrite(dev, uio, ioflag)
604 	int ioflag;
605 #else
606 static int ipfwrite(dev, uio)
607 #endif
608 #ifdef __FreeBSD_version
609 	struct cdev *dev;
610 #else
611 	dev_t dev;
612 #endif
613 	struct uio *uio;
614 {
615 	int error;
616 
617 	CURVNET_SET(TD_TO_VNET(curthread));
618 	if (V_ipfmain.ipf_running < 1) {
619 		CURVNET_RESTORE();
620 		return EIO;
621 	}
622 
623 	if (GET_MINOR(dev) == IPL_LOGSYNC) {
624 		error = ipf_sync_write(&V_ipfmain, uio);
625 		CURVNET_RESTORE();
626 		return error;
627 	}
628 	return ENXIO;
629 }
630 
631 static int
ipf_fbsd_sysctl_create(void)632 ipf_fbsd_sysctl_create(void)
633 {
634 
635 	sysctl_ctx_init(&ipf_clist);
636 
637 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO,
638 	    (void *)offsetof(ipf_nat_softc_t, ipf_nat_defage), 0, "");
639 	SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO,
640 	    (void *)offsetof(ipf_state_softc_t, ipf_state_size), 0, "");
641 	SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO,
642 	    (void *)offsetof(ipf_state_softc_t, ipf_state_max), 0, "");
643 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO,
644 	    (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_max), 0, "");
645 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO,
646 	    (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_sz), 0, "");
647 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO,
648 	    (void *)offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz), 0, "");
649 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO,
650 	    (void *)offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), 0, "");
651 	SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO,
652 	    (void *)offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz), 0, "");
653 	SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO,
654 	    (void *)offsetof(ipf_auth_softc_t, ipf_auth_size), 0, "");
655 	SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD,
656 	    (void *)offsetof(ipf_auth_softc_t, ipf_auth_used), 0, "");
657 	SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW,
658 	    (void *)offsetof(ipf_auth_softc_t, ipf_auth_defaultage), 0, "");
659 	SYSCTL_DYN_IPF_FRAG(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW,
660 	    (void *)offsetof(ipf_frag_softc_t, ipfr_ttl), 0, "");
661 	return 0;
662 }
663 
664 static int
ipf_fbsd_sysctl_destroy(void)665 ipf_fbsd_sysctl_destroy(void)
666 {
667 	if (sysctl_ctx_free(&ipf_clist)) {
668 		printf("sysctl_ctx_free failed");
669 		return(ENOTEMPTY);
670 	}
671 	return 0;
672 }
673 
674