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