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