]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/contrib/ipfilter/netinet/mlfk_ipl.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / sys / contrib / ipfilter / netinet / mlfk_ipl.c
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * $FreeBSD$
7  * See the IPFILTER.LICENCE file for details on licencing.
8  */
9
10
11 #include <sys/param.h>
12 #include <sys/systm.h>
13 #include <sys/kernel.h>
14 #include <sys/module.h>
15 #include <sys/conf.h>
16 #include <sys/socket.h>
17 #include <sys/sysctl.h>
18 #include <sys/select.h>
19 #if __FreeBSD_version >= 500000
20 # include <sys/selinfo.h>
21 #endif
22 #include <net/if.h>
23 #include <netinet/in_systm.h>
24 #include <netinet/in.h>
25
26
27 #include "netinet/ipl.h"
28 #include "netinet/ip_compat.h"
29 #include "netinet/ip_fil.h"
30 #include "netinet/ip_state.h"
31 #include "netinet/ip_nat.h"
32 #include "netinet/ip_auth.h"
33 #include "netinet/ip_frag.h"
34 #include "netinet/ip_sync.h"
35
36 extern ipf_main_softc_t ipfmain;
37
38 #if __FreeBSD_version >= 502116
39 static struct cdev *ipf_devs[IPL_LOGSIZE];
40 #else
41 static dev_t ipf_devs[IPL_LOGSIZE];
42 #endif
43
44 static int sysctl_ipf_int ( SYSCTL_HANDLER_ARGS );
45 static int ipf_modload(void);
46 static int ipf_modunload(void);
47
48 #if (__FreeBSD_version >= 500024)
49 # if (__FreeBSD_version >= 502116)
50 static  int     ipfopen __P((struct cdev*, int, int, struct thread *));
51 static  int     ipfclose __P((struct cdev*, int, int, struct thread *));
52 # else
53 static  int     ipfopen __P((dev_t, int, int, struct thread *));
54 static  int     ipfclose __P((dev_t, int, int, struct thread *));
55 # endif /* __FreeBSD_version >= 502116 */
56 #else
57 static  int     ipfopen __P((dev_t, int, int, struct proc *));
58 static  int     ipfclose __P((dev_t, int, int, struct proc *));
59 #endif
60 #if (__FreeBSD_version >= 502116)
61 static  int     ipfread __P((struct cdev*, struct uio *, int));
62 static  int     ipfwrite __P((struct cdev*, struct uio *, int));
63 #else
64 static  int     ipfread __P((dev_t, struct uio *, int));
65 static  int     ipfwrite __P((dev_t, struct uio *, int));
66 #endif /* __FreeBSD_version >= 502116 */
67
68
69 SYSCTL_DECL(_net_inet);
70 #define SYSCTL_IPF(parent, nbr, name, access, ptr, val, descr) \
71         SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|access, \
72                    ptr, val, sysctl_ipf_int, "I", descr);
73 #define CTLFLAG_OFF     0x00800000      /* IPFilter must be disabled */
74 #define CTLFLAG_RWO     (CTLFLAG_RW|CTLFLAG_OFF)
75 SYSCTL_NODE(_net_inet, OID_AUTO, ipf, CTLFLAG_RW, 0, "IPF");
76 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_flags, CTLFLAG_RW, &ipfmain.ipf_flags, 0, "");
77 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_pass, CTLFLAG_RW, &ipfmain.ipf_pass, 0, "");
78 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_active, CTLFLAG_RD, &ipfmain.ipf_active, 0, "");
79 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpidletimeout, CTLFLAG_RWO,
80            &ipfmain.ipf_tcpidletimeout, 0, "");
81 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcphalfclosed, CTLFLAG_RWO,
82            &ipfmain.ipf_tcphalfclosed, 0, "");
83 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosewait, CTLFLAG_RWO,
84            &ipfmain.ipf_tcpclosewait, 0, "");
85 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcplastack, CTLFLAG_RWO,
86            &ipfmain.ipf_tcplastack, 0, "");
87 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcptimeout, CTLFLAG_RWO,
88            &ipfmain.ipf_tcptimeout, 0, "");
89 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_tcpclosed, CTLFLAG_RWO,
90            &ipfmain.ipf_tcpclosed, 0, "");
91 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udptimeout, CTLFLAG_RWO,
92            &ipfmain.ipf_udptimeout, 0, "");
93 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_udpacktimeout, CTLFLAG_RWO,
94            &ipfmain.ipf_udpacktimeout, 0, "");
95 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_icmptimeout, CTLFLAG_RWO,
96            &ipfmain.ipf_icmptimeout, 0, "");
97 #if 0
98 /* this needs to be resolved at compile time */
99 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defnatage, CTLFLAG_RWO,
100            &((ipf_nat_softc_t *)ipfmain.ipf_nat_soft)->ipf_nat_defage, 0, "");
101 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_ipfrttl, CTLFLAG_RW,
102            &ipf_ipfrttl, 0, "");
103 #endif
104 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_running, CTLFLAG_RD,
105            &ipfmain.ipf_running, 0, "");
106 #if 0
107 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statesize, CTLFLAG_RWO,
108            &ipfmain.ipf_state_soft)->ipf_state_size, 0, "");
109 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_statemax, CTLFLAG_RWO,
110            &(ipfmain.ipf_state_soft)->ipf_state_max, 0, "");
111 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_nattable_sz, CTLFLAG_RWO,
112            &(ipfmain.ipf_nat_soft)->ipf_nat_table_sz, 0, "");
113 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_natrules_sz, CTLFLAG_RWO,
114            &(ipfmain.ipf_nat_soft)->ipf_nat_maprules_sz, 0, "");
115 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_rdrrules_sz, CTLFLAG_RWO,
116            &(ipfmain.ipf_nat_soft)->ipf_nat_rdrrules_sz, 0, "");
117 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, ipf_hostmap_sz, CTLFLAG_RWO,
118            &(ipfmain.ipf_nat_soft)->ipf_nat_hostmap_sz, 0, "");
119 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authsize, CTLFLAG_RWO,
120            &ipf_auth_size, 0, "");
121 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_authused, CTLFLAG_RD,
122            &ipf_auth_used, 0, "");
123 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_defaultauthage, CTLFLAG_RW,
124            &ipf_auth_defaultage, 0, "");
125 #endif
126 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &ipfmain.ipf_chksrc, 0, "");
127 SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &ipfmain.ipf_minttl, 0, "");
128
129 #define CDEV_MAJOR 79
130 #include <sys/poll.h>
131 #if __FreeBSD_version >= 500043
132 # include <sys/select.h>
133 static int ipfpoll(struct cdev *dev, int events, struct thread *td);
134
135 static struct cdevsw ipf_cdevsw = {
136 #if __FreeBSD_version >= 502103
137         .d_version =    D_VERSION,
138         .d_flags =      0,      /* D_NEEDGIANT - Should be SMP safe */
139 #endif
140         .d_open =       ipfopen,
141         .d_close =      ipfclose,
142         .d_read =       ipfread,
143         .d_write =      ipfwrite,
144         .d_ioctl =      ipfioctl,
145         .d_poll =       ipfpoll,
146         .d_name =       "ipf",
147 #if __FreeBSD_version < 600000
148         .d_maj =        CDEV_MAJOR,
149 #endif
150 };
151 #else
152 static int ipfpoll(dev_t dev, int events, struct proc *td);
153
154 static struct cdevsw ipf_cdevsw = {
155         /* open */      ipfopen,
156         /* close */     ipfclose,
157         /* read */      ipfread,
158         /* write */     ipfwrite,
159         /* ioctl */     ipfioctl,
160         /* poll */      ipfpoll,
161         /* mmap */      nommap,
162         /* strategy */  nostrategy,
163         /* name */      "ipf",
164         /* maj */       CDEV_MAJOR,
165         /* dump */      nodump,
166         /* psize */     nopsize,
167         /* flags */     0,
168 # if (__FreeBSD_version < 500043)
169         /* bmaj */      -1,
170 # endif
171 # if (__FreeBSD_version >= 430000)
172         /* kqfilter */  NULL
173 # endif
174 };
175 #endif
176
177 static char *ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME, IPAUTH_NAME,
178                                 IPSYNC_NAME, IPSCAN_NAME, IPLOOKUP_NAME, NULL };
179
180
181 static int
182 ipfilter_modevent(module_t mod, int type, void *unused)
183 {
184         int error = 0;
185
186         switch (type)
187         {
188         case MOD_LOAD :
189                 error = ipf_modload();
190                 break;
191
192         case MOD_UNLOAD :
193                 error = ipf_modunload();
194                 break;
195         default:
196                 error = EINVAL;
197                 break;
198         }
199         return error;
200 }
201
202
203 static int
204 ipf_modload()
205 {
206         char *defpass, *c, *str;
207         int i, j, error;
208
209         if (ipf_load_all() != 0)
210                 return EIO;
211
212         if (ipf_create_all(&ipfmain) == NULL)
213                 return EIO;
214
215         error = ipfattach(&ipfmain);
216         if (error)
217                 return error;
218
219         for (i = 0; i < IPL_LOGSIZE; i++)
220                 ipf_devs[i] = NULL;
221
222         for (i = 0; (str = ipf_devfiles[i]); i++) {
223                 c = NULL;
224                 for(j = strlen(str); j > 0; j--)
225                         if (str[j] == '/') {
226                                 c = str + j + 1;
227                                 break;
228                         }
229                 if (!c)
230                         c = str;
231                 ipf_devs[i] = make_dev(&ipf_cdevsw, i, 0, 0, 0600, "%s", c);
232         }
233
234         error = ipf_pfil_hook();
235         if (error != 0)
236                 return error;
237         ipf_event_reg();
238
239         if (FR_ISPASS(ipfmain.ipf_pass))
240                 defpass = "pass";
241         else if (FR_ISBLOCK(ipfmain.ipf_pass))
242                 defpass = "block";
243         else
244                 defpass = "no-match -> block";
245
246         printf("%s initialized.  Default = %s all, Logging = %s%s\n",
247                 ipfilter_version, defpass,
248 #ifdef IPFILTER_LOG
249                 "enabled",
250 #else
251                 "disabled",
252 #endif
253 #ifdef IPFILTER_COMPILED
254                 " (COMPILED)"
255 #else
256                 ""
257 #endif
258                 );
259         return 0;
260 }
261
262
263 static int
264 ipf_modunload()
265 {
266         int error, i;
267
268         if (ipfmain.ipf_refcnt)
269                 return EBUSY;
270
271         error = ipf_pfil_unhook();
272         if (error != 0)
273                 return error;
274
275         if (ipfmain.ipf_running >= 0) {
276                 error = ipfdetach(&ipfmain);
277                 if (error != 0)
278                         return error;
279
280                 ipf_destroy_all(&ipfmain);
281                 ipf_unload_all();
282         } else
283                 error = 0;
284
285         ipfmain.ipf_running = -2;
286
287         for (i = 0; ipf_devfiles[i]; i++) {
288                 if (ipf_devs[i] != NULL)
289                         destroy_dev(ipf_devs[i]);
290         }
291
292         printf("%s unloaded\n", ipfilter_version);
293
294         return error;
295 }
296
297
298 static moduledata_t ipfiltermod = {
299         "ipfilter",
300         ipfilter_modevent,
301         0
302 };
303
304
305 DECLARE_MODULE(ipfilter, ipfiltermod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);
306 #ifdef  MODULE_VERSION
307 MODULE_VERSION(ipfilter, 1);
308 #endif
309
310
311 #ifdef SYSCTL_IPF
312 int
313 sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
314 {
315         int error = 0;
316
317         if (arg1)
318                 error = SYSCTL_OUT(req, arg1, sizeof(int));
319         else
320                 error = SYSCTL_OUT(req, &arg2, sizeof(int));
321
322         if (error || !req->newptr)
323                 return (error);
324
325         if (!arg1)
326                 error = EPERM;
327         else {
328                 if ((oidp->oid_kind & CTLFLAG_OFF) && (ipfmain.ipf_running > 0))
329                         error = EBUSY;
330                 else
331                         error = SYSCTL_IN(req, arg1, sizeof(int));
332         }
333         return (error);
334 }
335 #endif
336
337
338 static int
339 #if __FreeBSD_version >= 500043
340 ipfpoll(struct cdev *dev, int events, struct thread *td)
341 #else
342 ipfpoll(dev_t dev, int events, struct proc *td)
343 #endif
344 {
345         int unit = GET_MINOR(dev);
346         int revents;
347
348         if (unit < 0 || unit > IPL_LOGMAX)
349                 return 0;
350
351         revents = 0;
352
353         switch (unit)
354         {
355         case IPL_LOGIPF :
356         case IPL_LOGNAT :
357         case IPL_LOGSTATE :
358 #ifdef IPFILTER_LOG
359                 if ((events & (POLLIN | POLLRDNORM)) && ipf_log_canread(&ipfmain, unit))
360                         revents |= events & (POLLIN | POLLRDNORM);
361 #endif
362                 break;
363         case IPL_LOGAUTH :
364                 if ((events & (POLLIN | POLLRDNORM)) && ipf_auth_waiting(&ipfmain))
365                         revents |= events & (POLLIN | POLLRDNORM);
366                 break;
367         case IPL_LOGSYNC :
368                 if ((events & (POLLIN | POLLRDNORM)) && ipf_sync_canread(&ipfmain))
369                         revents |= events & (POLLIN | POLLRDNORM);
370                 if ((events & (POLLOUT | POLLWRNORM)) && ipf_sync_canwrite(&ipfmain))
371                         revents |= events & (POLLOUT | POLLWRNORM);
372                 break;
373         case IPL_LOGSCAN :
374         case IPL_LOGLOOKUP :
375         default :
376                 break;
377         }
378
379         if ((revents == 0) && ((events & (POLLIN|POLLRDNORM)) != 0))
380                 selrecord(td, &ipfmain.ipf_selwait[unit]);
381
382         return revents;
383 }
384
385
386 /*
387  * routines below for saving IP headers to buffer
388  */
389 static int ipfopen(dev, flags
390 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
391 , devtype, p)
392         int devtype;
393 # if (__FreeBSD_version >= 500024)
394         struct thread *p;
395 # else
396         struct proc *p;
397 # endif /* __FreeBSD_version >= 500024 */
398 #else
399 )
400 #endif
401 #if (__FreeBSD_version >= 502116)
402         struct cdev *dev;
403 #else
404         dev_t dev;
405 #endif
406         int flags;
407 {
408         int unit = GET_MINOR(dev);
409         int error;
410
411         if (IPL_LOGMAX < unit)
412                 error = ENXIO;
413         else {
414                 switch (unit)
415                 {
416                 case IPL_LOGIPF :
417                 case IPL_LOGNAT :
418                 case IPL_LOGSTATE :
419                 case IPL_LOGAUTH :
420                 case IPL_LOGLOOKUP :
421                 case IPL_LOGSYNC :
422 #ifdef IPFILTER_SCAN
423                 case IPL_LOGSCAN :
424 #endif
425                         error = 0;
426                         break;
427                 default :
428                         error = ENXIO;
429                         break;
430                 }
431         }
432         return error;
433 }
434
435
436 static int ipfclose(dev, flags
437 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000))
438 , devtype, p)
439         int devtype;
440 # if (__FreeBSD_version >= 500024)
441         struct thread *p;
442 # else
443         struct proc *p;
444 # endif /* __FreeBSD_version >= 500024 */
445 #else
446 )
447 #endif
448 #if (__FreeBSD_version >= 502116)
449         struct cdev *dev;
450 #else
451         dev_t dev;
452 #endif
453         int flags;
454 {
455         int     unit = GET_MINOR(dev);
456
457         if (IPL_LOGMAX < unit)
458                 unit = ENXIO;
459         else
460                 unit = 0;
461         return unit;
462 }
463
464 /*
465  * ipfread/ipflog
466  * both of these must operate with at least splnet() lest they be
467  * called during packet processing and cause an inconsistancy to appear in
468  * the filter lists.
469  */
470 #if (BSD >= 199306)
471 static int ipfread(dev, uio, ioflag)
472         int ioflag;
473 #else
474 static int ipfread(dev, uio)
475 #endif
476 #if (__FreeBSD_version >= 502116)
477         struct cdev *dev;
478 #else
479         dev_t dev;
480 #endif
481         struct uio *uio;
482 {
483         int     unit = GET_MINOR(dev);
484
485         if (unit < 0)
486                 return ENXIO;
487
488         if (ipfmain.ipf_running < 1)
489                 return EIO;
490
491         if (unit == IPL_LOGSYNC)
492                 return ipf_sync_read(&ipfmain, uio);
493
494 #ifdef IPFILTER_LOG
495         return ipf_log_read(&ipfmain, unit, uio);
496 #else
497         return ENXIO;
498 #endif
499 }
500
501
502 /*
503  * ipfwrite
504  * both of these must operate with at least splnet() lest they be
505  * called during packet processing and cause an inconsistancy to appear in
506  * the filter lists.
507  */
508 #if (BSD >= 199306)
509 static int ipfwrite(dev, uio, ioflag)
510         int ioflag;
511 #else
512 static int ipfwrite(dev, uio)
513 #endif
514 #if (__FreeBSD_version >= 502116)
515         struct cdev *dev;
516 #else
517         dev_t dev;
518 #endif
519         struct uio *uio;
520 {
521
522         if (ipfmain.ipf_running < 1)
523                 return EIO;
524
525         if (GET_MINOR(dev) == IPL_LOGSYNC)
526                 return ipf_sync_write(&ipfmain, uio);
527         return ENXIO;
528 }