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