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