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