]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ipfilter/tools/ipf.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ipfilter / tools / ipf.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 #ifdef  __FreeBSD__
9 # ifndef __FreeBSD_cc_version
10 #  include <osreldate.h>
11 # else
12 #  if __FreeBSD_cc_version < 430000
13 #   include <osreldate.h>
14 #  endif
15 # endif
16 #endif
17 #include "ipf.h"
18 #include <fcntl.h>
19 #include <ctype.h>
20 #include <sys/ioctl.h>
21 #include "netinet/ipl.h"
22
23 #if !defined(lint)
24 static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
25 static const char rcsid[] = "@(#)$Id$";
26 #endif
27
28 #if !defined(__SVR4) && defined(__GNUC__)
29 extern  char    *index __P((const char *, int));
30 #endif
31
32 extern  char    *optarg;
33 extern  int     optind;
34 extern  frentry_t *frtop;
35
36
37 void    ipf_frsync __P((void));
38 void    zerostats __P((void));
39 int     main __P((int, char *[]));
40
41 int     opts = 0;
42 int     outputc = 0;
43 int     use_inet6 = 0;
44 int     exitstatus = 0;
45
46 static  void    procfile __P((char *));
47 static  void    flushfilter __P((char *, int *));
48 static  void    set_state __P((u_int));
49 static  void    showstats __P((friostat_t *));
50 static  void    packetlogon __P((char *));
51 static  void    swapactive __P((void));
52 static  int     opendevice __P((char *, int));
53 static  void    closedevice __P((void));
54 static  char    *ipfname = IPL_NAME;
55 static  void    usage __P((void));
56 static  int     showversion __P((void));
57 static  int     get_flags __P((void));
58 static  int     ipf_interceptadd __P((int, ioctlfunc_t, void *));
59
60 static  int     fd = -1;
61 static  ioctlfunc_t     iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
62                                                       ioctl, ioctl, ioctl,
63                                                       ioctl, ioctl };
64
65 /* XXX  The following was added to satisfy a rescue/rescue/ build
66    XXX  requirement.  */
67 int     nohdrfields;
68
69 static void usage()
70 {
71         fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n",
72                 "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
73                 "[-f filename] [-T <tuneopts>]");
74         exit(1);
75 }
76
77
78 int main(argc,argv)
79         int argc;
80         char *argv[];
81 {
82         int c, *filter = NULL;
83
84         if (argc < 2)
85                 usage();
86
87         assigndefined(getenv("IPF_PREDEFINED"));
88
89         while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ")) != -1) {
90                 switch (c)
91                 {
92                 case '?' :
93                         usage();
94                         break;
95                 case '4' :
96                         use_inet6 = -1;
97                         break;
98                 case '6' :
99                         use_inet6 = 1;
100                         break;
101                 case 'A' :
102                         opts &= ~OPT_INACTIVE;
103                         break;
104                 case 'c' :
105                         if (strcmp(optarg, "c") == 0)
106                                 outputc = 1;
107                         break;
108                 case 'E' :
109                         set_state((u_int)1);
110                         break;
111                 case 'D' :
112                         set_state((u_int)0);
113                         break;
114                 case 'd' :
115                         opts ^= OPT_DEBUG;
116                         break;
117                 case 'f' :
118                         procfile(optarg);
119                         break;
120                 case 'F' :
121                         flushfilter(optarg, filter);
122                         break;
123                 case 'I' :
124                         opts ^= OPT_INACTIVE;
125                         break;
126                 case 'l' :
127                         packetlogon(optarg);
128                         break;
129                 case 'm' :
130                         filter = parseipfexpr(optarg, NULL);
131                         break;
132                 case 'n' :
133                         opts ^= OPT_DONOTHING|OPT_DONTOPEN;
134                         break;
135                 case 'o' :
136                         break;
137                 case 'P' :
138                         ipfname = IPAUTH_NAME;
139                         break;
140                 case 'R' :
141                         opts ^= OPT_NORESOLVE;
142                         break;
143                 case 'r' :
144                         opts ^= OPT_REMOVE;
145                         break;
146                 case 's' :
147                         swapactive();
148                         break;
149                 case 'T' :
150                         if (opendevice(ipfname, 1) >= 0)
151                                 ipf_dotuning(fd, optarg, ioctl);
152                         break;
153                 case 'v' :
154                         opts += OPT_VERBOSE;
155                         break;
156                 case 'V' :
157                         if (showversion())
158                                 exit(1);
159                         break;
160                 case 'y' :
161                         ipf_frsync();
162                         break;
163                 case 'z' :
164                         opts ^= OPT_ZERORULEST;
165                         break;
166                 case 'Z' :
167                         zerostats();
168                         break;
169                 }
170         }
171
172         if (optind < 2)
173                 usage();
174
175         if (fd != -1)
176                 (void) close(fd);
177
178         return(exitstatus);
179         /* NOTREACHED */
180 }
181
182
183 static int opendevice(ipfdev, check)
184         char *ipfdev;
185         int check;
186 {
187         if (opts & OPT_DONOTHING)
188                 return -2;
189
190         if (check && checkrev(ipfname) == -1) {
191                 fprintf(stderr, "User/kernel version check failed\n");
192                 return -2;
193         }
194
195         if (!ipfdev)
196                 ipfdev = ipfname;
197
198         if (fd == -1)
199                 if ((fd = open(ipfdev, O_RDWR)) == -1)
200                         if ((fd = open(ipfdev, O_RDONLY)) == -1)
201                                 ipferror(fd, "open device");
202         return fd;
203 }
204
205
206 static void closedevice()
207 {
208         close(fd);
209         fd = -1;
210 }
211
212
213 static  int     get_flags()
214 {
215         int i = 0;
216
217         if ((opendevice(ipfname, 1) != -2) &&
218             (ioctl(fd, SIOCGETFF, &i) == -1)) {
219                 ipferror(fd, "SIOCGETFF");
220                 return 0;
221         }
222         return i;
223 }
224
225
226 static  void    set_state(enable)
227         u_int   enable;
228 {
229         if (opendevice(ipfname, 0) != -2) {
230                 if (ioctl(fd, SIOCFRENB, &enable) == -1) {
231                         if (errno == EBUSY) {
232                                 fprintf(stderr,
233                                         "IP FIlter: already initialized\n");
234                         } else {
235                                 ipferror(fd, "SIOCFRENB");
236                         }
237                 }
238         }
239         return;
240 }
241
242
243 static  void    procfile(file)
244         char    *file;
245 {
246         (void) opendevice(ipfname, 1);
247
248         initparse();
249
250         ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
251
252         if (outputc) {
253                 printC(0);
254                 printC(1);
255                 emit(-1, -1, NULL, NULL);
256         }
257 }
258
259
260 static int ipf_interceptadd(fd, ioctlfunc, ptr)
261         int fd;
262         ioctlfunc_t ioctlfunc;
263         void *ptr;
264 {
265         if (outputc)
266                 printc(ptr);
267
268         if (ipf_addrule(fd, ioctlfunc, ptr) != 0)
269                 exitstatus = 1;
270         return 0;
271 }
272
273
274 static void packetlogon(opt)
275         char    *opt;
276 {
277         int     flag, xfd, logopt, change = 0;
278
279         flag = get_flags();
280         if (flag != 0) {
281                 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
282                         printf("log flag is currently %#x\n", flag);
283         }
284
285         flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
286
287         if (strstr(opt, "pass")) {
288                 flag |= FF_LOGPASS;
289                 if (opts & OPT_VERBOSE)
290                         printf("set log flag: pass\n");
291                 change = 1;
292         }
293         if (strstr(opt, "nomatch")) {
294                 flag |= FF_LOGNOMATCH;
295                 if (opts & OPT_VERBOSE)
296                         printf("set log flag: nomatch\n");
297                 change = 1;
298         }
299         if (strstr(opt, "block") || strchr(opt, 'd')) {
300                 flag |= FF_LOGBLOCK;
301                 if (opts & OPT_VERBOSE)
302                         printf("set log flag: block\n");
303                 change = 1;
304         }
305         if (strstr(opt, "none")) {
306                 if (opts & OPT_VERBOSE)
307                         printf("disable all log flags\n");
308                 change = 1;
309         }
310
311         if (change == 1) {
312                 if (opendevice(ipfname, 1) != -2 &&
313                     (ioctl(fd, SIOCSETFF, &flag) != 0))
314                         ipferror(fd, "ioctl(SIOCSETFF)");
315         }
316
317         if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
318                 flag = get_flags();
319                 printf("log flags are now %#x\n", flag);
320         }
321
322         if (strstr(opt, "state")) {
323                 if (opts & OPT_VERBOSE)
324                         printf("set state log flag\n");
325                 xfd = open(IPSTATE_NAME, O_RDWR);
326                 if (xfd >= 0) {
327                         logopt = 0;
328                         if (ioctl(xfd, SIOCGETLG, &logopt))
329                                 ipferror(fd, "ioctl(SIOCGETLG)");
330                         else {
331                                 logopt = 1 - logopt;
332                                 if (ioctl(xfd, SIOCSETLG, &logopt))
333                                         ipferror(xfd, "ioctl(SIOCSETLG)");
334                         }
335                         close(xfd);
336                 }
337         }
338
339         if (strstr(opt, "nat")) {
340                 if (opts & OPT_VERBOSE)
341                         printf("set nat log flag\n");
342                 xfd = open(IPNAT_NAME, O_RDWR);
343                 if (xfd >= 0) {
344                         logopt = 0;
345                         if (ioctl(xfd, SIOCGETLG, &logopt))
346                                 ipferror(xfd, "ioctl(SIOCGETLG)");
347                         else {
348                                 logopt = 1 - logopt;
349                                 if (ioctl(xfd, SIOCSETLG, &logopt))
350                                         ipferror(xfd, "ioctl(SIOCSETLG)");
351                         }
352                         close(xfd);
353                 }
354         }
355 }
356
357
358 static void flushfilter(arg, filter)
359         char *arg;
360         int *filter;
361 {
362         int     fl = 0, rem;
363
364         if (!arg || !*arg)
365                 return;
366         if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) {
367                 if (*arg == 'S')
368                         fl = 0;
369                 else if (*arg == 's')
370                         fl = 1;
371                 else
372                         fl = atoi(arg);
373                 rem = fl;
374
375                 closedevice();
376                 if (opendevice(IPSTATE_NAME, 1) == -2)
377                         exit(1);
378
379                 if (!(opts & OPT_DONOTHING)) {
380                         if (use_inet6) {
381                                 fprintf(stderr,
382                                         "IPv6 rules are no longer seperate\n");
383                         } else if (filter != NULL) {
384                                 ipfobj_t obj;
385
386                                 obj.ipfo_rev = IPFILTER_VERSION;
387                                 obj.ipfo_size = filter[0] * sizeof(int);
388                                 obj.ipfo_type = IPFOBJ_IPFEXPR;
389                                 obj.ipfo_ptr = filter;
390                                 if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) {
391                                         ipferror(fd, "ioctl(SIOCMATCHFLUSH)");
392                                         fl = -1;
393                                 } else {
394                                         fl = obj.ipfo_retval;
395                                 }
396                         } else {
397                                 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
398                                         ipferror(fd, "ioctl(SIOCIPFFL)");
399                                         exit(1);
400                                 }
401                         }
402                 }
403                 if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
404                         printf("remove flags %s (%d)\n", arg, rem);
405                 }
406                 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
407                         printf("%d state entries removed\n", fl);
408                 }
409                 closedevice();
410                 return;
411         }
412
413 #ifdef  SIOCIPFFA
414         if (!strcmp(arg, "u")) {
415                 closedevice();
416                 /*
417                  * Flush auth rules and packets
418                  */
419                 if (opendevice(IPL_AUTH, 1) == -1)
420                         perror("open(IPL_AUTH)");
421                 else {
422                         if (ioctl(fd, SIOCIPFFA, &fl) == -1)
423                                 ipferror(fd, "ioctl(SIOCIPFFA)");
424                 }
425                 closedevice();
426                 return;
427         }
428 #endif
429
430         if (strchr(arg, 'i') || strchr(arg, 'I'))
431                 fl = FR_INQUE;
432         if (strchr(arg, 'o') || strchr(arg, 'O'))
433                 fl = FR_OUTQUE;
434         if (strchr(arg, 'a') || strchr(arg, 'A'))
435                 fl = FR_OUTQUE|FR_INQUE;
436         if (opts & OPT_INACTIVE)
437                 fl |= FR_INACTIVE;
438         rem = fl;
439
440         if (opendevice(ipfname, 1) == -2)
441                 exit(1);
442
443         if (!(opts & OPT_DONOTHING)) {
444                 if (use_inet6) {
445                         if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
446                                 ipferror(fd, "ioctl(SIOCIPFL6)");
447                                 exit(1);
448                         }
449                 } else {
450                         if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
451                                 ipferror(fd, "ioctl(SIOCIPFFL)");
452                                 exit(1);
453                         }
454                 }
455         }
456
457         if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
458                 printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
459                         (rem & FR_OUTQUE) ? "O" : "", rem);
460         }
461         if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
462                 printf("%d filter rules removed\n", fl);
463         }
464         return;
465 }
466
467
468 static void swapactive()
469 {
470         int in = 2;
471
472         if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
473                 ipferror(fd, "ioctl(SIOCSWAPA)");
474         else
475                 printf("Set %d now inactive\n", in);
476 }
477
478
479 void ipf_frsync()
480 {
481         int frsyn = 0;
482
483         if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
484                 ipferror(fd, "SIOCFRSYN");
485         else
486                 printf("filter sync'd\n");
487 }
488
489
490 void zerostats()
491 {
492         ipfobj_t        obj;
493         friostat_t      fio;
494
495         obj.ipfo_rev = IPFILTER_VERSION;
496         obj.ipfo_type = IPFOBJ_IPFSTAT;
497         obj.ipfo_size = sizeof(fio);
498         obj.ipfo_ptr = &fio;
499         obj.ipfo_offset = 0;
500
501         if (opendevice(ipfname, 1) != -2) {
502                 if (ioctl(fd, SIOCFRZST, &obj) == -1) {
503                         ipferror(fd, "ioctl(SIOCFRZST)");
504                         exit(-1);
505                 }
506                 showstats(&fio);
507         }
508
509 }
510
511
512 /*
513  * read the kernel stats for packets blocked and passed
514  */
515 static void showstats(fp)
516         friostat_t      *fp;
517 {
518         printf("bad packets:\t\tin %lu\tout %lu\n",
519                         fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
520         printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
521                         fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
522                         fp->f_st[0].fr_nom);
523         printf(" counted %lu\n", fp->f_st[0].fr_acct);
524         printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
525                         fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
526                         fp->f_st[1].fr_nom);
527         printf(" counted %lu\n", fp->f_st[0].fr_acct);
528         printf(" input packets logged:\tblocked %lu passed %lu\n",
529                         fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
530         printf("output packets logged:\tblocked %lu passed %lu\n",
531                         fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
532 }
533
534
535 static int showversion()
536 {
537         struct friostat fio;
538         ipfobj_t ipfo;
539         u_32_t flags;
540         char *s;
541         int vfd;
542
543         bzero((caddr_t)&ipfo, sizeof(ipfo));
544         ipfo.ipfo_rev = IPFILTER_VERSION;
545         ipfo.ipfo_size = sizeof(fio);
546         ipfo.ipfo_ptr = (void *)&fio;
547         ipfo.ipfo_type = IPFOBJ_IPFSTAT;
548
549         printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
550
551         if ((vfd = open(ipfname, O_RDONLY)) == -1) {
552                 perror("open device");
553                 return 1;
554         }
555
556         if (ioctl(vfd, SIOCGETFS, &ipfo)) {
557                 ipferror(vfd, "ioctl(SIOCGETFS)");
558                 close(vfd);
559                 return 1;
560         }
561         close(vfd);
562         flags = get_flags();
563
564         printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version),
565                 (int)sizeof(fio.f_version), fio.f_version);
566         printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no");
567         printf("Log Flags: %#x = ", flags);
568         s = "";
569         if (flags & FF_LOGPASS) {
570                 printf("pass");
571                 s = ", ";
572         }
573         if (flags & FF_LOGBLOCK) {
574                 printf("%sblock", s);
575                 s = ", ";
576         }
577         if (flags & FF_LOGNOMATCH) {
578                 printf("%snomatch", s);
579                 s = ", ";
580         }
581         if (flags & FF_BLOCKNONIP) {
582                 printf("%snonip", s);
583                 s = ", ";
584         }
585         if (!*s)
586                 printf("none set");
587         putchar('\n');
588
589         printf("Default: ");
590         if (FR_ISPASS(fio.f_defpass))
591                 s = "pass";
592         else if (FR_ISBLOCK(fio.f_defpass))
593                 s = "block";
594         else
595                 s = "nomatch -> block";
596         printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un");
597         printf("Active list: %d\n", fio.f_active);
598         printf("Feature mask: %#x\n", fio.f_features);
599
600         return 0;
601 }