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