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 * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate 10 * its own major char number! Way cool patch! 11 */ 12 13 14#include <sys/param.h> 15 16#ifdef IPFILTER_LKM 17# ifndef __FreeBSD_cc_version 18# include <osreldate.h> 19# else 20# if __FreeBSD_cc_version < 430000 21# include <osreldate.h> 22# endif 23# endif 24# define ACTUALLY_LKM_NOT_KERNEL 25#else 26# ifndef __FreeBSD_cc_version 27# include <sys/osreldate.h> 28# else 29# if __FreeBSD_cc_version < 430000 30# include <sys/osreldate.h> 31# endif 32# endif 33#endif 34#include <sys/systm.h> 35#if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) 36# ifndef ACTUALLY_LKM_NOT_KERNEL 37# include "opt_devfs.h" 38# endif 39# include <sys/conf.h> 40# include <sys/kernel.h> 41# ifdef DEVFS 42# include <sys/devfsext.h> 43# endif /*DEVFS*/ 44#endif 45#include <sys/conf.h> 46#include <sys/file.h> 47#if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 48# include <sys/lock.h> 49#endif 50#include <sys/stat.h> 51#include <sys/proc.h> 52#include <sys/kernel.h> 53#include <sys/vnode.h> 54#include <sys/namei.h> 55#include <sys/malloc.h> 56#include <sys/mount.h> 57#include <sys/exec.h> 58#include <sys/mbuf.h> 59#if BSD >= 199506 60# include <sys/sysctl.h> 61#endif 62#if (__FreeBSD_version >= 300000) 63# include <sys/socket.h> 64#endif 65#include <net/if.h> 66#include <netinet/in_systm.h> 67#include <netinet/in.h> 68#include <netinet/ip.h> 69#include <net/route.h> 70#include <netinet/ip_var.h> 71#include <netinet/tcp.h> 72#include <netinet/tcpip.h> 73#include <sys/sysent.h> 74#include <sys/lkm.h> 75#include "netinet/ipl.h" 76#include "netinet/ip_compat.h" 77#include "netinet/ip_fil.h" 78#include "netinet/ip_state.h" 79#include "netinet/ip_nat.h" 80#include "netinet/ip_auth.h" 81#include "netinet/ip_frag.h" 82 83 84#if !defined(VOP_LEASE) && defined(LEASE_CHECK) 85#define VOP_LEASE LEASE_CHECK 86#endif 87 88int xxxinit __P((struct lkm_table *, int, int)); 89 90#ifdef SYSCTL_OID 91int sysctl_ipf_int SYSCTL_HANDLER_ARGS; 92# define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \ 93 SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \ 94 ptr, val, sysctl_ipf_int, "I", descr); 95# define CTLFLAG_OFF 0x00800000 /* IPFilter must be disabled */ 96# define CTLFLAG_RWO (CTLFLAG_RW|CTLFLAG_OFF) 97SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF"); 98SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipf_flags, 0, ""); 99SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipf_pass, 0, ""); 100SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipf_active, 0, ""); 101SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipf_chksrc, 0, ""); 102SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipf_minttl, 0, ""); 103SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO, 104 &ipf_tcpidletimeout, 0, ""); 105SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO, 106 &ipf_tcphalfclosed, 0, ""); 107SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO, 108 &ipf_tcpclosewait, 0, ""); 109SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO, 110 &ipf_tcplastack, 0, ""); 111SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO, 112 &ipf_tcptimeout, 0, ""); 113SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO, 114 &ipf_tcpclosed, 0, ""); 115SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO, 116 &ipf_udptimeout, 0, ""); 117SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO, 118 &ipf_icmptimeout, 0, ""); 119SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO, 120 &ipf_defnatage, 0, ""); 121SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW, 122 &ipf_ipfrttl, 0, ""); 123SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD, 124 &ipf_running, 0, ""); 125SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO, 126 &ipf_statesize, 0, ""); 127SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO, 128 &ipf_statemax, 0, ""); 129SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO, 130 &ipf_authsize, 0, ""); 131SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD, 132 &ipf_authused, 0, ""); 133SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW, 134 &ipf_defaultauthage, 0, ""); 135SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ippr_ftp_pasvonly, CTLFLAG_RW, 136 &ippr_ftp_pasvonly, 0, ""); 137#endif 138 139#ifdef DEVFS 140static void *ipf_devfs[IPL_LOGSIZE]; 141#endif 142 143#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) 144int ipf_major = 0; 145 146static struct cdevsw ipfdevsw = 147{ 148 ipfopen, /* open */ 149 ipfclose, /* close */ 150 ipfread, /* read */ 151 (void *)nullop, /* write */ 152 ipfioctl, /* ioctl */ 153 (void *)nullop, /* stop */ 154 (void *)nullop, /* reset */ 155 (void *)NULL, /* tty */ 156 (void *)nullop, /* select */ 157 (void *)nullop, /* mmap */ 158 NULL /* strategy */ 159}; 160 161MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipfdevsw); 162 163extern struct cdevsw cdevsw[]; 164extern int vd_unuseddev __P((void)); 165extern int nchrdev; 166#else 167 168static struct cdevsw ipf_cdevsw = { 169 ipfopen, ipfclose, ipfread, nowrite, /* 79 */ 170 ipfioctl, nostop, noreset, nodevtotty, 171#if (__FreeBSD_version >= 300000) 172 seltrue, nommap, nostrategy, "ipf", 173#else 174 noselect, nommap, nostrategy, "ipf", 175#endif 176 NULL, -1 177}; 178#endif 179 180static void ipf_drvinit __P((void *)); 181 182#ifdef ACTUALLY_LKM_NOT_KERNEL 183static int if_ipf_unload __P((struct lkm_table *, int)); 184static int if_ipf_load __P((struct lkm_table *, int)); 185static int if_ipf_remove __P((void)); 186static int ipf_major = CDEV_MAJOR; 187 188static int ipfaction __P((struct lkm_table *, int)); 189static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, 190 IPL_SCAN, IPL_SYNC, IPL_POOL, NULL }; 191 192extern int lkmenodev __P((void)); 193 194static int ipfaction(lkmtp, cmd) 195 struct lkm_table *lkmtp; 196 int cmd; 197{ 198#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) 199 int i = ipf_major; 200 struct lkm_dev *args = lkmtp->private.lkm_dev; 201#endif 202 int err = 0; 203 204 switch (cmd) 205 { 206 case LKM_E_LOAD : 207 if (lkmexists(lkmtp)) 208 return EEXIST; 209 210#if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000) 211 for (i = 0; i < nchrdev; i++) 212 if (cdevsw[i].d_open == lkmenodev || 213 cdevsw[i].d_open == ipfopen) 214 break; 215 if (i == nchrdev) { 216 printf("IP Filter: No free cdevsw slots\n"); 217 return ENODEV; 218 } 219 220 ipf_major = i; 221 args->lkm_offset = i; /* slot in cdevsw[] */ 222#endif 223 printf("IP Filter: loaded into slot %d\n", ipf_major); 224 err = if_ipf_load(lkmtp, cmd); 225 if (!err) 226 ipf_drvinit((void *)NULL); 227 return err; 228 break; 229 case LKM_E_UNLOAD : 230 err = if_ipf_unload(lkmtp, cmd); 231 if (!err) { 232 printf("IP Filter: unloaded from slot %d\n", 233 ipf_major); 234#ifdef DEVFS 235 if (ipf_devfs[IPL_LOGIPF]) 236 devfs_remove_dev(ipf_devfs[IPL_LOGIPF]); 237 if (ipf_devfs[IPL_LOGNAT]) 238 devfs_remove_dev(ipf_devfs[IPL_LOGNAT]); 239 if (ipf_devfs[IPL_LOGSTATE]) 240 devfs_remove_dev(ipf_devfs[IPL_LOGSTATE]); 241 if (ipf_devfs[IPL_LOGAUTH]) 242 devfs_remove_dev(ipf_devfs[IPL_LOGAUTH]); 243 if (ipf_devfs[IPL_LOGSCAN]) 244 devfs_remove_dev(ipf_devfs[IPL_LOGSCAN]); 245 if (ipf_devfs[IPL_LOGSYNC]) 246 devfs_remove_dev(ipf_devfs[IPL_LOGSYNC]); 247 if (ipf_devfs[IPL_LOGLOOKUP]) 248 devfs_remove_dev(ipf_devfs[IPL_LOGLOOKUP]); 249#endif 250 } 251 return err; 252 case LKM_E_STAT : 253 break; 254 default: 255 err = EIO; 256 break; 257 } 258 return 0; 259} 260 261 262static int if_ipf_remove __P((void)) 263{ 264 char *name; 265 struct nameidata nd; 266 int error, i; 267 268 for (i = 0; (name = ipf_devfiles[i]); i++) { 269 NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc); 270 if ((error = namei(&nd))) 271 return (error); 272 VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE); 273#if (__FreeBSD_version >= 300000) 274 VOP_LOCK(nd.ni_vp, LK_RETRY | LK_EXCLUSIVE, curproc); 275 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); 276 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 277 278 if (nd.ni_dvp == nd.ni_vp) 279 vrele(nd.ni_dvp); 280 else 281 vput(nd.ni_dvp); 282 if (nd.ni_vp != NULLVP) 283 vput(nd.ni_vp); 284#else 285 VOP_LOCK(nd.ni_vp); 286 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); 287 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 288#endif 289 } 290 291 return 0; 292} 293 294 295static int if_ipf_unload(lkmtp, cmd) 296 struct lkm_table *lkmtp; 297 int cmd; 298{ 299 int error = 0; 300 301 error = ipfdetach(); 302 if (!error) 303 error = if_ipf_remove(); 304 return error; 305} 306 307 308static int if_ipf_load(lkmtp, cmd) 309 struct lkm_table *lkmtp; 310 int cmd; 311{ 312 struct nameidata nd; 313 struct vattr vattr; 314 int error = 0, fmode = S_IFCHR|0600, i; 315 char *name; 316 317 error = ipfattach(); 318 if (error) 319 return error; 320 (void) if_ipf_remove(); 321 322 for (i = 0; (name = ipf_devfiles[i]); i++) { 323 NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc); 324 if ((error = namei(&nd))) 325 return error; 326 if (nd.ni_vp != NULL) { 327 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 328 if (nd.ni_dvp == nd.ni_vp) 329 vrele(nd.ni_dvp); 330 else 331 vput(nd.ni_dvp); 332 vrele(nd.ni_vp); 333 return (EEXIST); 334 } 335 VATTR_NULL(&vattr); 336 vattr.va_type = VCHR; 337 vattr.va_mode = (fmode & 07777); 338 vattr.va_rdev = (ipf_major << 8) | i; 339 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE); 340 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 341#if (__FreeBSD_version >= 300000) 342 vput(nd.ni_dvp); 343#endif 344 if (error) 345 return error; 346 } 347 return 0; 348} 349 350#endif /* actually LKM */ 351 352#if defined(__FreeBSD_version) && (__FreeBSD_version < 220000) 353/* 354 * strlen isn't present in 2.1.* kernels. 355 */ 356size_t strlen(string) 357 char *string; 358{ 359 register char *s; 360 361 for (s = string; *s; s++) 362 ; 363 return (size_t)(s - string); 364} 365 366 367int xxxinit(lkmtp, cmd, ver) 368 struct lkm_table *lkmtp; 369 int cmd, ver; 370{ 371 DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); 372} 373#else /* __FREEBSD_version >= 220000 */ 374# ifdef IPFILTER_LKM 375# include <sys/exec.h> 376 377# if (__FreeBSD_version >= 300000) 378MOD_DEV(if_ipf, LM_DT_CHAR, CDEV_MAJOR, &ipf_cdevsw); 379# else 380MOD_DECL(if_ipf); 381 382 383static struct lkm_dev _module = { 384 LM_DEV, 385 LKM_VERSION, 386 IPL_VERSION, 387 CDEV_MAJOR, 388 LM_DT_CHAR, 389 { (void *)&ipf_cdevsw } 390}; 391# endif 392 393 394int if_ipf __P((struct lkm_table *, int, int)); 395 396 397int if_ipf(lkmtp, cmd, ver) 398 struct lkm_table *lkmtp; 399 int cmd, ver; 400{ 401# if (__FreeBSD_version >= 300000) 402 MOD_DISPATCH(if_ipf, lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); 403# else 404 DISPATCH(lkmtp, cmd, ver, ipfaction, ipfaction, ipfaction); 405# endif 406} 407# endif /* IPFILTER_LKM */ 408static ipf_devsw_installed = 0; 409 410static void ipf_drvinit __P((void *unused)) 411{ 412 dev_t dev; 413# ifdef DEVFS 414 void **tp = ipf_devfs; 415# endif 416 417 if (!ipf_devsw_installed ) { 418 dev = makedev(CDEV_MAJOR, 0); 419 cdevsw_add(&dev, &ipf_cdevsw, NULL); 420 ipf_devsw_installed = 1; 421 422# ifdef DEVFS 423 tp[IPL_LOGIPF] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGIPF, 424 DV_CHR, 0, 0, 0600, "ipf"); 425 tp[IPL_LOGNAT] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGNAT, 426 DV_CHR, 0, 0, 0600, "ipnat"); 427 tp[IPL_LOGSTATE] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGSTATE, 428 DV_CHR, 0, 0, 0600, 429 "ipstate"); 430 tp[IPL_LOGAUTH] = devfs_add_devswf(&ipf_cdevsw, IPL_LOGAUTH, 431 DV_CHR, 0, 0, 0600, 432 "ipauth"); 433# endif 434 } 435} 436 437 438#ifdef SYSCTL_IPF 439int 440sysctl_ipf_int SYSCTL_HANDLER_ARGS 441{ 442 int error = 0; 443 444 if (arg1) 445 error = SYSCTL_OUT(req, arg1, sizeof(int)); 446 else 447 error = SYSCTL_OUT(req, &arg2, sizeof(int)); 448 449 if (error || !req->newptr) 450 return (error); 451 452 if (!arg1) 453 error = EPERM; 454 else { 455 if ((oidp->oid_kind & CTLFLAG_OFF) && (ipf_running > 0)) 456 error = EBUSY; 457 else 458 error = SYSCTL_IN(req, arg1, sizeof(int)); 459 } 460 return (error); 461} 462#endif 463 464 465# if defined(IPFILTER_LKM) || \ 466 defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) 467SYSINIT(ipfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipf_drvinit,NULL) 468# endif /* IPFILTER_LKM */ 469#endif /* _FreeBSD_version */ 470 471 472/* 473 * routines below for saving IP headers to buffer 474 */ 475int ipfopen(dev, flags 476#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 477, devtype, p) 478 int devtype; 479# if (__FreeBSD_version >= 500024) 480 struct thread *p; 481# else 482 struct proc *p; 483# endif /* __FreeBSD_version >= 500024 */ 484#else 485) 486#endif 487#if (__FreeBSD_version >= 502116) 488 struct cdev *dev; 489#else 490 dev_t dev; 491#endif 492 int flags; 493{ 494 u_int unit = GET_MINOR(dev); 495 496 if (IPL_LOGMAX < unit) 497 unit = ENXIO; 498 else 499 unit = 0; 500 return unit; 501} 502 503 504int ipfclose(dev, flags 505#if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) 506, devtype, p) 507 int devtype; 508# if (__FreeBSD_version >= 500024) 509 struct thread *p; 510# else 511 struct proc *p; 512# endif /* __FreeBSD_version >= 500024 */ 513#else 514) 515#endif 516#if (__FreeBSD_version >= 502116) 517 struct cdev *dev; 518#else 519 dev_t dev; 520#endif 521 int flags; 522{ 523 u_int unit = GET_MINOR(dev); 524 525 if (IPL_LOGMAX < unit) 526 unit = ENXIO; 527 else 528 unit = 0; 529 return unit; 530} 531 532/* 533 * ipfread/ipflog 534 * both of these must operate with at least splnet() lest they be 535 * called during packet processing and cause an inconsistancy to appear in 536 * the filter lists. 537 */ 538#if (BSD >= 199306) 539int ipfread(dev, uio, ioflag) 540 int ioflag; 541#else 542int ipfread(dev, uio) 543#endif 544#if (__FreeBSD_version >= 502116) 545 struct cdev *dev; 546#else 547 dev_t dev; 548#endif 549 register struct uio *uio; 550{ 551 u_int unit = GET_MINOR(dev); 552 553 if (unit < 0) 554 return ENXIO; 555 556 if (ipf_running < 1) 557 return EIO; 558 559 if (unit == IPL_LOGSYNC) 560 return ipfsync_read(uio); 561 562#ifdef IPFILTER_LOG 563 return ipflog_read(unit, uio); 564#else 565 return ENXIO; 566#endif 567} 568 569 570/* 571 * ipfwrite 572 * both of these must operate with at least splnet() lest they be 573 * called during packet processing and cause an inconsistancy to appear in 574 * the filter lists. 575 */ 576#if (BSD >= 199306) 577int ipfwrite(dev, uio, ioflag) 578 int ioflag; 579#else 580int ipfwrite(dev, uio) 581#endif 582#if (__FreeBSD_version >= 502116) 583 struct cdev *dev; 584#else 585 dev_t dev; 586#endif 587 register struct uio *uio; 588{ 589 590 if (ipf_running < 1) 591 return EIO; 592 593 if (GET_MINOR(dev) == IPL_LOGSYNC) 594 return ipfsync_write(uio); 595 return ENXIO; 596} 597