]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/ipfilter/netinet/mlfk_ipl.c
Import IPFilter 4.1.23 to vendor branch.
[FreeBSD/FreeBSD.git] / sys / contrib / ipfilter / netinet / mlfk_ipl.c
1 /*
2  * Copyright (C) 2000 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  */
6
7
8 #include <sys/param.h>
9 #include <sys/systm.h>
10 #include <sys/kernel.h>
11 #include <sys/module.h>
12 #include <sys/conf.h>
13 #include <sys/socket.h>
14 #include <sys/sysctl.h>
15 #include <sys/select.h>
16 #if __FreeBSD_version >= 500000
17 # include <sys/selinfo.h>
18 #endif                  
19 #include <net/if.h>
20 #include <netinet/in_systm.h>
21 #include <netinet/in.h>
22
23
24 #include <netinet/ipl.h>
25 #include <netinet/ip_compat.h>
26 #include <netinet/ip_fil.h>
27 #include <netinet/ip_state.h>
28 #include <netinet/ip_nat.h>
29 #include <netinet/ip_auth.h>
30 #include <netinet/ip_frag.h>
31 #include <netinet/ip_sync.h>
32
33 #if __FreeBSD_version >= 502116
34 static struct cdev *ipf_devs[IPL_LOGSIZE];
35 #else
36 static dev_t ipf_devs[IPL_LOGSIZE];
37 #endif
38
39 static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
40 static int ipf_modload(void);
41 static int ipf_modunload(void);
42
43 SYSCTL_DECL(_net_inet);
44 #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
45         SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
46                    ptr, val, sysctl_ipf_int, "I", descr);
47 #define CTLFLAG_OFF     0x00800000      /* IPFilter must be disabled */
48 #define CTLFLAG_RWO     (CTLFLAG_RW|CTLFLAG_OFF)
49 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
50 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &fr_flags, 0, "");
51 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_pass, CTLFLAG_RW, &fr_pass, 0, "");
52 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &fr_active, 0, "");
53 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
54            &fr_tcpidletimeout, 0, "");
55 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
56            &fr_tcphalfclosed, 0, "");
57 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
58            &fr_tcpclosewait, 0, "");
59 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
60            &fr_tcplastack, 0, "");
61 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
62            &fr_tcptimeout, 0, "");
63 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
64            &fr_tcpclosed, 0, "");
65 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
66            &fr_udptimeout, 0, "");
67 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
68            &fr_udpacktimeout, 0, "");
69 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
70            &fr_icmptimeout, 0, "");
71 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
72            &fr_defnatage, 0, "");
73 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
74            &fr_ipfrttl, 0, "");
75 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_running, CTLFLAG_RD,
76            &fr_running, 0, "");
77 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
78            &fr_statesize, 0, "");
79 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
80            &fr_statemax, 0, "");
81 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO,
82            &ipf_nattable_sz, 0, "");
83 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO,
84            &ipf_natrules_sz, 0, "");
85 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO,
86            &ipf_rdrrules_sz, 0, "");
87 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO,
88            &ipf_hostmap_sz, 0, "");
89 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
90            &fr_authsize, 0, "");
91 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
92            &fr_authused, 0, "");
93 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
94            &fr_defaultauthage, 0, "");
95 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &fr_chksrc, 0, "");
96 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &fr_minttl, 0, "");
97
98 #define CDEV_MAJOR 79
99 #include <sys/poll.h>
100 #if __FreeBSD_version >= 500043
101 # include <sys/select.h>
102 static int iplpoll(struct cdev *dev, int events, struct thread *td);
103
104 static struct cdevsw ipl_cdevsw = {
105 # if __FreeBSD_version >= 502103
106         .d_version =    D_VERSION,
107         .d_flags =      0,      /* D_NEEDGIANT - Should be SMP safe */
108 # endif
109         .d_open =       iplopen,
110         .d_close =      iplclose,
111         .d_read =       iplread,
112         .d_write =      iplwrite,
113         .d_ioctl =      iplioctl,
114         .d_name =       "ipl",
115 # if __FreeBSD_version >= 500043
116         .d_poll =       iplpoll,
117 # endif
118 # if __FreeBSD_version < 600000
119         .d_maj =        CDEV_MAJOR,
120 # endif
121 };
122 #else
123 static int iplpoll(dev_t dev, int events, struct proc *p);
124
125 static struct cdevsw ipl_cdevsw = {
126         /* open */      iplopen,
127         /* close */     iplclose,
128         /* read */      iplread,
129         /* write */     iplwrite,
130         /* ioctl */     iplioctl,
131         /* poll */      iplpoll,
132         /* mmap */      nommap,
133         /* strategy */  nostrategy,
134         /* name */      "ipl",
135         /* maj */       CDEV_MAJOR,
136         /* dump */      nodump,
137         /* psize */     nopsize,
138         /* flags */     0,
139 # if (__FreeBSD_version < 500043)
140         /* bmaj */      -1,
141 # endif
142 # if (__FreeBSD_version > 430000)
143         /* kqfilter */  NULL
144 # endif
145 };
146 #endif
147
148 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
149                                 IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
150
151
152 static int
153 ipfilter_modevent(module_t mod, int type, void *unused)
154 {
155         int error = 0;
156
157         switch (type)
158         {
159         case MOD_LOAD :
160                 error = ipf_modload();
161                 break;
162
163         case MOD_UNLOAD :
164                 error = ipf_modunload();
165                 break;
166         default:
167                 error = EINVAL;
168                 break;
169         }
170         return error;
171 }
172
173
174 static int
175 ipf_modload()
176 {
177         char *defpass, *c, *str;
178         int i, j, error;
179
180         RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
181         RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
182         RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock");
183
184         error = ipfattach();
185         if (error) {
186                 RW_DESTROY(&ipf_global);
187                 RW_DESTROY(&ipf_mutex);
188                 RW_DESTROY(&ipf_frcache);
189                 return error;
190         }
191
192         for (i = 0; i < IPL_LOGSIZE; i++)
193                 ipf_devs[i] = NULL;
194
195         for (i = 0; (str = ipf_devfiles[i]); i++) {
196                 c = NULL;
197                 for(j = strlen(str); j > 0; j--)
198                         if (str[j] == '/') {
199                                 c = str + j + 1;
200                                 break;
201                         }
202                 if (!c)
203                         c = str;
204                 ipf_devs[i] = make_dev(&ipl_cdevsw, i, 0, 0, 0600, c);
205         }
206
207         if (FR_ISPASS(fr_pass))
208                 defpass = "pass";
209         else if (FR_ISBLOCK(fr_pass))
210                 defpass = "block";
211         else          
212                 defpass = "no-match -> block";
213
214         printf("%s initialized.  Default = %s all, Logging = %s%s\n",
215                 ipfilter_version, defpass,                
216 #ifdef IPFILTER_LOG
217                 "enabled",
218 #else
219                 "disabled",
220 #endif
221 #ifdef IPFILTER_COMPILED
222                 " (COMPILED)"
223 #else
224                 ""
225 #endif
226                 );         
227         return 0;
228 }
229
230
231 static int
232 ipf_modunload()
233 {
234         int error, i;
235
236         if (fr_refcnt)
237                 return EBUSY;
238
239         if (fr_running >= 0) {
240                 error = ipfdetach();
241                 if (error != 0)
242                         return error;
243         } else
244                 error = 0;
245
246         RW_DESTROY(&ipf_global);
247         RW_DESTROY(&ipf_mutex);
248         RW_DESTROY(&ipf_frcache);
249
250         fr_running = -2;
251
252         for (i = 0; ipf_devfiles[i]; i++) {
253                 if (ipf_devs[i] != NULL)
254                         destroy_dev(ipf_devs[i]);
255         }
256
257         printf("%s unloaded\n", ipfilter_version);
258
259         return error;
260 }
261
262
263 static moduledata_t ipfiltermod = {
264         "ipfilter",
265         ipfilter_modevent,
266         0
267 };
268
269
270 DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
271 #ifdef  MODULE_VERSION
272 MODULE_VERSION(ipfilter, 1);
273 #endif
274
275
276 #ifdef SYSCTL_IPF
277 int
278 sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
279 {
280         int error = 0;
281
282         if (arg1)
283                 error = SYSCTL_OUT(req, arg1, sizeof(int));
284         else
285                 error = SYSCTL_OUT(req, &arg2, sizeof(int));
286
287         if (error || !req->newptr)
288                 return (error);
289
290         if (!arg1)
291                 error = EPERM;
292         else {
293                 if ((oidp->oid_kind & CTLFLAG_OFF) && (fr_running > 0))
294                         error = EBUSY;
295                 else
296                         error = SYSCTL_IN(req, arg1, sizeof(int));
297         }
298         return (error);
299 }
300 #endif
301
302
303 static int
304 #if __FreeBSD_version >= 500043
305 iplpoll(struct cdev *dev, int events, struct thread *td)
306 #else
307 iplpoll(dev_t dev, int events, struct proc *td)
308 #endif
309 {
310         u_int xmin = GET_MINOR(dev);
311         int revents;
312
313         if (xmin < 0 || xmin > IPL_LOGMAX)
314                 return 0;
315
316         revents = 0;
317
318         switch (xmin) 
319         {
320         case IPL_LOGIPF :
321         case IPL_LOGNAT :
322         case IPL_LOGSTATE :
323 #ifdef IPFILTER_LOG
324                 if ((events & (POLLIN | POLLRDNORM)) && ipflog_canread(xmin))
325                         revents |= events & (POLLIN | POLLRDNORM);
326 #endif  
327                 break;
328         case IPL_LOGAUTH :
329                 if ((events & (POLLIN | POLLRDNORM)) && fr_auth_waiting())
330                         revents |= events & (POLLIN | POLLRDNORM);
331                 break; 
332         case IPL_LOGSYNC :
333 #ifdef IPFILTER_SYNC
334                 if ((events & (POLLIN | POLLRDNORM)) && ipfsync_canread())
335                         revents |= events & (POLLIN | POLLRDNORM);
336                 if ((events & (POLLOUT | POLLWRNORM)) && ipfsync_canwrite())
337                         revents |= events & (POLLOUT | POLLWRNORM);
338 #endif
339                 break;
340         case IPL_LOGSCAN :
341         case IPL_LOGLOOKUP :
342         default :
343                 break;
344         }
345
346         if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
347                 selrecord(td, &ipfselwait[xmin]);
348
349         return revents;
350 }