]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netpfil/ipfilter/netinet/mlfk_ipl.c
Import device-tree files from Linux 5.16
[FreeBSD/FreeBSD.git] / sys / netpfil / ipfilter / netinet / mlfk_ipl.c
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
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
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
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
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
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
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
378 sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS )
379 {
380         if (jailed_without_vnet(curthread->td_ucred))
381                 return (0);
382
383         ipf_nat_softc_t *nat_softc;
384
385         nat_softc = V_ipfmain.ipf_nat_soft;
386         arg1 = (void *)((uintptr_t)nat_softc + arg2);
387
388         return (sysctl_ipf_int(oidp, arg1, 0, req));
389 }
390
391 static int
392 sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS )
393 {
394         if (jailed_without_vnet(curthread->td_ucred))
395                 return (0);
396
397         ipf_state_softc_t *state_softc;
398
399         state_softc = V_ipfmain.ipf_state_soft;
400         arg1 = (void *)((uintptr_t)state_softc + arg2);
401
402         return (sysctl_ipf_int(oidp, arg1, 0, req));
403 }
404
405 static int
406 sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS )
407 {
408         if (jailed_without_vnet(curthread->td_ucred))
409                 return (0);
410
411         ipf_auth_softc_t *auth_softc;
412
413         auth_softc = V_ipfmain.ipf_auth_soft;
414         arg1 = (void *)((uintptr_t)auth_softc + arg2);
415
416         return (sysctl_ipf_int(oidp, arg1, 0, req));
417 }
418
419 static int
420 sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS )
421 {
422         if (jailed_without_vnet(curthread->td_ucred))
423                 return (0);
424
425         ipf_frag_softc_t *frag_softc;
426
427         frag_softc = V_ipfmain.ipf_frag_soft;
428         arg1 = (void *)((uintptr_t)frag_softc + arg2);
429
430         return (sysctl_ipf_int(oidp, arg1, 0, req));
431 }
432 #endif
433
434
435 static int
436 #ifdef __FreeBSD__
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  */
488 static int
489 #ifdef __FreeBSD__
490 ipfopen(struct cdev *dev, int flags, int devtype, struct thread *p)
491 #else
492 ipfopen(dev_t dev, int flags)
493 #endif
494 {
495         int unit = GET_MINOR(dev);
496         int error;
497
498         if (IPL_LOGMAX < unit)
499                 error = ENXIO;
500         else {
501                 switch (unit)
502                 {
503                 case IPL_LOGIPF :
504                 case IPL_LOGNAT :
505                 case IPL_LOGSTATE :
506                 case IPL_LOGAUTH :
507                 case IPL_LOGLOOKUP :
508                 case IPL_LOGSYNC :
509 #ifdef IPFILTER_SCAN
510                 case IPL_LOGSCAN :
511 #endif
512                         error = 0;
513                         break;
514                 default :
515                         error = ENXIO;
516                         break;
517                 }
518         }
519         return (error);
520 }
521
522
523 static int
524 #ifdef __FreeBSD__
525 ipfclose(struct cdev *dev, int flags, int devtype, struct thread *p)
526 #else
527 ipfclose(dev_t dev, int flags)
528 #endif
529 {
530         int     unit = GET_MINOR(dev);
531
532         if (IPL_LOGMAX < unit)
533                 unit = ENXIO;
534         else
535                 unit = 0;
536         return (unit);
537 }
538
539 /*
540  * ipfread/ipflog
541  * both of these must operate with at least splnet() lest they be
542  * called during packet processing and cause an inconsistancy to appear in
543  * the filter lists.
544  */
545 static int ipfread(dev, uio, ioflag)
546         int ioflag;
547 #ifdef __FreeBSD__
548         struct cdev *dev;
549 #else
550         dev_t dev;
551 #endif
552         struct uio *uio;
553 {
554         int error;
555         int     unit = GET_MINOR(dev);
556
557         if (unit < 0)
558                 return (ENXIO);
559
560         CURVNET_SET(TD_TO_VNET(curthread));
561         if (V_ipfmain.ipf_running < 1) {
562                 CURVNET_RESTORE();
563                 return (EIO);
564         }
565
566         if (unit == IPL_LOGSYNC) {
567                 error = ipf_sync_read(&V_ipfmain, uio);
568                 CURVNET_RESTORE();
569                 return (error);
570         }
571
572 #ifdef IPFILTER_LOG
573         error = ipf_log_read(&V_ipfmain, unit, uio);
574 #else
575         error = ENXIO;
576 #endif
577         CURVNET_RESTORE();
578         return (error);
579 }
580
581
582 /*
583  * ipfwrite
584  * both of these must operate with at least splnet() lest they be
585  * called during packet processing and cause an inconsistancy to appear in
586  * the filter lists.
587  */
588 static int ipfwrite(dev, uio, ioflag)
589         int ioflag;
590 #ifdef __FreeBSD__
591         struct cdev *dev;
592 #else
593         dev_t dev;
594 #endif
595         struct uio *uio;
596 {
597         int error;
598
599         CURVNET_SET(TD_TO_VNET(curthread));
600         if (V_ipfmain.ipf_running < 1) {
601                 CURVNET_RESTORE();
602                 return (EIO);
603         }
604
605         if (GET_MINOR(dev) == IPL_LOGSYNC) {
606                 error = ipf_sync_write(&V_ipfmain, uio);
607                 CURVNET_RESTORE();
608                 return (error);
609         }
610         return (ENXIO);
611 }
612
613 static int
614 ipf_fbsd_sysctl_create(void)
615 {
616
617         sysctl_ctx_init(&ipf_clist);
618
619         SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO,
620             NULL, offsetof(ipf_nat_softc_t, ipf_nat_defage), "");
621         SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO,
622             NULL, offsetof(ipf_state_softc_t, ipf_state_size), "");
623         SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO,
624             NULL, offsetof(ipf_state_softc_t, ipf_state_max), "");
625         SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO,
626             NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_max), "");
627         SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO,
628             NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_sz), "");
629         SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO,
630             NULL, offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz), "");
631         SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO,
632             NULL, offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), "");
633         SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO,
634             NULL, offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz), "");
635         SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO,
636             NULL, offsetof(ipf_auth_softc_t, ipf_auth_size), "");
637         SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD,
638             NULL, offsetof(ipf_auth_softc_t, ipf_auth_used), "");
639         SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW,
640             NULL, offsetof(ipf_auth_softc_t, ipf_auth_defaultage), "");
641         SYSCTL_DYN_IPF_FRAG(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW,
642             NULL, offsetof(ipf_frag_softc_t, ipfr_ttl), "");
643         return (0);
644 }
645
646 static int
647 ipf_fbsd_sysctl_destroy(void)
648 {
649         if (sysctl_ctx_free(&ipf_clist)) {
650                 printf("sysctl_ctx_free failed");
651                 return (ENOTEMPTY);
652         }
653         return (0);
654 }