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