FreeBSD/Linux Kernel Cross Reference
sys/netinet/mlf_ipl.c
1 /*
2 * Copyright (C) 1993-1997 by Darren Reed.
3 *
4 * Redistribution and use in source and binary forms are permitted
5 * provided that this notice is preserved and due credit is given
6 * to the original author and the contributors.
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
13
14 #include <sys/param.h>
15
16 #if defined(__FreeBSD__) && (__FreeBSD__ > 1)
17 # ifdef IPFILTER_LKM
18 # include <osreldate.h>
19 # define ACTUALLY_LKM_NOT_KERNEL
20 # else
21 # ifndef __FreeBSD_version
22 # define __FreeBSD_version 300000 /* this will do as a hack */
23 # endif
24 # endif
25 #endif
26 #include <sys/systm.h>
27 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
28 # include "opt_devfs.h"
29 # include <sys/conf.h>
30 # include <sys/kernel.h>
31 # ifdef DEVFS
32 # include <sys/devfsext.h>
33 # endif /*DEVFS*/
34 #endif
35 #include <sys/conf.h>
36 #include <sys/file.h>
37 #include <sys/lock.h>
38 #include <sys/stat.h>
39 #include <sys/proc.h>
40 #include <sys/uio.h>
41 #include <sys/kernel.h>
42 #include <sys/vnode.h>
43 #include <sys/namei.h>
44 #include <sys/malloc.h>
45 #include <sys/socket.h>
46 #include <sys/exec.h>
47 #include <sys/mbuf.h>
48 #if BSD >= 199506
49 # include <sys/sysctl.h>
50 #endif
51 #if (__FreeBSD_version >= 199511)
52 #include <net/if.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/in.h>
55 #include <netinet/ip.h>
56 #include <net/route.h>
57 #include <netinet/ip_var.h>
58 #include <netinet/tcp.h>
59 #include <netinet/tcpip.h>
60 #endif
61 #if (__FreeBSD__ > 1)
62 # include <sys/sysent.h>
63 #endif
64 #include <sys/lkm.h>
65 #include "netinet/ipl.h"
66 #include "netinet/ip_compat.h"
67 #include "netinet/ip_fil.h"
68 #include "netinet/ip_state.h"
69 #include "netinet/ip_nat.h"
70 #include "netinet/ip_auth.h"
71 #include "netinet/ip_frag.h"
72
73
74 #if !defined(VOP_LEASE) && defined(LEASE_CHECK)
75 #define VOP_LEASE LEASE_CHECK
76 #endif
77
78 #ifndef MIN
79 #define MIN(a,b) (((a)<(b))?(a):(b))
80 #endif
81
82 extern int lkmenodev __P((void));
83
84 int xxxinit __P((struct lkm_table *, int, int));
85
86 #ifdef SYSCTL_INT
87 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
88 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, "");
89 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, "");
90 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
91 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RW,
92 &fr_tcpidletimeout, 0, "");
93 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RW,
94 &fr_tcpclosewait, 0, "");
95 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RW,
96 &fr_tcplastack, 0, "");
97 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RW,
98 &fr_tcptimeout, 0, "");
99 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RW,
100 &fr_tcpclosed, 0, "");
101 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RW,
102 &fr_udptimeout, 0, "");
103 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RW,
104 &fr_icmptimeout, 0, "");
105 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RW,
106 &fr_defnatage, 0, "");
107 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
108 &fr_ipfrttl, 0, "");
109 SYSCTL_INT(_net_inet_ipf, OID_AUTO, ipl_unreach, CTLFLAG_RW,
110 &ipl_unreach, 0, "");
111 SYSCTL_INT(_net_inet_ipf, OID_AUTO, ipl_inited, CTLFLAG_RD,
112 &ipl_inited, 0, "");
113 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RD,
114 &fr_authsize, 0, "");
115 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
116 &fr_authused, 0, "");
117 SYSCTL_INT(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
118 &fr_defaultauthage, 0, "");
119 #endif
120
121 #ifdef DEVFS
122 static void *ipf_devfs[IPL_LOGMAX + 1];
123 #endif
124
125 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
126 int ipl_major = 0;
127
128 static struct cdevsw ipldevsw =
129 {
130 iplopen, /* open */
131 iplclose, /* close */
132 iplread, /* read */
133 (void *)nullop, /* write */
134 iplioctl, /* ioctl */
135 (void *)nullop, /* stop */
136 (void *)nullop, /* reset */
137 (void *)NULL, /* tty */
138 (void *)nullop, /* select */
139 (void *)nullop, /* mmap */
140 NULL /* strategy */
141 };
142
143 MOD_DEV(IPL_VERSION, LM_DT_CHAR, -1, &ipldevsw);
144
145 extern struct cdevsw cdevsw[];
146 extern int vd_unuseddev __P((void));
147 extern int nchrdev;
148 #else
149
150 static struct cdevsw ipl_cdevsw = {
151 iplopen, iplclose, iplread, nowrite, /* 79 */
152 iplioctl, nostop, noreset, nodevtotty,
153 seltrue, nommap, nostrategy, "ipl",
154 NULL, -1
155 };
156 #endif
157
158
159 static void ipl_drvinit __P((void *));
160
161 #ifdef ACTUALLY_LKM_NOT_KERNEL
162 static int if_ipl_unload __P((struct lkm_table *, int));
163 static int if_ipl_load __P((struct lkm_table *, int));
164 static int if_ipl_remove __P((void));
165 static int ipl_major = CDEV_MAJOR;
166
167 static int iplaction __P((struct lkm_table *, int));
168 static char *ipf_devfiles[] = { IPL_NAME, IPL_NAT, IPL_STATE, IPL_AUTH, NULL };
169 static int iplaction(lkmtp, cmd)
170 struct lkm_table *lkmtp;
171 int cmd;
172 {
173 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
174 int i = ipl_major;
175 struct lkm_dev *args = lkmtp->private.lkm_dev;
176 #endif
177 int err = 0;
178
179 switch (cmd)
180 {
181 case LKM_E_LOAD :
182 if (lkmexists(lkmtp))
183 return EEXIST;
184
185 #if !defined(__FreeBSD_version) || (__FreeBSD_version < 220000)
186 for (i = 0; i < nchrdev; i++)
187 if (cdevsw[i].d_open == lkmenodev ||
188 cdevsw[i].d_open == iplopen)
189 break;
190 if (i == nchrdev) {
191 printf("IP Filter: No free cdevsw slots\n");
192 return ENODEV;
193 }
194
195 ipl_major = i;
196 args->lkm_offset = i; /* slot in cdevsw[] */
197 #endif
198 printf("IP Filter: loaded into slot %d\n", ipl_major);
199 err = if_ipl_load(lkmtp, cmd);
200 if (!err)
201 ipl_drvinit((void *)NULL);
202 return err;
203 break;
204 case LKM_E_UNLOAD :
205 err = if_ipl_unload(lkmtp, cmd);
206 if (!err) {
207 printf("IP Filter: unloaded from slot %d\n",
208 ipl_major);
209 # ifdef DEVFS
210 if (ipf_devfs[IPL_LOGIPF])
211 devfs_remove_dev(ipf_devfs[IPL_LOGIPF]);
212 if (ipf_devfs[IPL_LOGNAT])
213 devfs_remove_dev(ipf_devfs[IPL_LOGNAT]);
214 if (ipf_devfs[IPL_LOGSTATE])
215 devfs_remove_dev(ipf_devfs[IPL_LOGSTATE]);
216 if (ipf_devfs[IPL_LOGAUTH])
217 devfs_remove_dev(ipf_devfs[IPL_LOGAUTH]);
218 # endif
219 }
220 return err;
221 case LKM_E_STAT :
222 break;
223 default:
224 err = EIO;
225 break;
226 }
227 return 0;
228 }
229
230
231 static int if_ipl_remove __P((void))
232 {
233 char *name;
234 struct nameidata nd;
235 int error, i;
236
237 for (i = 0; (name = ipf_devfiles[i]); i++) {
238 NDINIT(&nd, DELETE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
239 if ((error = namei(&nd)))
240 return (error);
241 VOP_LEASE(nd.ni_vp, curproc, curproc->p_ucred, LEASE_WRITE);
242 vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
243 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
244 (void) VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
245 if (nd.ni_dvp == nd.ni_vp)
246 vrele(nd.ni_dvp);
247 else
248 vput(nd.ni_dvp);
249 if (nd.ni_vp != NULLVP)
250 vput(nd.ni_vp);
251 }
252
253 return 0;
254 }
255
256
257 static int if_ipl_unload(lkmtp, cmd)
258 struct lkm_table *lkmtp;
259 int cmd;
260 {
261 int error = 0;
262
263 error = ipldetach();
264 if (!error)
265 error = if_ipl_remove();
266 return error;
267 }
268
269
270 static int if_ipl_load(lkmtp, cmd)
271 struct lkm_table *lkmtp;
272 int cmd;
273 {
274 struct nameidata nd;
275 struct vattr vattr;
276 int error = 0, fmode = S_IFCHR|0600, i;
277 char *name;
278
279 error = iplattach();
280 if (error)
281 return error;
282 (void) if_ipl_remove();
283
284 for (i = 0; (name = ipf_devfiles[i]); i++) {
285 NDINIT(&nd, CREATE, LOCKPARENT, UIO_SYSSPACE, name, curproc);
286 if ((error = namei(&nd)))
287 return error;
288 if (nd.ni_vp != NULL) {
289 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
290 if (nd.ni_dvp == nd.ni_vp)
291 vrele(nd.ni_dvp);
292 else
293 vput(nd.ni_dvp);
294 vrele(nd.ni_vp);
295 return (EEXIST);
296 }
297 VATTR_NULL(&vattr);
298 vattr.va_type = VCHR;
299 vattr.va_mode = (fmode & 07777);
300 vattr.va_rdev = (ipl_major << 8) | i;
301 VOP_LEASE(nd.ni_dvp, curproc, curproc->p_ucred, LEASE_WRITE);
302 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
303 vput(nd.ni_dvp);
304 if (error)
305 return error;
306 }
307 return 0;
308 }
309
310 #endif /* actually LKM */
311
312 #if defined(__FreeBSD_version) && (__FreeBSD_version < 220000)
313 /*
314 * strlen isn't present in 2.1.* kernels.
315 */
316 size_t strlen(string)
317 char *string;
318 {
319 register char *s;
320
321 for (s = string; *s; s++)
322 ;
323 return (size_t)(s - string);
324 }
325
326
327 int xxxinit(lkmtp, cmd, ver)
328 struct lkm_table *lkmtp;
329 int cmd, ver;
330 {
331 DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
332 }
333 #else
334 # ifdef IPFILTER_LKM
335 # include <sys/exec.h>
336
337 MOD_DECL(if_ipl);
338
339
340 static struct lkm_dev _module = {
341 LM_DEV,
342 LKM_VERSION,
343 IPL_VERSION,
344 CDEV_MAJOR,
345 LM_DT_CHAR,
346 { (void *)&ipl_cdevsw }
347 };
348
349
350 int if_ipl __P((struct lkm_table *, int, int));
351
352
353 int if_ipl(lkmtp, cmd, ver)
354 struct lkm_table *lkmtp;
355 int cmd, ver;
356 {
357 DISPATCH(lkmtp, cmd, ver, iplaction, iplaction, iplaction);
358 }
359 # endif
360 static ipl_devsw_installed = 0;
361
362 static void ipl_drvinit __P((void *unused))
363 {
364 dev_t dev;
365 # ifdef DEVFS
366 void **tp = ipf_devfs;
367 # endif
368
369 if (!ipl_devsw_installed ) {
370 dev = makedev(CDEV_MAJOR, 0);
371 cdevsw_add(&dev, &ipl_cdevsw, NULL);
372 ipl_devsw_installed = 1;
373
374 # ifdef DEVFS
375 tp[IPL_LOGIPF] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGIPF,
376 DV_CHR, 0, 0, 0600, "ipf");
377 tp[IPL_LOGNAT] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGNAT,
378 DV_CHR, 0, 0, 0600, "ipnat");
379 tp[IPL_LOGSTATE] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGSTATE,
380 DV_CHR, 0, 0, 0600,
381 "ipstate");
382 tp[IPL_LOGAUTH] = devfs_add_devswf(&ipl_cdevsw, IPL_LOGAUTH,
383 DV_CHR, 0, 0, 0600,
384 "ipauth");
385 # endif
386 }
387 }
388
389 SYSINIT(ipldev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ipl_drvinit,NULL);
390 #endif /* _FreeBSD_version */
Cache object: 5fdaf480ce0b2eb6420eb7ce4727a6c6
|