]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/ipfilter/mls_ipl.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / ipfilter / mls_ipl.c
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)
44 static const char sccsid[] = "@(#)mls_ipl.c     2.6 10/15/95 (C) 1993-2000 Darren Reed";
45 static const char rcsid[] = "@(#)$Id$";
46 #endif
47
48 extern  int     ipfdetach __P((void));
49 #ifndef IPFILTER_LOG
50 #define ipfread nulldev
51 #endif
52 extern  int     nulldev __P((void));
53 extern  int     errno;
54
55 extern int nodev __P((void));
56
57 static  int     unload __P((void));
58 static  int     ipf_attach __P((void));
59 int     xxxinit __P((u_int, struct vddrv *, caddr_t, struct vdstat *));
60 static  char    *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
61                                     IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
62                                     IPLOOKUP_NAME, NULL };
63 static  int     ipfopen __P((dev_t, int));
64 static  int     ipfclose __P((dev_t, int));
65 static  int     ipfread __P((dev_t, struct uio *));
66 static  int     ipfwrite __P((dev_t, struct uio *));
67
68
69 struct  cdevsw  ipfdevsw =
70 {
71         ipfopen, ipfclose, ipfread, nulldev,
72         ipfioctl, nulldev, nulldev, nulldev,
73         0, nulldev,
74 };
75
76
77 struct  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
94 int     ipf_major = 0;
95
96 #ifdef sun4m
97 struct  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 */
113 struct 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
133 extern int vd_unuseddev __P((void));
134 extern struct cdevsw cdevsw[];
135 extern int nchrdev;
136
137 xxxinit(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
178 static int
179 unload()
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
199 static int
200 ipf_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  */
259 static int
260 ipfopen(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
292 static int
293 ipfclose(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  */
313 static int
314 ipfread(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  */
336 static int
337 ipfwrite(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 }