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