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