1/* $FreeBSD: releng/10.3/sys/contrib/ipfilter/netinet/mlfk_ipl.c 266829 2014-05-29 02:55:07Z cy $ */ 2 3/* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * $FreeBSD: releng/10.3/sys/contrib/ipfilter/netinet/mlfk_ipl.c 266829 2014-05-29 02:55:07Z cy $ 7 * See the IPFILTER.LICENCE file for details on licencing. 8 */ 9 10 11#include <sys/param.h> 12#include <sys/systm.h> 13#include <sys/kernel.h> 14#include <sys/module.h> 15#include <sys/conf.h> 16#include <sys/socket.h> 17#include <sys/sysctl.h> 18#include <sys/select.h> 19#if __FreeBSD_version >= 500000 20# include <sys/selinfo.h> 21#endif 22#include <net/if.h> 23#include <netinet/in_systm.h> 24#include <netinet/in.h> 25 26 27#include "netinet/ipl.h" 28#include "netinet/ip_compat.h" 29#include "netinet/ip_fil.h" 30#include "netinet/ip_state.h" 31#include "netinet/ip_nat.h" 32#include "netinet/ip_auth.h" 33#include "netinet/ip_frag.h" 34#include "netinet/ip_sync.h" 35 36extern ipf_main_softc_t ipfmain; 37 38#if __FreeBSD_version >= 502116 39static struct cdev *ipf_devs[IPL_LOGSIZE]; 40#else 41static dev_t ipf_devs[IPL_LOGSIZE]; 42#endif 43 44static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ); 45static int ipf_modload(void); 46static int ipf_modunload(void); 47static int ipf_fbsd_sysctl_create(ipf_main_softc_t*); 48static int ipf_fbsd_sysctl_destroy(ipf_main_softc_t*); 49 50#if (__FreeBSD_version >= 500024) 51# if (__FreeBSD_version >= 502116) 52static int ipfopen __P((struct cdev*, int, int, struct thread *)); 53static int ipfclose __P((struct cdev*, int, int, struct thread *)); 54# else 55static int ipfopen __P((dev_t, int, int, struct thread *)); 56static int ipfclose __P((dev_t, int, int, struct thread *)); 57# endif /* __FreeBSD_version >= 502116 */ 58#else 59static int ipfopen __P((dev_t, int, int, struct proc *)); 60static int ipfclose __P((dev_t, int, int, struct proc *)); 61#endif 62#if (__FreeBSD_version >= 502116) 63static int ipfread __P((struct cdev*, struct uio *, int)); 64static int ipfwrite __P((struct cdev*, struct uio *, int)); 65#else 66static int ipfread __P((dev_t, struct uio *, int)); 67static int ipfwrite __P((dev_t, struct uio *, int)); 68#endif /* __FreeBSD_version >= 502116 */ 69 70 71SYSCTL_DECL(_net_inet); 72#define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \ 73 SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \ 74 ptr, val, sysctl_ipf_int, "I", descr); 75#define SYSCTL_DYN_IPF(parent, nbr, name, access,ptr, val, descr) \ 76 SYSCTL_ADD_OID(&ipf_clist, SYSCTL_STATIC_CHILDREN(parent), nbr, name, \ 77 CTLFLAG_DYN|CTLTYPE_INT|access, ptr, val, sysctl_ipf_int, "I", descr) 78static struct sysctl_ctx_list ipf_clist; 79#define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ 80#define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) 81SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); 82SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipfmain.ipf_flags, 0, "IPF flags"); 83SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipfmain.ipf_pass, 0, "default pass/block"); 84SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipfmain.ipf_active, 0, "IPF is active"); 85SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, 86 &ipfmain.ipf_tcpidletimeout, 0, "TCP idle timeout in seconds"); 87SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, 88 &ipfmain.ipf_tcphalfclosed, 0, "timeout for half closed TCP sessions"); 89SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, 90 &ipfmain.ipf_tcpclosewait, 0, "timeout for TCP sessions in closewait status"); 91SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO, 92 &ipfmain.ipf_tcplastack, 0, "timeout for TCP sessions in last ack status"); 93SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, 94 &ipfmain.ipf_tcptimeout, 0, ""); 95SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, 96 &ipfmain.ipf_tcpclosed, 0, ""); 97SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, 98 &ipfmain.ipf_udptimeout, 0, "UDP timeout"); 99SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO, 100 &ipfmain.ipf_udpacktimeout, 0, ""); 101SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, 102 &ipfmain.ipf_icmptimeout, 0, "ICMP timeout"); 103SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD, 104 &ipfmain.ipf_running, 0, "IPF is running"); 105SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipfmain.ipf_chksrc, 0, ""); 106SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipfmain.ipf_minttl, 0, ""); 107 108#define CDEV_MAJOR 79 109#include <sys/poll.h> 110#if __FreeBSD_version >= 500043 111# include <sys/select.h> 112static int ipfpoll(struct cdev *dev, int events, struct thread *td); 113 114static struct cdevsw ipf_cdevsw = { 115#if __FreeBSD_version >= 502103 116 .d_version = D_VERSION, 117 .d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */ 118#endif 119 .d_open = ipfopen, 120 .d_close = ipfclose, 121 .d_read = ipfread, 122 .d_write = ipfwrite, 123 .d_ioctl = ipfioctl, 124 .d_poll = ipfpoll, 125 .d_name = "ipf", 126#if __FreeBSD_version < 600000 127 .d_maj = CDEV_MAJOR, 128#endif 129}; 130#else 131static int ipfpoll(dev_t dev, int events, struct proc *td); 132 133static struct cdevsw ipf_cdevsw = { 134 /* open */ ipfopen, 135 /* close */ ipfclose, 136 /* read */ ipfread, 137 /* write */ ipfwrite, 138 /* ioctl */ ipfioctl, 139 /* poll */ ipfpoll, 140 /* mmap */ nommap, 141 /* strategy */ nostrategy, 142 /* name */ "ipf", 143 /* maj */ CDEV_MAJOR, 144 /* dump */ nodump, 145 /* psize */ nopsize, 146 /* flags */ 0, 147# if (__FreeBSD_version < 500043) 148 /* bmaj */ -1, 149# endif 150# if (__FreeBSD_version >= 430000) 151 /* kqfilter */ NULL 152# endif 153}; 154#endif 155 156static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME, 157 IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL }; 158 159static int 160ipfilter_modevent(module_t mod, int type, void *unused) 161{ 162 int error = 0; 163 164 switch (type) 165 { 166 case MOD_LOAD : 167 error = ipf_modload(); 168 break; 169 170 case MOD_UNLOAD : 171 error = ipf_modunload(); 172 break; 173 default: 174 error = EINVAL; 175 break; 176 } 177 return error; 178} 179 180 181static int 182ipf_modload() 183{ 184 char *defpass, *c, *str; 185 int i, j, error; 186 187 if (ipf_load_all() != 0) 188 return EIO; 189 190 if (ipf_create_all(&ipfmain) == NULL) 191 return EIO; 192 193 if (ipf_fbsd_sysctl_create(&ipfmain) != 0) 194 return EIO; 195 196 error = ipfattach(&ipfmain); 197 if (error) 198 return error; 199 200 for (i = 0; i < IPL_LOGSIZE; i++) 201 ipf_devs[i] = NULL; 202 203 for (i = 0; (str = ipf_devfiles[i]); i++) { 204 c = NULL; 205 for(j = strlen(str); j > 0; j--) 206 if (str[j] == '/') { 207 c = str + j + 1; 208 break; 209 } 210 if (!c) 211 c = str; 212 ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c); 213 } 214 215 error = ipf_pfil_hook(); 216 if (error != 0) 217 return error; 218 ipf_event_reg(); 219 220 if (FR_ISPASS(ipfmain.ipf_pass)) 221 defpass = "pass"; 222 else if (FR_ISBLOCK(ipfmain.ipf_pass)) 223 defpass = "block"; 224 else 225 defpass = "no-match -> block"; 226 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 return 0; 241} 242 243 244static int 245ipf_modunload() 246{ 247 int error, i; 248 249 if (ipfmain.ipf_refcnt) 250 return EBUSY; 251 252 if (ipf_fbsd_sysctl_destroy(&ipfmain) != 0) 253 return EIO; 254 255 error = ipf_pfil_unhook(); 256 if (error != 0) 257 return error; 258 259 if (ipfmain.ipf_running >= 0) { 260 error = ipfdetach(&ipfmain); 261 if (error != 0) 262 return error; 263 264 ipf_fbsd_sysctl_destroy(&ipfmain); 265 ipf_destroy_all(&ipfmain); 266 ipf_unload_all(); 267 } else 268 error = 0; 269 270 ipfmain.ipf_running = -2; 271 272 for (i = 0; ipf_devfiles[i]; i++) { 273 if (ipf_devs[i] != NULL) 274 destroy_dev(ipf_devs[i]); 275 } 276 277 printf("%s unloaded\n", ipfilter_version); 278 279 return error; 280} 281 282 283static moduledata_t ipfiltermod = { 284 "ipfilter", 285 ipfilter_modevent, 286 0 287}; 288 289 290DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); 291#ifdef MODULE_VERSION 292MODULE_VERSION(ipfilter, 1); 293#endif 294 295 296#ifdef SYSCTL_IPF 297int 298sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) 299{ 300 int error = 0; 301 302 if (arg1) 303 error = SYSCTL_OUT(req, arg1, sizeof(int)); 304 else 305 error = SYSCTL_OUT(req, &arg2, sizeof(int)); 306 307 if (error || !req->newptr) 308 return (error); 309 310 if (!arg1) 311 error = EPERM; 312 else { 313 if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0)) 314 error = EBUSY; 315 else 316 error = SYSCTL_IN(req, arg1, sizeof(int)); 317 } 318 return (error); 319} 320#endif 321 322 323static int 324#if __FreeBSD_version >= 500043 325ipfpoll(struct cdev *dev, int events, struct thread *td) 326#else 327ipfpoll(dev_t dev, int events, struct proc *td) 328#endif 329{ 330 int unit = GET_MINOR(dev); 331 int revents; 332 333 if (unit < 0 || unit > IPL_LOGMAX) 334 return 0; 335 336 revents = 0; 337 338 switch (unit) 339 { 340 case IPL_LOGIPF : 341 case IPL_LOGNAT : 342 case IPL_LOGSTATE : 343#ifdef IPFILTER_LOG 344 if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit)) 345 revents |= events & (POLLIN | POLLRDNORM); 346#endif 347 break; 348 case IPL_LOGAUTH : 349 if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain)) 350 revents |= events & (POLLIN | POLLRDNORM); 351 break; 352 case IPL_LOGSYNC : 353 if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain)) 354 revents |= events & (POLLIN | POLLRDNORM); 355 if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain)) 356 revents |= events & (POLLOUT | POLLWRNORM); 357 break; 358 case IPL_LOGSCAN : 359 case IPL_LOGLOOKUP : 360 default : 361 break; 362 } 363 364 if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0)) 365 selrecord(td, &ipfmain.ipf_selwait[unit]); 366 367 return revents; 368} 369 370 371/* 372 * routines below for saving IP headers to buffer 373 */ 374static int ipfopen(dev, flags 375#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 376, devtype, p) 377 int devtype; 378# if (__FreeBSD_version >= 500024) 379 struct thread *p; 380# else 381 struct proc *p; 382# endif /* __FreeBSD_version >= 500024 */ 383#else 384) 385#endif 386#if (__FreeBSD_version >= 502116) 387 struct cdev *dev; 388#else 389 dev_t dev; 390#endif 391 int flags; 392{ 393 int unit = GET_MINOR(dev); 394 int error; 395 396 if (IPL_LOGMAX < unit) 397 error = ENXIO; 398 else { 399 switch (unit) 400 { 401 case IPL_LOGIPF : 402 case IPL_LOGNAT : 403 case IPL_LOGSTATE : 404 case IPL_LOGAUTH : 405 case IPL_LOGLOOKUP : 406 case IPL_LOGSYNC : 407#ifdef IPFILTER_SCAN 408 case IPL_LOGSCAN : 409#endif 410 error = 0; 411 break; 412 default : 413 error = ENXIO; 414 break; 415 } 416 } 417 return error; 418} 419 420 421static int ipfclose(dev, flags 422#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 423, devtype, p) 424 int devtype; 425# if (__FreeBSD_version >= 500024) 426 struct thread *p; 427# else 428 struct proc *p; 429# endif /* __FreeBSD_version >= 500024 */ 430#else 431) 432#endif 433#if (__FreeBSD_version >= 502116) 434 struct cdev *dev; 435#else 436 dev_t dev; 437#endif 438 int flags; 439{ 440 int unit = GET_MINOR(dev); 441 442 if (IPL_LOGMAX < unit) 443 unit = ENXIO; 444 else 445 unit = 0; 446 return unit; 447} 448 449/* 450 * ipfread/ipflog 451 * both of these must operate with at least splnet() lest they be 452 * called during packet processing and cause an inconsistancy to appear in 453 * the filter lists. 454 */ 455#if (BSD >= 199306) 456static int ipfread(dev, uio, ioflag) 457 int ioflag; 458#else 459static int ipfread(dev, uio) 460#endif 461#if (__FreeBSD_version >= 502116) 462 struct cdev *dev; 463#else 464 dev_t dev; 465#endif 466 struct uio *uio; 467{ 468 int unit = GET_MINOR(dev); 469 470 if (unit < 0) 471 return ENXIO; 472 473 if (ipfmain.ipf_running < 1) 474 return EIO; 475 476 if (unit == IPL_LOGSYNC) 477 return ipf_sync_read(&ipfmain, uio); 478 479#ifdef IPFILTER_LOG 480 return ipf_log_read(&ipfmain, unit, uio); 481#else 482 return ENXIO; 483#endif 484} 485 486 487/* 488 * ipfwrite 489 * both of these must operate with at least splnet() lest they be 490 * called during packet processing and cause an inconsistancy to appear in 491 * the filter lists. 492 */ 493#if (BSD >= 199306) 494static int ipfwrite(dev, uio, ioflag) 495 int ioflag; 496#else 497static int ipfwrite(dev, uio) 498#endif 499#if (__FreeBSD_version >= 502116) 500 struct cdev *dev; 501#else 502 dev_t dev; 503#endif 504 struct uio *uio; 505{ 506 507 if (ipfmain.ipf_running < 1) 508 return EIO; 509 510 if (GET_MINOR(dev) == IPL_LOGSYNC) 511 return ipf_sync_write(&ipfmain, uio); 512 return ENXIO; 513} 514 515static int 516ipf_fbsd_sysctl_create(main_softc) 517 ipf_main_softc_t *main_softc; 518{ 519 ipf_nat_softc_t *nat_softc; 520 ipf_state_softc_t *state_softc; 521 ipf_auth_softc_t *auth_softc; 522 ipf_frag_softc_t *frag_softc; 523 524 nat_softc = main_softc->ipf_nat_soft; 525 state_softc = main_softc->ipf_state_soft; 526 auth_softc = main_softc->ipf_auth_soft; 527 frag_softc = main_softc->ipf_frag_soft; 528 529 sysctl_ctx_init(&ipf_clist); 530 531 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_defnatage", CTLFLAG_RWO, 532 &nat_softc->ipf_nat_defage, 0, ""); 533 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_statesize", CTLFLAG_RWO, 534 &state_softc->ipf_state_size, 0, ""); 535 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_statemax", CTLFLAG_RWO, 536 &state_softc->ipf_state_max, 0, ""); 537 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_nattable_max", CTLFLAG_RWO, 538 &nat_softc->ipf_nat_table_max, 0, ""); 539 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_nattable_sz", CTLFLAG_RWO, 540 &nat_softc->ipf_nat_table_sz, 0, ""); 541 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_natrules_sz", CTLFLAG_RWO, 542 &nat_softc->ipf_nat_maprules_sz, 0, ""); 543 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_rdrrules_sz", CTLFLAG_RWO, 544 &nat_softc->ipf_nat_rdrrules_sz, 0, ""); 545 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "ipf_hostmap_sz", CTLFLAG_RWO, 546 &nat_softc->ipf_nat_hostmap_sz, 0, ""); 547 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_authsize", CTLFLAG_RWO, 548 &auth_softc->ipf_auth_size, 0, ""); 549 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_authused", CTLFLAG_RD, 550 &auth_softc->ipf_auth_used, 0, ""); 551 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_defaultauthage", CTLFLAG_RW, 552 &auth_softc->ipf_auth_defaultage, 0, ""); 553 SYSCTL_DYN_IPF(_net_inet_ipf, OID_AUTO, "fr_ipfrttl", CTLFLAG_RW, 554 &frag_softc->ipfr_ttl, 0, ""); 555 return 0; 556} 557 558static int 559ipf_fbsd_sysctl_destroy(main_softc) 560 ipf_main_softc_t *main_softc; 561{ 562 if (sysctl_ctx_free(&ipf_clist)) { 563 printf("sysctl_ctx_free failed"); 564 return(ENOTEMPTY); 565 } 566 return 0; 567} 568 569