1/* $FreeBSD$ */ 2 3/* 4 * Copyright (C) 2000 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 36#if __FreeBSD_version >= 502116 37static struct cdev *ipf_devs[IPL_LOGSIZE]; 38#else 39static dev_t ipf_devs[IPL_LOGSIZE]; 40#endif 41 42static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ); 43static int ipf_modload(void); 44static int ipf_modunload(void); 45 46SYSCTL_DECL(_net_inet); 47#define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \ 48 SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \ 49 ptr, val, sysctl_ipf_int, "I", descr); 50#define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ 51#define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) 52SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); 53SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, ""); 54SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, ""); 55SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, ""); 56SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, 57 &fr_tcpidletimeout, 0, ""); 58SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, 59 &fr_tcphalfclosed, 0, ""); 60SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, 61 &fr_tcpclosewait, 0, ""); 62SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO, 63 &fr_tcplastack, 0, ""); 64SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, 65 &fr_tcptimeout, 0, ""); 66SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, 67 &fr_tcpclosed, 0, ""); 68SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, 69 &fr_udptimeout, 0, ""); 70SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO, 71 &fr_udpacktimeout, 0, ""); 72SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, 73 &fr_icmptimeout, 0, ""); 74SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO, 75 &fr_defnatage, 0, ""); 76SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW, 77 &fr_ipfrttl, 0, ""); 78SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD, 79 &fr_running, 0, ""); 80SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO, 81 &fr_statesize, 0, ""); 82SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO, 83 &fr_statemax, 0, ""); 84SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO, 85 &ipf_nattable_sz, 0, ""); 86SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO, 87 &ipf_natrules_sz, 0, ""); 88SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO, 89 &ipf_rdrrules_sz, 0, ""); 90SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO, 91 &ipf_hostmap_sz, 0, ""); 92SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO, 93 &fr_authsize, 0, ""); 94SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, 95 &fr_authused, 0, ""); 96SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, 97 &fr_defaultauthage, 0, ""); 98SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, ""); 99SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, ""); 100 101#define CDEV_MAJOR 79 102#include <sys/poll.h> 103#if __FreeBSD_version >= 500043 104# include <sys/select.h> 105static int iplpoll(struct cdev *dev, int events, struct thread *td); 106 107static struct cdevsw ipl_cdevsw = { 108# if __FreeBSD_version >= 502103 109 .d_version = D_VERSION, 110 .d_flags = 0, /* D_NEEDGIANT - Should be SMP safe */ 111# endif 112 .d_open = iplopen, 113 .d_close = iplclose, 114 .d_read = iplread, 115 .d_write = iplwrite, 116 .d_ioctl = iplioctl, 117 .d_name = "ipl", 118# if __FreeBSD_version >= 500043 119 .d_poll = iplpoll, 120# endif 121# if __FreeBSD_version < 600000 122 .d_maj = CDEV_MAJOR, 123# endif 124}; 125#else 126static int iplpoll(dev_t dev, int events, struct proc *p); 127 128static struct cdevsw ipl_cdevsw = { 129 /* open */ iplopen, 130 /* close */ iplclose, 131 /* read */ iplread, 132 /* write */ iplwrite, 133 /* ioctl */ iplioctl, 134 /* poll */ iplpoll, 135 /* mmap */ nommap, 136 /* strategy */ nostrategy, 137 /* name */ "ipl", 138 /* maj */ CDEV_MAJOR, 139 /* dump */ nodump, 140 /* psize */ nopsize, 141 /* flags */ 0, 142# if (__FreeBSD_version < 500043) 143 /* bmaj */ -1, 144# endif 145# if (__FreeBSD_version > 430000) 146 /* kqfilter */ NULL 147# endif 148}; 149#endif 150 151static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME, 152 IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL }; 153 154 155static int 156ipfilter_modevent(module_t mod, int type, void *unused) 157{ 158 int error = 0; 159 160 switch (type) 161 { 162 case MOD_LOAD : 163 error = ipf_modload(); 164 break; 165 166 case MOD_UNLOAD : 167 error = ipf_modunload(); 168 break; 169 default: 170 error = EINVAL; 171 break; 172 } 173 return error; 174} 175 176 177static int 178ipf_modload() 179{ 180 char *defpass, *c, *str; 181 int i, j, error; 182 183 RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); 184 RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); 185 RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); 186 187 error = ipfattach(); 188 if (error) { 189 RW_DESTROY(&ipf_global); 190 RW_DESTROY(&ipf_mutex); 191 RW_DESTROY(&ipf_frcache); 192 return error; 193 } 194 195 for (i = 0; i < IPL_LOGSIZE; i++) 196 ipf_devs[i] = NULL; 197 198 for (i = 0; (str = ipf_devfiles[i]); i++) { 199 c = NULL; 200 for(j = strlen(str); j > 0; j--) 201 if (str[j] == '/') { 202 c = str + j + 1; 203 break; 204 } 205 if (!c) 206 c = str; 207 ipf_devs[i] = make_dev(&ipl_cdevsw, i, 0, 0, 0600, "%s", c); 208 } 209 210 error = ipf_pfil_hook(); 211 if (error != 0) 212 return error; 213 ipf_event_reg(); 214 215 if (FR_ISPASS(fr_pass)) 216 defpass = "pass"; 217 else if (FR_ISBLOCK(fr_pass)) 218 defpass = "block"; 219 else 220 defpass = "no-match -> block"; 221 222 printf("%s initialized. Default = %s all, Logging = %s%s\n", 223 ipfilter_version, defpass, 224#ifdef IPFILTER_LOG 225 "enabled", 226#else 227 "disabled", 228#endif 229#ifdef IPFILTER_COMPILED 230 " (COMPILED)" 231#else 232 "" 233#endif 234 ); 235 return 0; 236} 237 238 239static int 240ipf_modunload() 241{ 242 int error, i; 243 244 if (fr_refcnt) 245 return EBUSY; 246 247 if (fr_running >= 0) { 248 ipf_pfil_unhook(); 249 ipf_event_dereg(); 250 WRITE_ENTER(&ipf_global); 251 error = ipfdetach(); 252 RWLOCK_EXIT(&ipf_global); 253 if (error != 0) 254 return error; 255 } else 256 error = 0; 257 258 RW_DESTROY(&ipf_global); 259 RW_DESTROY(&ipf_mutex); 260 RW_DESTROY(&ipf_frcache); 261 262 fr_running = -2; 263 264 for (i = 0; ipf_devfiles[i]; i++) { 265 if (ipf_devs[i] != NULL) 266 destroy_dev(ipf_devs[i]); 267 } 268 269 printf("%s unloaded\n", ipfilter_version); 270 271 return error; 272} 273 274 275static moduledata_t ipfiltermod = { 276 "ipfilter", 277 ipfilter_modevent, 278 0 279}; 280 281 282DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); 283#ifdef MODULE_VERSION 284MODULE_VERSION(ipfilter, 1); 285#endif 286 287 288#ifdef SYSCTL_IPF 289int 290sysctl_ipf_int ( SYSCTL_HANDLER_ARGS ) 291{ 292 int error = 0; 293 294 if (arg1) 295 error = SYSCTL_OUT(req, arg1, sizeof(int)); 296 else 297 error = SYSCTL_OUT(req, &arg2, sizeof(int)); 298 299 if (error || !req->newptr) 300 return (error); 301 302 if (!arg1) 303 error = EPERM; 304 else { 305 if ((oidp->oid_kind & CTLFLAG_OFF) && (fr_running > 0)) 306 error = EBUSY; 307 else 308 error = SYSCTL_IN(req, arg1, sizeof(int)); 309 } 310 return (error); 311} 312#endif 313 314 315static int 316#if __FreeBSD_version >= 500043 317iplpoll(struct cdev *dev, int events, struct thread *td) 318#else 319iplpoll(dev_t dev, int events, struct proc *td) 320#endif 321{ 322 u_int xmin = GET_MINOR(dev); 323 int revents; 324 325 if (xmin < 0 || xmin > IPL_LOGMAX) 326 return 0; 327 328 revents = 0; 329 330 switch (xmin) 331 { 332 case IPL_LOGIPF : 333 case IPL_LOGNAT : 334 case IPL_LOGSTATE : 335#ifdef IPFILTER_LOG 336 if ((events & (POLLIN | POLLRDNORM)) && ipflog_canread(xmin)) 337 revents |= events & (POLLIN | POLLRDNORM); 338#endif 339 break; 340 case IPL_LOGAUTH : 341 if ((events & (POLLIN | POLLRDNORM)) && fr_auth_waiting()) 342 revents |= events & (POLLIN | POLLRDNORM); 343 break; 344 case IPL_LOGSYNC : 345#ifdef IPFILTER_SYNC 346 if ((events & (POLLIN | POLLRDNORM)) && ipfsync_canread()) 347 revents |= events & (POLLIN | POLLRDNORM); 348 if ((events & (POLLOUT | POLLWRNORM)) && ipfsync_canwrite()) 349 revents |= events & (POLLOUT | POLLWRNORM); 350#endif 351 break; 352 case IPL_LOGSCAN : 353 case IPL_LOGLOOKUP : 354 default : 355 break; 356 } 357 358 if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0)) 359 selrecord(td, &ipfselwait[xmin]); 360 361 return revents; 362} 363