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 * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate 10255332Scy * its own major char number! Way cool patch! 11255332Scy */ 12255332Scy#include <sys/types.h> 13255332Scy#include <sys/stat.h> 14255332Scy#include <sys/time.h> 15255332Scy#include <sys/file.h> 16255332Scy#include <sys/socket.h> 17255332Scy#include <sys/conf.h> 18255332Scy#include <sys/syslog.h> 19255332Scy#include <sys/buf.h> 20255332Scy#include <sys/mbuf.h> 21255332Scy#include <sys/param.h> 22255332Scy#include <sys/errno.h> 23255332Scy#include <sys/uio.h> 24255332Scy#include <sys/vnode.h> 25255332Scy#include <sundev/mbvar.h> 26255332Scy#include <sun/autoconf.h> 27255332Scy#include <sun/vddrv.h> 28255332Scy#if defined(sun4c) || defined(sun4m) 29255332Scy# include <sun/openprom.h> 30255332Scy#endif 31255332Scy#include <netinet/in.h> 32255332Scy#include <netinet/in_systm.h> 33255332Scy#include <netinet/ip.h> 34255332Scy#include <netinet/ip_var.h> 35255332Scy#include <netinet/tcp.h> 36255332Scy#include <netinet/tcpip.h> 37255332Scy#include <net/if.h> 38255332Scy#include "ipl.h" 39255332Scy#include "ip_compat.h" 40255332Scy#include "ip_fil.h" 41255332Scy 42255332Scy 43255332Scy#if !defined(lint) 44255332Scystatic const char sccsid[] = "@(#)mls_ipl.c 2.6 10/15/95 (C) 1993-2000 Darren Reed"; 45255332Scystatic const char rcsid[] = "@(#)$Id$"; 46255332Scy#endif 47255332Scy 48255332Scyextern int ipfdetach __P((void)); 49255332Scy#ifndef IPFILTER_LOG 50255332Scy#define ipfread nulldev 51255332Scy#endif 52255332Scyextern int nulldev __P((void)); 53255332Scyextern int errno; 54255332Scy 55255332Scyextern int nodev __P((void)); 56255332Scy 57255332Scystatic int unload __P((void)); 58255332Scystatic int ipf_attach __P((void)); 59255332Scyint xxxinit __P((u_int, struct vddrv *, caddr_t, struct vdstat *)); 60255332Scystatic char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, 61255332Scy IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, 62255332Scy IPLOOKUP_NAME, NULL }; 63255332Scystatic int ipfopen __P((dev_t, int)); 64255332Scystatic int ipfclose __P((dev_t, int)); 65255332Scystatic int ipfread __P((dev_t, struct uio *)); 66255332Scystatic int ipfwrite __P((dev_t, struct uio *)); 67255332Scy 68255332Scy 69255332Scystruct cdevsw ipfdevsw = 70255332Scy{ 71255332Scy ipfopen, ipfclose, ipfread, nulldev, 72255332Scy ipfioctl, nulldev, nulldev, nulldev, 73255332Scy 0, nulldev, 74255332Scy}; 75255332Scy 76255332Scy 77255332Scystruct dev_ops ipf_ops = 78255332Scy{ 79255332Scy 1, 80255332Scy ipfidentify, 81255332Scy ipfattach, 82255332Scy ipfopen, 83255332Scy ipfclose, 84255332Scy ipfread, 85255332Scy ipfwrite, 86255332Scy NULL, /* strategy */ 87255332Scy NULL, /* dump */ 88255332Scy 0, /* psize */ 89255332Scy ipfioctl, 90255332Scy NULL, /* reset */ 91255332Scy NULL /* mmap */ 92255332Scy}; 93255332Scy 94255332Scyint ipf_major = 0; 95255332Scy 96255332Scy#ifdef sun4m 97255332Scystruct vdldrv vd = 98255332Scy{ 99255332Scy VDMAGIC_PSEUDO, 100255332Scy IPL_VERSION, 101255332Scy &ipf_ops, 102255332Scy NULL, 103255332Scy &ipfdevsw, 104255332Scy 0, 105255332Scy 0, 106255332Scy NULL, 107255332Scy NULL, 108255332Scy NULL, 109255332Scy 0, 110255332Scy 1, 111255332Scy}; 112255332Scy#else /* sun4m */ 113255332Scystruct vdldrv vd = 114255332Scy{ 115255332Scy VDMAGIC_PSEUDO, /* magic */ 116255332Scy IPL_VERSION, 117255332Scy#ifdef sun4c 118255332Scy &ipf_ops, /* dev_ops */ 119255332Scy#else 120255332Scy NULL, /* struct mb_ctlr *mb_ctlr */ 121255332Scy NULL, /* struct mb_driver *mb_driver */ 122255332Scy NULL, /* struct mb_device *mb_device */ 123255332Scy 0, /* num ctlrs */ 124255332Scy 1, /* numdevs */ 125255332Scy#endif /* sun4c */ 126255332Scy NULL, /* bdevsw */ 127255332Scy &ipfdevsw, /* cdevsw */ 128255332Scy 0, /* block major */ 129255332Scy 0, /* char major */ 130255332Scy}; 131255332Scy#endif /* sun4m */ 132255332Scy 133255332Scyextern int vd_unuseddev __P((void)); 134255332Scyextern struct cdevsw cdevsw[]; 135255332Scyextern int nchrdev; 136255332Scy 137255332Scyxxxinit(fc, vdp, data, vds) 138255332Scy u_int fc; 139255332Scy struct vddrv *vdp; 140255332Scy caddr_t data; 141255332Scy struct vdstat *vds; 142255332Scy{ 143255332Scy struct vdioctl_load *vdi = (struct vdioctl_load *)data; 144255332Scy 145255332Scy switch (fc) 146255332Scy { 147255332Scy case VDLOAD: 148255332Scy { 149255332Scy struct vdconf *vdc; 150255332Scy if (vdi && vdi->vdi_userconf) 151255332Scy for (vdc = vdi->vdi_userconf; vdc->vdc_type; vdc++) 152255332Scy if (vdc->vdc_type == VDCCHARMAJOR) { 153255332Scy ipf_major = vdc->vdc_data; 154255332Scy break; 155255332Scy } 156255332Scy 157255332Scy if (!ipf_major) { 158255332Scy while (ipf_major < nchrdev && 159255332Scy cdevsw[ipf_major].d_open != vd_unuseddev) 160255332Scy ipf_major++; 161255332Scy if (ipf_major == nchrdev) 162255332Scy return ENODEV; 163255332Scy } 164255332Scy vdp->vdd_vdtab = (struct vdlinkage *)&vd; 165255332Scy vd.Drv_charmajor = ipf_major; 166255332Scy return ipf_attach(); 167255332Scy } 168255332Scy case VDUNLOAD: 169255332Scy return unload(); 170255332Scy case VDSTAT: 171255332Scy return 0; 172255332Scy default: 173255332Scy return EIO; 174255332Scy } 175255332Scy} 176255332Scy 177255332Scy 178255332Scystatic int 179255332Scyunload() 180255332Scy{ 181255332Scy int err = 0, i; 182255332Scy char *name; 183255332Scy 184255332Scy if (ipf_refcnt != 0) 185255332Scy err = EBUSY; 186255332Scy else if (ipf_running >= 0) 187255332Scy err = ipfdetach(); 188255332Scy if (err) 189255332Scy return err; 190255332Scy 191255332Scy ipf_running = -2; 192255332Scy for (i = 0; (name = ipf_devfiles[i]); i++) 193255332Scy (void) vn_remove(name, UIO_SYSSPACE, FILE); 194255332Scy printf("%s unloaded\n", ipfilter_version); 195255332Scy return 0; 196255332Scy} 197255332Scy 198255332Scy 199255332Scystatic int 200255332Scyipf_attach() 201255332Scy{ 202255332Scy struct vnode *vp; 203255332Scy struct vattr vattr; 204255332Scy int error = 0, fmode = S_IFCHR|0600, i; 205255332Scy char *name; 206255332Scy 207255332Scy error = ipfattach(); 208255332Scy if (error) 209255332Scy return error; 210255332Scy 211255332Scy for (i = 0; (name = ipf_devfiles[i]); i++) { 212255332Scy (void) vn_remove(name, UIO_SYSSPACE, FILE); 213255332Scy vattr_null(&vattr); 214255332Scy vattr.va_type = MFTOVT(fmode); 215255332Scy vattr.va_mode = (fmode & 07777); 216255332Scy vattr.va_rdev = (ipf_major << 8) | i; 217255332Scy 218255332Scy error = vn_create(name, UIO_SYSSPACE, &vattr, EXCL, 0, &vp); 219255332Scy if (error) { 220255332Scy printf("IP Filter: vn_create(%s) = %d\n", name, error); 221255332Scy break; 222255332Scy } else { 223255332Scy VN_RELE(vp); 224255332Scy } 225255332Scy } 226255332Scy 227255332Scy if (error == 0) { 228255332Scy char *defpass; 229255332Scy 230255332Scy if (FR_ISPASS(ipf_pass)) 231255332Scy defpass = "pass"; 232255332Scy else if (FR_ISBLOCK(ipf_pass)) 233255332Scy defpass = "block"; 234255332Scy else 235255332Scy defpass = "no-match -> block"; 236255332Scy 237255332Scy printf("%s initialized. Default = %s all, Logging = %s%s\n", 238255332Scy ipfilter_version, defpass, 239255332Scy#ifdef IPFILTER_LOG 240255332Scy "enabled", 241255332Scy#else 242255332Scy "disabled", 243255332Scy#endif 244255332Scy#ifdef IPFILTER_COMPILED 245255332Scy " (COMPILED)" 246255332Scy#else 247255332Scy "" 248255332Scy#endif 249255332Scy ); 250255332Scy ipf_running = 1; 251255332Scy } 252255332Scy return error; 253255332Scy} 254255332Scy 255255332Scy 256255332Scy/* 257255332Scy * routines below for saving IP headers to buffer 258255332Scy */ 259255332Scystatic int 260255332Scyipfopen(dev, flags) 261255332Scy dev_t dev; 262255332Scy int flags; 263255332Scy{ 264255332Scy u_int unit = GET_MINOR(dev); 265255332Scy int error; 266255332Scy 267255332Scy if (IPL_LOGMAX < unit) { 268255332Scy error = ENXIO; 269255332Scy } else { 270255332Scy switch (unit) 271255332Scy { 272255332Scy case IPL_LOGIPF : 273255332Scy case IPL_LOGNAT : 274255332Scy case IPL_LOGSTATE : 275255332Scy case IPL_LOGAUTH : 276255332Scy case IPL_LOGLOOKUP : 277255332Scy case IPL_LOGSYNC : 278255332Scy#ifdef IPFILTER_SCAN 279255332Scy case IPL_LOGSCAN : 280255332Scy#endif 281255332Scy error = 0; 282255332Scy break; 283255332Scy default : 284255332Scy error = ENXIO; 285255332Scy break; 286255332Scy } 287255332Scy } 288255332Scy return error; 289255332Scy} 290255332Scy 291255332Scy 292255332Scystatic int 293255332Scyipfclose(dev, flags) 294255332Scy dev_t dev; 295255332Scy int flags; 296255332Scy{ 297255332Scy u_int unit = GET_MINOR(dev); 298255332Scy 299255332Scy if (IPL_LOGMAX < unit) 300255332Scy unit = ENXIO; 301255332Scy else 302255332Scy unit = 0; 303255332Scy return unit; 304255332Scy} 305255332Scy 306255332Scy 307255332Scy/* 308255332Scy * ipfread/ipflog 309255332Scy * both of these must operate with at least splnet() lest they be 310255332Scy * called during packet processing and cause an inconsistancy to appear in 311255332Scy * the filter lists. 312255332Scy */ 313255332Scystatic int 314255332Scyipfread(dev, uio) 315255332Scy dev_t dev; 316255332Scy register struct uio *uio; 317255332Scy{ 318255332Scy 319255332Scy if (ipf_running < 1) { 320255332Scy ipfmain.ipf_interror = 130006; 321255332Scy return EIO; 322255332Scy } 323255332Scy 324255332Scy#ifdef IPFILTER_LOG 325255332Scy return ipflog_read(GET_MINOR(dev), uio); 326255332Scy#else 327255332Scy ipfmain.ipf_interror = 130007; 328255332Scy return ENXIO; 329255332Scy#endif 330255332Scy} 331255332Scy 332255332Scy 333255332Scy/* 334255332Scy * ipfwrite 335255332Scy */ 336255332Scystatic int 337255332Scyipfwrite(dev, uio) 338255332Scy dev_t dev; 339255332Scy register struct uio *uio; 340255332Scy{ 341255332Scy 342255332Scy if (ipf_running < 1) { 343255332Scy ipfmain.ipf_interror = 130008; 344255332Scy return EIO; 345255332Scy } 346255332Scy 347255332Scy if (getminor(dev) == IPL_LOGSYNC) 348255332Scy return ipfsync_write(uio); 349255332Scy ipfmain.ipf_interror = 130009; 350255332Scy return ENXIO; 351255332Scy} 352