1255332Scy/* $FreeBSD$ */ 2255332Scy 3255332Scy/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5255332Scy * 6255332Scy * See the IPFILTER.LICENCE file for details on licencing. 7255332Scy */ 8255332Scy 9255332Scy 10255332Scy#include <sys/param.h> 11255332Scy#include <sys/systm.h> 12255332Scy#include <sys/kernel.h> 13255332Scy#include <sys/module.h> 14255332Scy#include <sys/conf.h> 15255332Scy#include <sys/socket.h> 16255332Scy#include <sys/sysctl.h> 17255332Scy#include <sys/select.h> 18255332Scy#if __FreeBSD_version >= 500000 19255332Scy# include <sys/selinfo.h> 20255332Scy#endif 21255332Scy#include <net/if.h> 22255332Scy#include <netinet/in_systm.h> 23255332Scy#include <netinet/in.h> 24255332Scy 25255332Scy 26255332Scy#include "netinet/ipl.h" 27255332Scy#include "netinet/ip_compat.h" 28255332Scy#include "netinet/ip_fil.h" 29255332Scy#include "netinet/ip_state.h" 30255332Scy#include "netinet/ip_nat.h" 31255332Scy#include "netinet/ip_auth.h" 32255332Scy#include "netinet/ip_frag.h" 33255332Scy#include "netinet/ip_sync.h" 34255332Scy 35255332Scyextern ipf_main_softc_t ipfmain; 36255332Scy 37255332Scy#if __FreeBSD_version >= 502116 38255332Scystatic struct cdev *ipf_devs[IPL_LOGSIZE]; 39255332Scy#else 40255332Scystatic dev_t ipf_devs[IPL_LOGSIZE]; 41255332Scy#endif 42255332Scy 43255332Scy#if 0 44255332Scystatic int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ); 45255332Scy#endif 46255332Scystatic int ipf_modload(void); 47255332Scystatic int ipf_modunload(void); 48255332Scy 49255332Scy#if (__FreeBSD_version >= 500024) 50255332Scy# if (__FreeBSD_version >= 502116) 51255332Scystatic int ipfopen __P((struct cdev*, int, int, struct thread *)); 52255332Scystatic int ipfclose __P((struct cdev*, int, int, struct thread *)); 53255332Scy# else 54255332Scystatic int ipfopen __P((dev_t, int, int, struct thread *)); 55255332Scystatic int ipfclose __P((dev_t, int, int, struct thread *)); 56255332Scy# endif /* __FreeBSD_version >= 502116 */ 57255332Scy#else 58255332Scystatic int ipfopen __P((dev_t, int, int, struct proc *)); 59255332Scystatic int ipfclose __P((dev_t, int, int, struct proc *)); 60255332Scy#endif 61255332Scy#if (__FreeBSD_version >= 502116) 62255332Scystatic int ipfread __P((struct cdev*, struct uio *, int)); 63255332Scystatic int ipfwrite __P((struct cdev*, struct uio *, int)); 64255332Scy#else 65255332Scystatic int ipfread __P((dev_t, struct uio *, int)); 66255332Scystatic int ipfwrite __P((dev_t, struct uio *, int)); 67255332Scy#endif /* __FreeBSD_version >= 502116 */ 68255332Scy 69255332Scy 70255332Scy 71255332ScySYSCTL_DECL(_net_inet); 72255332Scy#define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \ 73255332Scy SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \ 74255332Scy ptr, val, sysctl_ipf_int, "I", descr); 75255332Scy#define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ 76255332Scy#define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) 77255332ScySYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); 78255332Scy#if 0 79255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipf_flags, 0, ""); 80255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipf_pass, 0, ""); 81255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipf_active, 0, ""); 82255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, 83255332Scy &ipf_tcpidletimeout, 0, ""); 84255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, 85255332Scy &ipf_tcphalfclosed, 0, ""); 86255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, 87255332Scy &ipf_tcpclosewait, 0, ""); 88255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO, 89255332Scy &ipf_tcplastack, 0, ""); 90255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, 91255332Scy &ipf_tcptimeout, 0, ""); 92255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, 93255332Scy &ipf_tcpclosed, 0, ""); 94255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, 95255332Scy &ipf_udptimeout, 0, ""); 96255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO, 97255332Scy &ipf_udpacktimeout, 0, ""); 98255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, 99255332Scy &ipf_icmptimeout, 0, ""); 100255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO, 101255332Scy &ipf_nat_defage, 0, ""); 102255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW, 103255332Scy &ipf_ipfrttl, 0, ""); 104255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD, 105255332Scy &ipf_running, 0, ""); 106255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO, 107255332Scy &ipf_state_size, 0, ""); 108255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO, 109255332Scy &ipf_state_max, 0, ""); 110255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO, 111255332Scy &ipf_nat_table_sz, 0, ""); 112255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO, 113255332Scy &ipf_nat_maprules_sz, 0, ""); 114255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO, 115255332Scy &ipf_nat_rdrrules_sz, 0, ""); 116255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO, 117255332Scy &ipf_nat_hostmap_sz, 0, ""); 118255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO, 119255332Scy &ipf_auth_size, 0, ""); 120255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, 121255332Scy &ipf_auth_used, 0, ""); 122255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, 123255332Scy &ipf_auth_defaultage, 0, ""); 124255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipf_chksrc, 0, ""); 125255332ScySYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipf_minttl, 0, ""); 126255332Scy#endif 127255332Scy 128255332Scy#define CDEV_MAJOR 79 129255332Scy#include <sys/poll.h> 130255332Scy#if __FreeBSD_version >= 500043 131255332Scy# include <sys/select.h> 132255332Scystatic int ipfpoll(struct cdev *dev, int events, struct thread *td); 133255332Scy 134255332Scystatic struct cdevsw ipf_cdevsw = { 135255332Scy#if __FreeBSD_version >= 502103 136255332Scy .d_version = D_VERSION, 137255332Scy .d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */ 138255332Scy#endif 139255332Scy .d_open = ipfopen, 140255332Scy .d_close = ipfclose, 141255332Scy .d_read = ipfread, 142255332Scy .d_write = ipfwrite, 143255332Scy .d_ioctl = ipfioctl, 144255332Scy .d_poll = ipfpoll, 145255332Scy .d_name = "ipf", 146255332Scy#if __FreeBSD_version < 600000 147255332Scy .d_maj = CDEV_MAJOR, 148255332Scy#endif 149255332Scy}; 150255332Scy#else 151255332Scystatic int ipfpoll(dev_t dev, int events, struct proc *td); 152255332Scy 153255332Scystatic struct cdevsw ipf_cdevsw = { 154255332Scy /* open */ ipfopen, 155255332Scy /* close */ ipfclose, 156255332Scy /* read */ ipfread, 157255332Scy /* write */ ipfwrite, 158255332Scy /* ioctl */ ipfioctl, 159255332Scy /* poll */ ipfpoll, 160255332Scy /* mmap */ nommap, 161255332Scy /* strategy */ nostrategy, 162255332Scy /* name */ "ipf", 163255332Scy /* maj */ CDEV_MAJOR, 164255332Scy /* dump */ nodump, 165255332Scy /* psize */ nopsize, 166255332Scy /* flags */ 0, 167255332Scy# if (__FreeBSD_version < 500043) 168255332Scy /* bmaj */ -1, 169255332Scy# endif 170255332Scy# if (__FreeBSD_version >= 430000) 171255332Scy /* kqfilter */ NULL 172255332Scy# endif 173255332Scy}; 174255332Scy#endif 175255332Scy 176255332Scystatic char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME, 177255332Scy IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL }; 178255332Scy 179255332Scy 180255332Scystatic int 181255332Scyipfilter_modevent(module_t mod, int type, void *unused) 182255332Scy{ 183255332Scy int error = 0; 184255332Scy 185255332Scy switch (type) 186255332Scy { 187255332Scy case MOD_LOAD : 188255332Scy error = ipf_modload(); 189255332Scy break; 190255332Scy 191255332Scy case MOD_UNLOAD : 192255332Scy error = ipf_modunload(); 193255332Scy break; 194255332Scy default: 195255332Scy error = EINVAL; 196255332Scy break; 197255332Scy } 198255332Scy return error; 199255332Scy} 200255332Scy 201255332Scy 202255332Scystatic int 203255332Scyipf_modload() 204255332Scy{ 205255332Scy char *defpass, *c, *str; 206255332Scy int i, j, error; 207255332Scy 208255332Scy if (ipf_load_all() != 0) 209255332Scy return EIO; 210255332Scy 211255332Scy if (ipf_create_all(&ipfmain) == NULL) 212255332Scy return EIO; 213255332Scy 214255332Scy error = ipfattach(&ipfmain); 215255332Scy if (error) 216255332Scy return error; 217255332Scy 218255332Scy for (i = 0; i < IPL_LOGSIZE; i++) 219255332Scy ipf_devs[i] = NULL; 220255332Scy 221255332Scy for (i = 0; (str = ipf_devfiles[i]); i++) { 222255332Scy c = NULL; 223255332Scy for(j = strlen(str); j > 0; j--) 224255332Scy if (str[j] == '/') { 225255332Scy c = str + j + 1; 226255332Scy break; 227255332Scy } 228255332Scy if (!c) 229255332Scy c = str; 230255332Scy ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, c); 231255332Scy } 232255332Scy 233255332Scy error = ipf_pfil_hook(); 234255332Scy if (error != 0) 235255332Scy return error; 236255332Scy ipf_event_reg(); 237255332Scy 238255332Scy if (FR_ISPASS(ipfmain.ipf_pass)) 239255332Scy defpass = "pass"; 240255332Scy else if (FR_ISBLOCK(ipfmain.ipf_pass)) 241255332Scy defpass = "block"; 242255332Scy else 243255332Scy defpass = "no-match -> block"; 244255332Scy 245255332Scy printf("%s initialized. Default = %s all, Logging = %s%s\n", 246255332Scy ipfilter_version, defpass, 247255332Scy#ifdef IPFILTER_LOG 248255332Scy "enabled", 249255332Scy#else 250255332Scy "disabled", 251255332Scy#endif 252255332Scy#ifdef IPFILTER_COMPILED 253255332Scy " (COMPILED)" 254255332Scy#else 255255332Scy "" 256255332Scy#endif 257255332Scy ); 258255332Scy return 0; 259255332Scy} 260255332Scy 261255332Scy 262255332Scystatic int 263255332Scyipf_modunload() 264255332Scy{ 265255332Scy int error, i; 266255332Scy 267255332Scy if (ipfmain.ipf_refcnt) 268255332Scy return EBUSY; 269255332Scy 270255332Scy error = ipf_pfil_unhook(); 271255332Scy if (error != 0) 272255332Scy return error; 273255332Scy 274255332Scy if (ipfmain.ipf_running >= 0) { 275255332Scy error = ipfdetach(&ipfmain); 276255332Scy if (error != 0) 277255332Scy return error; 278255332Scy 279255332Scy ipf_destroy_all(&ipfmain); 280255332Scy ipf_unload_all(); 281255332Scy } else 282255332Scy error = 0; 283255332Scy 284255332Scy ipfmain.ipf_running = -2; 285255332Scy 286255332Scy for (i = 0; ipf_devfiles[i]; i++) { 287255332Scy if (ipf_devs[i] != NULL) 288255332Scy destroy_dev(ipf_devs[i]); 289255332Scy } 290255332Scy 291255332Scy printf("%s unloaded\n", ipfilter_version); 292255332Scy 293255332Scy return error; 294255332Scy} 295255332Scy 296255332Scy 297255332Scystatic moduledata_t ipfiltermod = { 298255332Scy "ipfilter", 299255332Scy ipfilter_modevent, 300255332Scy 0 301255332Scy}; 302255332Scy 303255332Scy 304255332ScyDECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); 305255332Scy#ifdef MODULE_VERSION 306255332ScyMODULE_VERSION(ipfilter, 1); 307255332Scy#endif 308255332Scy 309255332Scy 310255332Scy#if 0 311255332Scy#ifdef SYSCTL_IPF 312255332Scyint 313255332Scysysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) 314255332Scy{ 315255332Scy int error = 0; 316255332Scy 317255332Scy if (arg1) 318255332Scy error = SYSCTL_OUT(req, arg1, sizeof(int)); 319255332Scy else 320255332Scy error = SYSCTL_OUT(req, &arg2, sizeof(int)); 321255332Scy 322255332Scy if (error || !req->newptr) 323255332Scy return (error); 324255332Scy 325255332Scy if (!arg1) 326255332Scy error = EPERM; 327255332Scy else { 328255332Scy if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0)) 329255332Scy error = EBUSY; 330255332Scy else 331255332Scy error = SYSCTL_IN(req, arg1, sizeof(int)); 332255332Scy } 333255332Scy return (error); 334255332Scy} 335255332Scy#endif 336255332Scy#endif 337255332Scy 338255332Scy 339255332Scystatic int 340255332Scy#if __FreeBSD_version >= 500043 341255332Scyipfpoll(struct cdev *dev, int events, struct thread *td) 342255332Scy#else 343255332Scyipfpoll(dev_t dev, int events, struct proc *td) 344255332Scy#endif 345255332Scy{ 346255332Scy u_int unit = GET_MINOR(dev); 347255332Scy int revents; 348255332Scy 349255332Scy if (unit < 0 || unit > IPL_LOGMAX) 350255332Scy return 0; 351255332Scy 352255332Scy revents = 0; 353255332Scy 354255332Scy switch (unit) 355255332Scy { 356255332Scy case IPL_LOGIPF : 357255332Scy case IPL_LOGNAT : 358255332Scy case IPL_LOGSTATE : 359255332Scy#ifdef IPFILTER_LOG 360255332Scy if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit)) 361255332Scy revents |= events & (POLLIN | POLLRDNORM); 362255332Scy#endif 363255332Scy break; 364255332Scy case IPL_LOGAUTH : 365255332Scy if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain)) 366255332Scy revents |= events & (POLLIN | POLLRDNORM); 367255332Scy break; 368255332Scy case IPL_LOGSYNC : 369255332Scy if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain)) 370255332Scy revents |= events & (POLLIN | POLLRDNORM); 371255332Scy if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain)) 372255332Scy revents |= events & (POLLOUT | POLLWRNORM); 373255332Scy break; 374255332Scy case IPL_LOGSCAN : 375255332Scy case IPL_LOGLOOKUP : 376255332Scy default : 377255332Scy break; 378255332Scy } 379255332Scy 380255332Scy if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0)) 381255332Scy selrecord(td, &ipfmain.ipf_selwait[unit]); 382255332Scy 383255332Scy return revents; 384255332Scy} 385255332Scy 386255332Scy 387255332Scy/* 388255332Scy * routines below for saving IP headers to buffer 389255332Scy */ 390255332Scystatic int ipfopen(dev, flags 391255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 392255332Scy, devtype, p) 393255332Scy int devtype; 394255332Scy# if (__FreeBSD_version >= 500024) 395255332Scy struct thread *p; 396255332Scy# else 397255332Scy struct proc *p; 398255332Scy# endif /* __FreeBSD_version >= 500024 */ 399255332Scy#else 400255332Scy) 401255332Scy#endif 402255332Scy#if (__FreeBSD_version >= 502116) 403255332Scy struct cdev *dev; 404255332Scy#else 405255332Scy dev_t dev; 406255332Scy#endif 407255332Scy int flags; 408255332Scy{ 409255332Scy u_int unit = GET_MINOR(dev); 410255332Scy int error; 411255332Scy 412255332Scy if (IPL_LOGMAX < unit) 413255332Scy error = ENXIO; 414255332Scy else { 415255332Scy switch (unit) 416255332Scy { 417255332Scy case IPL_LOGIPF : 418255332Scy case IPL_LOGNAT : 419255332Scy case IPL_LOGSTATE : 420255332Scy case IPL_LOGAUTH : 421255332Scy case IPL_LOGLOOKUP : 422255332Scy case IPL_LOGSYNC : 423255332Scy#ifdef IPFILTER_SCAN 424255332Scy case IPL_LOGSCAN : 425255332Scy#endif 426255332Scy error = 0; 427255332Scy break; 428255332Scy default : 429255332Scy error = ENXIO; 430255332Scy break; 431255332Scy } 432255332Scy } 433255332Scy return error; 434255332Scy} 435255332Scy 436255332Scy 437255332Scystatic int ipfclose(dev, flags 438255332Scy#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 439255332Scy, devtype, p) 440255332Scy int devtype; 441255332Scy# if (__FreeBSD_version >= 500024) 442255332Scy struct thread *p; 443255332Scy# else 444255332Scy struct proc *p; 445255332Scy# endif /* __FreeBSD_version >= 500024 */ 446255332Scy#else 447255332Scy) 448255332Scy#endif 449255332Scy#if (__FreeBSD_version >= 502116) 450255332Scy struct cdev *dev; 451255332Scy#else 452255332Scy dev_t dev; 453255332Scy#endif 454255332Scy int flags; 455255332Scy{ 456255332Scy u_int unit = GET_MINOR(dev); 457255332Scy 458255332Scy if (IPL_LOGMAX < unit) 459255332Scy unit = ENXIO; 460255332Scy else 461255332Scy unit = 0; 462255332Scy return unit; 463255332Scy} 464255332Scy 465255332Scy/* 466255332Scy * ipfread/ipflog 467255332Scy * both of these must operate with at least splnet() lest they be 468255332Scy * called during packet processing and cause an inconsistancy to appear in 469255332Scy * the filter lists. 470255332Scy */ 471255332Scy#if (BSD >= 199306) 472255332Scystatic int ipfread(dev, uio, ioflag) 473255332Scy int ioflag; 474255332Scy#else 475255332Scystatic int ipfread(dev, uio) 476255332Scy#endif 477255332Scy#if (__FreeBSD_version >= 502116) 478255332Scy struct cdev *dev; 479255332Scy#else 480255332Scy dev_t dev; 481255332Scy#endif 482255332Scy struct uio *uio; 483255332Scy{ 484255332Scy u_int unit = GET_MINOR(dev); 485255332Scy 486255332Scy if (unit < 0) 487255332Scy return ENXIO; 488255332Scy 489255332Scy if (ipfmain.ipf_running < 1) 490255332Scy return EIO; 491255332Scy 492255332Scy if (unit == IPL_LOGSYNC) 493255332Scy return ipf_sync_read(&ipfmain, uio); 494255332Scy 495255332Scy#ifdef IPFILTER_LOG 496255332Scy return ipf_log_read(&ipfmain, unit, uio); 497255332Scy#else 498255332Scy return ENXIO; 499255332Scy#endif 500255332Scy} 501255332Scy 502255332Scy 503255332Scy/* 504255332Scy * ipfwrite 505255332Scy * both of these must operate with at least splnet() lest they be 506255332Scy * called during packet processing and cause an inconsistancy to appear in 507255332Scy * the filter lists. 508255332Scy */ 509255332Scy#if (BSD >= 199306) 510255332Scystatic int ipfwrite(dev, uio, ioflag) 511255332Scy int ioflag; 512255332Scy#else 513255332Scystatic int ipfwrite(dev, uio) 514255332Scy#endif 515255332Scy#if (__FreeBSD_version >= 502116) 516255332Scy struct cdev *dev; 517255332Scy#else 518255332Scy dev_t dev; 519255332Scy#endif 520255332Scy struct uio *uio; 521255332Scy{ 522255332Scy 523255332Scy if (ipfmain.ipf_running < 1) 524255332Scy return EIO; 525255332Scy 526255332Scy if (GET_MINOR(dev) == IPL_LOGSYNC) 527255332Scy return ipf_sync_write(&ipfmain, uio); 528255332Scy return ENXIO; 529255332Scy} 530