mls_ipl.c revision 259128
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#include <sys/types.h> 13#include <sys/stat.h> 14#include <sys/time.h> 15#include <sys/file.h> 16#include <sys/socket.h> 17#include <sys/conf.h> 18#include <sys/syslog.h> 19#include <sys/buf.h> 20#include <sys/mbuf.h> 21#include <sys/param.h> 22#include <sys/errno.h> 23#include <sys/uio.h> 24#include <sys/vnode.h> 25#include <sundev/mbvar.h> 26#include <sun/autoconf.h> 27#include <sun/vddrv.h> 28#if defined(sun4c) || defined(sun4m) 29# include <sun/openprom.h> 30#endif 31#include <netinet/in.h> 32#include <netinet/in_systm.h> 33#include <netinet/ip.h> 34#include <netinet/ip_var.h> 35#include <netinet/tcp.h> 36#include <netinet/tcpip.h> 37#include <net/if.h> 38#include "ipl.h" 39#include "ip_compat.h" 40#include "ip_fil.h" 41 42 43#if !defined(lint) 44static const char sccsid[] = "@(#)mls_ipl.c 2.6 10/15/95 (C) 1993-2000 Darren Reed"; 45static const char rcsid[] = "@(#)$Id$"; 46#endif 47 48extern int ipfdetach __P((void)); 49#ifndef IPFILTER_LOG 50#define ipfread nulldev 51#endif 52extern int nulldev __P((void)); 53extern int errno; 54 55extern int nodev __P((void)); 56 57static int unload __P((void)); 58static int ipf_attach __P((void)); 59int xxxinit __P((u_int, struct vddrv *, caddr_t, struct vdstat *)); 60static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, 61 IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME, 62 IPLOOKUP_NAME, NULL }; 63static int ipfopen __P((dev_t, int)); 64static int ipfclose __P((dev_t, int)); 65static int ipfread __P((dev_t, struct uio *)); 66static int ipfwrite __P((dev_t, struct uio *)); 67 68 69struct cdevsw ipfdevsw = 70{ 71 ipfopen, ipfclose, ipfread, nulldev, 72 ipfioctl, nulldev, nulldev, nulldev, 73 0, nulldev, 74}; 75 76 77struct dev_ops ipf_ops = 78{ 79 1, 80 ipfidentify, 81 ipfattach, 82 ipfopen, 83 ipfclose, 84 ipfread, 85 ipfwrite, 86 NULL, /* strategy */ 87 NULL, /* dump */ 88 0, /* psize */ 89 ipfioctl, 90 NULL, /* reset */ 91 NULL /* mmap */ 92}; 93 94int ipf_major = 0; 95 96#ifdef sun4m 97struct vdldrv vd = 98{ 99 VDMAGIC_PSEUDO, 100 IPL_VERSION, 101 &ipf_ops, 102 NULL, 103 &ipfdevsw, 104 0, 105 0, 106 NULL, 107 NULL, 108 NULL, 109 0, 110 1, 111}; 112#else /* sun4m */ 113struct vdldrv vd = 114{ 115 VDMAGIC_PSEUDO, /* magic */ 116 IPL_VERSION, 117#ifdef sun4c 118 &ipf_ops, /* dev_ops */ 119#else 120 NULL, /* struct mb_ctlr *mb_ctlr */ 121 NULL, /* struct mb_driver *mb_driver */ 122 NULL, /* struct mb_device *mb_device */ 123 0, /* num ctlrs */ 124 1, /* numdevs */ 125#endif /* sun4c */ 126 NULL, /* bdevsw */ 127 &ipfdevsw, /* cdevsw */ 128 0, /* block major */ 129 0, /* char major */ 130}; 131#endif /* sun4m */ 132 133extern int vd_unuseddev __P((void)); 134extern struct cdevsw cdevsw[]; 135extern int nchrdev; 136 137xxxinit(fc, vdp, data, vds) 138 u_int fc; 139 struct vddrv *vdp; 140 caddr_t data; 141 struct vdstat *vds; 142{ 143 struct vdioctl_load *vdi = (struct vdioctl_load *)data; 144 145 switch (fc) 146 { 147 case VDLOAD: 148 { 149 struct vdconf *vdc; 150 if (vdi && vdi->vdi_userconf) 151 for (vdc = vdi->vdi_userconf; vdc->vdc_type; vdc++) 152 if (vdc->vdc_type == VDCCHARMAJOR) { 153 ipf_major = vdc->vdc_data; 154 break; 155 } 156 157 if (!ipf_major) { 158 while (ipf_major < nchrdev && 159 cdevsw[ipf_major].d_open != vd_unuseddev) 160 ipf_major++; 161 if (ipf_major == nchrdev) 162 return ENODEV; 163 } 164 vdp->vdd_vdtab = (struct vdlinkage *)&vd; 165 vd.Drv_charmajor = ipf_major; 166 return ipf_attach(); 167 } 168 case VDUNLOAD: 169 return unload(); 170 case VDSTAT: 171 return 0; 172 default: 173 return EIO; 174 } 175} 176 177 178static int 179unload() 180{ 181 int err = 0, i; 182 char *name; 183 184 if (ipf_refcnt != 0) 185 err = EBUSY; 186 else if (ipf_running >= 0) 187 err = ipfdetach(); 188 if (err) 189 return err; 190 191 ipf_running = -2; 192 for (i = 0; (name = ipf_devfiles[i]); i++) 193 (void) vn_remove(name, UIO_SYSSPACE, FILE); 194 printf("%s unloaded\n", ipfilter_version); 195 return 0; 196} 197 198 199static int 200ipf_attach() 201{ 202 struct vnode *vp; 203 struct vattr vattr; 204 int error = 0, fmode = S_IFCHR|0600, i; 205 char *name; 206 207 error = ipfattach(); 208 if (error) 209 return error; 210 211 for (i = 0; (name = ipf_devfiles[i]); i++) { 212 (void) vn_remove(name, UIO_SYSSPACE, FILE); 213 vattr_null(&vattr); 214 vattr.va_type = MFTOVT(fmode); 215 vattr.va_mode = (fmode & 07777); 216 vattr.va_rdev = (ipf_major << 8) | i; 217 218 error = vn_create(name, UIO_SYSSPACE, &vattr, EXCL, 0, &vp); 219 if (error) { 220 printf("IP Filter: vn_create(%s) = %d\n", name, error); 221 break; 222 } else { 223 VN_RELE(vp); 224 } 225 } 226 227 if (error == 0) { 228 char *defpass; 229 230 if (FR_ISPASS(ipf_pass)) 231 defpass = "pass"; 232 else if (FR_ISBLOCK(ipf_pass)) 233 defpass = "block"; 234 else 235 defpass = "no-match -> block"; 236 237 printf("%s initialized. Default = %s all, Logging = %s%s\n", 238 ipfilter_version, defpass, 239#ifdef IPFILTER_LOG 240 "enabled", 241#else 242 "disabled", 243#endif 244#ifdef IPFILTER_COMPILED 245 " (COMPILED)" 246#else 247 "" 248#endif 249 ); 250 ipf_running = 1; 251 } 252 return error; 253} 254 255 256/* 257 * routines below for saving IP headers to buffer 258 */ 259static int 260ipfopen(dev, flags) 261 dev_t dev; 262 int flags; 263{ 264 u_int unit = GET_MINOR(dev); 265 int error; 266 267 if (IPL_LOGMAX < unit) { 268 error = ENXIO; 269 } else { 270 switch (unit) 271 { 272 case IPL_LOGIPF : 273 case IPL_LOGNAT : 274 case IPL_LOGSTATE : 275 case IPL_LOGAUTH : 276 case IPL_LOGLOOKUP : 277 case IPL_LOGSYNC : 278#ifdef IPFILTER_SCAN 279 case IPL_LOGSCAN : 280#endif 281 error = 0; 282 break; 283 default : 284 error = ENXIO; 285 break; 286 } 287 } 288 return error; 289} 290 291 292static int 293ipfclose(dev, flags) 294 dev_t dev; 295 int flags; 296{ 297 u_int unit = GET_MINOR(dev); 298 299 if (IPL_LOGMAX < unit) 300 unit = ENXIO; 301 else 302 unit = 0; 303 return unit; 304} 305 306 307/* 308 * ipfread/ipflog 309 * both of these must operate with at least splnet() lest they be 310 * called during packet processing and cause an inconsistancy to appear in 311 * the filter lists. 312 */ 313static int 314ipfread(dev, uio) 315 dev_t dev; 316 register struct uio *uio; 317{ 318 319 if (ipf_running < 1) { 320 ipfmain.ipf_interror = 130006; 321 return EIO; 322 } 323 324#ifdef IPFILTER_LOG 325 return ipflog_read(GET_MINOR(dev), uio); 326#else 327 ipfmain.ipf_interror = 130007; 328 return ENXIO; 329#endif 330} 331 332 333/* 334 * ipfwrite 335 */ 336static int 337ipfwrite(dev, uio) 338 dev_t dev; 339 register struct uio *uio; 340{ 341 342 if (ipf_running < 1) { 343 ipfmain.ipf_interror = 130008; 344 return EIO; 345 } 346 347 if (getminor(dev) == IPL_LOGSYNC) 348 return ipfsync_write(uio); 349 ipfmain.ipf_interror = 130009; 350 return ENXIO; 351} 352