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 52VNET_DECLARE(ipf_main_softc_t, ipfmain); 53#define V_ipfmain VNET(ipfmain) 54 55#ifdef __FreeBSD__ 56static struct cdev *ipf_devs[IPL_LOGSIZE]; 57#else 58static dev_t ipf_devs[IPL_LOGSIZE]; 59#endif 60 61static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ); 62static int sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS ); 63static int sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS ); 64static int sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS ); 65static int sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS ); 66static int ipf_modload(void); 67static int ipf_modunload(void); 68static int ipf_fbsd_sysctl_create(void); 69static int ipf_fbsd_sysctl_destroy(void); 70 71#ifdef __FreeBSD__ 72static int ipfopen(struct cdev*, int, int, struct thread *); 73static int ipfclose(struct cdev*, int, int, struct thread *); 74static int ipfread(struct cdev*, struct uio *, int); 75static int ipfwrite(struct cdev*, struct uio *, int); 76#else 77static int ipfopen(dev_t, int, int, struct proc *); 78static int ipfclose(dev_t, int, int, struct proc *); 79static int ipfread(dev_t, struct uio *, int); 80static int ipfwrite(dev_t, struct uio *, int); 81#endif 82 83 84SYSCTL_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) 105static struct sysctl_ctx_list ipf_clist; 106#define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ 107#define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) 108SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 109 "IPF"); 110SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_flags), 0, "IPF flags"); 111SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_pass), 0, "default pass/block"); 112SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &VNET_NAME(ipfmain.ipf_active), 0, "IPF is active"); 113SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, 114 &VNET_NAME(ipfmain.ipf_tcpidletimeout), 0, "TCP idle timeout in seconds"); 115SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, 116 &VNET_NAME(ipfmain.ipf_tcphalfclosed), 0, "timeout for half closed TCP sessions"); 117SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, 118 &VNET_NAME(ipfmain.ipf_tcpclosewait), 0, "timeout for TCP sessions in closewait status"); 119SYSCTL_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"); 121SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, 122 &VNET_NAME(ipfmain.ipf_tcptimeout), 0, ""); 123SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, 124 &VNET_NAME(ipfmain.ipf_tcpclosed), 0, ""); 125SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, 126 &VNET_NAME(ipfmain.ipf_udptimeout), 0, "UDP timeout"); 127SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO, 128 &VNET_NAME(ipfmain.ipf_udpacktimeout), 0, ""); 129SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, 130 &VNET_NAME(ipfmain.ipf_icmptimeout), 0, "ICMP timeout"); 131SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD, 132 &VNET_NAME(ipfmain.ipf_running), 0, "IPF is running"); 133SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_chksrc), 0, ""); 134SYSCTL_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__ 139# include <sys/select.h> 140static int ipfpoll(struct cdev *dev, int events, struct thread *td); 141 142static 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 154static int ipfpoll(dev_t dev, int events, struct proc *td); 155 156static 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 173static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME, 174 IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL }; 175 176static int 177ipfilter_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 198static void 199vnet_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} 239VNET_SYSINIT(vnet_ipf_init, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD, 240 vnet_ipf_init, NULL); 241 242static int 243ipf_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 277static void 278vnet_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} 298VNET_SYSUNINIT(vnet_ipf_uninit, SI_SUB_PROTO_FIREWALL, SI_ORDER_THIRD, 299 vnet_ipf_uninit, NULL); 300 301static int 302ipf_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 327static moduledata_t ipfiltermod = { 328 "ipfilter", 329 ipfilter_modevent, 330 0 331}; 332 333 334DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_FIREWALL, SI_ORDER_SECOND); 335#ifdef MODULE_VERSION 336MODULE_VERSION(ipfilter, 1); 337#endif 338 339 340#ifdef SYSCTL_IPF 341int 342sysctl_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 364sysctl_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 */ 373static int 374sysctl_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 384static int 385sysctl_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 395static int 396sysctl_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 406static int 407sysctl_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 419static int 420#ifdef __FreeBSD__ 421ipfpoll(struct cdev *dev, int events, struct thread *td) 422#else 423ipfpoll(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 */ 472static int ipfopen(dev, flags 473#ifdef __FreeBSD__ 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 512static int ipfclose(dev, flags 513#ifdef __FreeBSD__ 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 */ 539static int ipfread(dev, uio, ioflag) 540 int ioflag; 541#ifdef __FreeBSD__ 542 struct cdev *dev; 543#else 544 dev_t dev; 545#endif 546 struct uio *uio; 547{ 548 int error; 549 int unit = GET_MINOR(dev); 550 551 if (unit < 0) 552 return ENXIO; 553 554 CURVNET_SET(TD_TO_VNET(curthread)); 555 if (V_ipfmain.ipf_running < 1) { 556 CURVNET_RESTORE(); 557 return EIO; 558 } 559 560 if (unit == IPL_LOGSYNC) { 561 error = ipf_sync_read(&V_ipfmain, uio); 562 CURVNET_RESTORE(); 563 return error; 564 } 565 566#ifdef IPFILTER_LOG 567 error = ipf_log_read(&V_ipfmain, unit, uio); 568#else 569 error = ENXIO; 570#endif 571 CURVNET_RESTORE(); 572 return error; 573} 574 575 576/* 577 * ipfwrite 578 * both of these must operate with at least splnet() lest they be 579 * called during packet processing and cause an inconsistancy to appear in 580 * the filter lists. 581 */ 582static int ipfwrite(dev, uio, ioflag) 583 int ioflag; 584#ifdef __FreeBSD__ 585 struct cdev *dev; 586#else 587 dev_t dev; 588#endif 589 struct uio *uio; 590{ 591 int error; 592 593 CURVNET_SET(TD_TO_VNET(curthread)); 594 if (V_ipfmain.ipf_running < 1) { 595 CURVNET_RESTORE(); 596 return EIO; 597 } 598 599 if (GET_MINOR(dev) == IPL_LOGSYNC) { 600 error = ipf_sync_write(&V_ipfmain, uio); 601 CURVNET_RESTORE(); 602 return error; 603 } 604 return ENXIO; 605} 606 607static int 608ipf_fbsd_sysctl_create(void) 609{ 610 611 sysctl_ctx_init(&ipf_clist); 612 613 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO, 614 NULL, offsetof(ipf_nat_softc_t, ipf_nat_defage), ""); 615 SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO, 616 NULL, offsetof(ipf_state_softc_t, ipf_state_size), ""); 617 SYSCTL_DYN_IPF_STATE(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO, 618 NULL, offsetof(ipf_state_softc_t, ipf_state_max), ""); 619 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO, 620 NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_max), ""); 621 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO, 622 NULL, offsetof(ipf_nat_softc_t, ipf_nat_table_sz), ""); 623 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO, 624 NULL, offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz), ""); 625 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO, 626 NULL, offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), ""); 627 SYSCTL_DYN_IPF_NAT(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO, 628 NULL, offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz), ""); 629 SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO, 630 NULL, offsetof(ipf_auth_softc_t, ipf_auth_size), ""); 631 SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD, 632 NULL, offsetof(ipf_auth_softc_t, ipf_auth_used), ""); 633 SYSCTL_DYN_IPF_AUTH(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW, 634 NULL, offsetof(ipf_auth_softc_t, ipf_auth_defaultage), ""); 635 SYSCTL_DYN_IPF_FRAG(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW, 636 NULL, offsetof(ipf_frag_softc_t, ipfr_ttl), ""); 637 return 0; 638} 639 640static int 641ipf_fbsd_sysctl_destroy(void) 642{ 643 if (sysctl_ctx_free(&ipf_clist)) { 644 printf("sysctl_ctx_free failed"); 645 return(ENOTEMPTY); 646 } 647 return 0; 648} 649 650