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