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__
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__
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__
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);
76 #else
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);
81 #endif
82 
83 #ifdef LARGE_NAT
84 #define IPF_LARGE_NAT	1
85 #else
86 #define IPF_LARGE_NAT	0
87 #endif
88 
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,
114     "IPF");
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");
141 
142 #define CDEV_MAJOR 79
143 #include <sys/poll.h>
144 #ifdef __FreeBSD__
145 # include <sys/select.h>
146 static int ipfpoll(struct cdev *dev, int events, struct thread *td);
147 
148 static struct cdevsw ipf_cdevsw = {
149 	.d_version =	D_VERSION,
150 	.d_flags =	0,	/* D_NEEDGIANT - Should be SMP safe */
151 	.d_open =	ipfopen,
152 	.d_close =	ipfclose,
153 	.d_read =	ipfread,
154 	.d_write =	ipfwrite,
155 	.d_ioctl =	ipfioctl,
156 	.d_poll =	ipfpoll,
157 	.d_name =	"ipf",
158 };
159 #else
160 static int ipfpoll(dev_t dev, int events, struct proc *td);
161 
162 static struct cdevsw ipf_cdevsw = {
163 	/* open */	ipfopen,
164 	/* close */	ipfclose,
165 	/* read */	ipfread,
166 	/* write */	ipfwrite,
167 	/* ioctl */	ipfioctl,
168 	/* poll */	ipfpoll,
169 	/* mmap */	nommap,
170 	/* strategy */	nostrategy,
171 	/* name */	"ipf",
172 	/* maj */	CDEV_MAJOR,
173 	/* dump */	nodump,
174 	/* psize */	nopsize,
175 	/* flags */	0,
176 };
177 #endif
178 
179 static char *ipf_devfiles[] = {	IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
180 				IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
181 
182 static int
ipfilter_modevent(module_t mod,int type,void * unused)183 ipfilter_modevent(module_t mod, int type, void *unused)
184 {
185 	int error = 0;
186 
187 	switch (type)
188 	{
189 	case MOD_LOAD :
190 		error = ipf_modload();
191 		break;
192 
193 	case MOD_UNLOAD :
194 		error = ipf_modunload();
195 		break;
196 	default:
197 		error = EINVAL;
198 		break;
199 	}
200 	return (error);
201 }
202 
203 
204 static void
vnet_ipf_init(void)205 vnet_ipf_init(void)
206 {
207 	char *defpass;
208 	int error;
209 
210 	if (ipf_create_all(&V_ipfmain) == NULL)
211 		return;
212 
213 	error = ipfattach(&V_ipfmain);
214 	if (error) {
215 		ipf_destroy_all(&V_ipfmain);
216 		return;
217 	}
218 
219 	if (FR_ISPASS(V_ipfmain.ipf_pass))
220 		defpass = "pass";
221 	else if (FR_ISBLOCK(V_ipfmain.ipf_pass))
222 		defpass = "block";
223 	else
224 		defpass = "no-match -> block";
225 
226 	if (IS_DEFAULT_VNET(curvnet)) {
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 	} else {
241 		(void)ipf_pfil_hook();
242 		ipf_event_reg();
243 	}
244 }
245 VNET_SYSINIT(vnet_ipf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
246     vnet_ipf_init, NULL);
247 
248 static int
ipf_modload(void)249 ipf_modload(void)
250 {
251 	char *c, *str;
252 	int i, j, error;
253 
254 	if (ipf_load_all() != 0)
255 		return (EIO);
256 
257 	if (ipf_fbsd_sysctl_create() != 0) {
258 		return (EIO);
259 	}
260 
261 	for (i = 0; i < IPL_LOGSIZE; i++)
262 		ipf_devs[i] = NULL;
263 	for (i = 0; (str = ipf_devfiles[i]); i++) {
264 		c = NULL;
265 		for(j = strlen(str); j > 0; j--)
266 			if (str[j] == '/') {
267 				c = str + j + 1;
268 				break;
269 			}
270 		if (!c)
271 			c = str;
272 		ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
273 	}
274 
275 	error = ipf_pfil_hook();
276 	if (error != 0)
277 		return (error);
278 	ipf_event_reg();
279 
280 	return (0);
281 }
282 
283 static void
vnet_ipf_uninit(void)284 vnet_ipf_uninit(void)
285 {
286 
287 	if (V_ipfmain.ipf_refcnt)
288 		return;
289 
290 	if (V_ipfmain.ipf_running >= 0) {
291 
292 		if (ipfdetach(&V_ipfmain) != 0)
293 			return;
294 
295 		V_ipfmain.ipf_running = -2;
296 
297 		ipf_destroy_all(&V_ipfmain);
298 		if (!IS_DEFAULT_VNET(curvnet)) {
299 			ipf_event_dereg();
300 			(void)ipf_pfil_unhook();
301 		}
302 	}
303 }
304 VNET_SYSUNINIT(vnet_ipf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD,
305     vnet_ipf_uninit, NULL);
306 
307 static int
ipf_modunload(void)308 ipf_modunload(void)
309 {
310 	int error, i;
311 
312 	ipf_event_dereg();
313 
314 	ipf_fbsd_sysctl_destroy();
315 
316 	error = ipf_pfil_unhook();
317 	if (error != 0)
318 		return (error);
319 
320 	for (i = 0; ipf_devfiles[i]; i++) {
321 		if (ipf_devs[i] != NULL)
322 			destroy_dev(ipf_devs[i]);
323 	}
324 
325 	ipf_unload_all();
326 
327 	printf("%s unloaded\n", ipfilter_version);
328 
329 	return (0);
330 }
331 
332 
333 static moduledata_t ipfiltermod = {
334 	"ipfilter",
335 	ipfilter_modevent,
336 	0
337 };
338 
339 
340 DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND);
341 #ifdef	MODULE_VERSION
342 MODULE_VERSION(ipfilter, 1);
343 #endif
344 
345 
346 #ifdef SYSCTL_IPF
347 int
sysctl_ipf_int(SYSCTL_HANDLER_ARGS)348 sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
349 {
350 	int error = 0;
351 
352 	if (arg1)
353 		error = SYSCTL_OUT(req, arg1, sizeof(int));
354 	else
355 		error = SYSCTL_OUT(req, &arg2, sizeof(int));
356 
357 	if (error || !req->newptr)
358 		goto sysctl_error;
359 
360 	if (!arg1)
361 		error = EPERM;
362 	else {
363 		if ((oidp->oid_kind & CTLFLAG_OFF) && (V_ipfmain.ipf_running > 0))
364 			error = EBUSY;
365 		else
366 			error = SYSCTL_IN(req, arg1, sizeof(int));
367 	}
368 
369 sysctl_error:
370 	return (error);
371 }
372 
373 /*
374  * arg2 holds the offset of the relevant member in the virtualized
375  * ipfmain structure.
376  */
377 static int
sysctl_ipf_int_nat(SYSCTL_HANDLER_ARGS)378 sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS )
379 {
380 	ipf_nat_softc_t *nat_softc;
381 
382 	nat_softc = V_ipfmain.ipf_nat_soft;
383 	arg1 = (void *)((uintptr_t)nat_softc + arg2);
384 
385 	return (sysctl_ipf_int(oidp, arg1, 0, req));
386 }
387 
388 static int
sysctl_ipf_int_state(SYSCTL_HANDLER_ARGS)389 sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS )
390 {
391 	ipf_state_softc_t *state_softc;
392 
393 	state_softc = V_ipfmain.ipf_state_soft;
394 	arg1 = (void *)((uintptr_t)state_softc + arg2);
395 
396 	return (sysctl_ipf_int(oidp, arg1, 0, req));
397 }
398 
399 static int
sysctl_ipf_int_auth(SYSCTL_HANDLER_ARGS)400 sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS )
401 {
402 	ipf_auth_softc_t *auth_softc;
403 
404 	auth_softc = V_ipfmain.ipf_auth_soft;
405 	arg1 = (void *)((uintptr_t)auth_softc + arg2);
406 
407 	return (sysctl_ipf_int(oidp, arg1, 0, req));
408 }
409 
410 static int
sysctl_ipf_int_frag(SYSCTL_HANDLER_ARGS)411 sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS )
412 {
413 	ipf_frag_softc_t *frag_softc;
414 
415 	frag_softc = V_ipfmain.ipf_frag_soft;
416 	arg1 = (void *)((uintptr_t)frag_softc + arg2);
417 
418 	return (sysctl_ipf_int(oidp, arg1, 0, req));
419 }
420 #endif
421 
422 
423 static int
424 #ifdef __FreeBSD__
ipfpoll(struct cdev * dev,int events,struct thread * td)425 ipfpoll(struct cdev *dev, int events, struct thread *td)
426 #else
427 ipfpoll(dev_t dev, int events, struct proc *td)
428 #endif
429 {
430 	int unit = GET_MINOR(dev);
431 	int revents;
432 
433 	if (unit < 0 || unit > IPL_LOGMAX)
434 		return (0);
435 
436 	revents = 0;
437 
438 	CURVNET_SET(TD_TO_VNET(td));
439 	switch (unit)
440 	{
441 	case IPL_LOGIPF :
442 	case IPL_LOGNAT :
443 	case IPL_LOGSTATE :
444 #ifdef IPFILTER_LOG
445 		if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&V_ipfmain, unit))
446 			revents |= events & (POLLIN | POLLRDNORM);
447 #endif
448 		break;
449 	case IPL_LOGAUTH :
450 		if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&V_ipfmain))
451 			revents |= events & (POLLIN | POLLRDNORM);
452 		break;
453 	case IPL_LOGSYNC :
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);
458 		break;
459 	case IPL_LOGSCAN :
460 	case IPL_LOGLOOKUP :
461 	default :
462 		break;
463 	}
464 
465 	if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
466 		selrecord(td, &V_ipfmain.ipf_selwait[unit]);
467 	CURVNET_RESTORE();
468 
469 	return (revents);
470 }
471 
472 
473 /*
474  * routines below for saving IP headers to buffer
475  */
476 static int
477 #ifdef __FreeBSD__
ipfopen(struct cdev * dev,int flags,int devtype,struct thread * p)478 ipfopen(struct cdev *dev, int flags, int devtype, struct thread *p)
479 #else
480 ipfopen(dev_t dev, int flags)
481 #endif
482 {
483 	int unit = GET_MINOR(dev);
484 	int error;
485 
486 	if (IPL_LOGMAX < unit)
487 		error = ENXIO;
488 	else {
489 		switch (unit)
490 		{
491 		case IPL_LOGIPF :
492 		case IPL_LOGNAT :
493 		case IPL_LOGSTATE :
494 		case IPL_LOGAUTH :
495 		case IPL_LOGLOOKUP :
496 		case IPL_LOGSYNC :
497 #ifdef IPFILTER_SCAN
498 		case IPL_LOGSCAN :
499 #endif
500 			error = 0;
501 			break;
502 		default :
503 			error = ENXIO;
504 			break;
505 		}
506 	}
507 	return (error);
508 }
509 
510 
511 static int
512 #ifdef __FreeBSD__
ipfclose(struct cdev * dev,int flags,int devtype,struct thread * p)513 ipfclose(struct cdev *dev, int flags, int devtype, struct thread *p)
514 #else
515 ipfclose(dev_t dev, int flags)
516 #endif
517 {
518 	int	unit = GET_MINOR(dev);
519 
520 	if (IPL_LOGMAX < unit)
521 		unit = ENXIO;
522 	else
523 		unit = 0;
524 	return (unit);
525 }
526 
527 /*
528  * ipfread/ipflog
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
531  * the filter lists.
532  */
ipfread(dev,uio,ioflag)533 static int ipfread(dev, uio, ioflag)
534 	int ioflag;
535 #ifdef __FreeBSD__
536 	struct cdev *dev;
537 #else
538 	dev_t dev;
539 #endif
540 	struct uio *uio;
541 {
542 	int error;
543 	int	unit = GET_MINOR(dev);
544 
545 	if (unit < 0)
546 		return (ENXIO);
547 
548 	CURVNET_SET(TD_TO_VNET(curthread));
549 	if (V_ipfmain.ipf_running < 1) {
550 		CURVNET_RESTORE();
551 		return (EIO);
552 	}
553 
554 	if (unit == IPL_LOGSYNC) {
555 		error = ipf_sync_read(&V_ipfmain, uio);
556 		CURVNET_RESTORE();
557 		return (error);
558 	}
559 
560 #ifdef IPFILTER_LOG
561 	error = ipf_log_read(&V_ipfmain, unit, uio);
562 #else
563 	error = ENXIO;
564 #endif
565 	CURVNET_RESTORE();
566 	return (error);
567 }
568 
569 
570 /*
571  * ipfwrite
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
574  * the filter lists.
575  */
ipfwrite(dev,uio,ioflag)576 static int ipfwrite(dev, uio, ioflag)
577 	int ioflag;
578 #ifdef __FreeBSD__
579 	struct cdev *dev;
580 #else
581 	dev_t dev;
582 #endif
583 	struct uio *uio;
584 {
585 	int error;
586 
587 	CURVNET_SET(TD_TO_VNET(curthread));
588 	if (V_ipfmain.ipf_running < 1) {
589 		CURVNET_RESTORE();
590 		return (EIO);
591 	}
592 
593 	if (GET_MINOR(dev) == IPL_LOGSYNC) {
594 		error = ipf_sync_write(&V_ipfmain, uio);
595 		CURVNET_RESTORE();
596 		return (error);
597 	}
598 	return (ENXIO);
599 }
600 
601 static int
ipf_fbsd_sysctl_create(void)602 ipf_fbsd_sysctl_create(void)
603 {
604 
605 	sysctl_ctx_init(&ipf_clist);
606 
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), "");
631 	return (0);
632 }
633 
634 static int
ipf_fbsd_sysctl_destroy(void)635 ipf_fbsd_sysctl_destroy(void)
636 {
637 	if (sysctl_ctx_free(&ipf_clist)) {
638 		printf("sysctl_ctx_free failed");
639 		return (ENOTEMPTY);
640 	}
641 	return (0);
642 }
643