add UNLEASHED_OBJ to unleashed.mk
[unleashed/tickless.git] / usr / src / cmd / ipf / tools / ipf.c
blob6605fad51e849c28e8a2ec2a302a63428c50a299
1 /*
2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
9 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
12 #ifdef __FreeBSD__
13 # ifndef __FreeBSD_cc_version
14 # include <osreldate.h>
15 # else
16 # if __FreeBSD_cc_version < 430000
17 # include <osreldate.h>
18 # endif
19 # endif
20 #endif
21 #include "ipf.h"
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include "netinet/ipl.h"
25 #include "ipfzone.h"
27 static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
28 static const char rcsid[] = "@(#)$Id: ipf.c,v 1.35.2.3 2004/12/15 18:27:17 darrenr Exp $";
30 #if !defined(__SVR4) && defined(__GNUC__)
31 extern char *index __P((const char *, int));
32 #endif
34 extern char *optarg;
35 extern int optind;
36 extern frentry_t *frtop;
39 void ipf_frsync __P((void));
40 void zerostats __P((void));
41 int main __P((int, char *[]));
43 int opts = 0;
44 int outputc = 0;
45 int use_inet6 = 0;
47 static void procfile __P((char *, char *)), flushfilter __P((char *));
48 static void set_state __P((u_int)), showstats __P((friostat_t *));
49 static void packetlogon __P((char *)), swapactive __P((void));
50 static int opendevice __P((char *, int));
51 static void closedevice __P((void));
52 static char *ipfname = IPL_NAME;
53 static void usage __P((void));
54 static int showversion __P((void));
55 static int get_flags __P((void));
56 static void ipf_interceptadd __P((int, ioctlfunc_t, void *));
58 static int fd = -1;
59 static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
60 ioctl, ioctl, ioctl,
61 ioctl, ioctl };
64 static void usage()
66 fprintf(stderr, "usage: ipf [-6AdDEGInoPrRsvVyzZ] %s %s %s",
67 "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]",
68 "[-f filename] [-T <tuneopts>] [zonename]\n");
69 exit(1);
73 int main(argc,argv)
74 int argc;
75 char *argv[];
77 int c;
78 const char *optstr = "6Ac:dDEf:F:GIl:noPrRsT:vVyzZ";
80 if (argc < 2)
81 usage();
84 * We need to set the zone name before calling the functions
85 * in the switch statement below. Note that ipf.c differs from the other
86 * tools in the ipfilter suite: the zone name is specified as the
87 * last argument, while the other tools use the -z option. ipf
88 * already has a -z option, so the last argument is used instead.
90 getzonearg(argc, argv, optstr);
92 while ((c = getopt(argc, argv, optstr)) != -1) {
93 switch (c)
95 case '?' :
96 usage();
97 break;
98 #ifdef USE_INET6
99 case '6' :
100 use_inet6 = 1;
101 break;
102 #endif
103 case 'A' :
104 opts &= ~OPT_INACTIVE;
105 break;
106 case 'c' :
107 if (strcmp(optarg, "c") == 0)
108 outputc = 1;
109 break;
110 case 'E' :
111 set_state((u_int)1);
112 break;
113 case 'D' :
114 set_state((u_int)0);
115 break;
116 case 'd' :
117 opts ^= OPT_DEBUG;
118 break;
119 case 'f' :
120 procfile(argv[0], optarg);
121 break;
122 case 'F' :
123 flushfilter(optarg);
124 break;
125 case 'G' :
126 /* Already handled by getzonearg() above */
127 break;
128 case 'I' :
129 opts ^= OPT_INACTIVE;
130 break;
131 case 'l' :
132 packetlogon(optarg);
133 break;
134 case 'n' :
135 opts ^= OPT_DONOTHING;
136 break;
137 case 'o' :
138 break;
139 case 'P' :
140 ipfname = IPAUTH_NAME;
141 break;
142 case 'R' :
143 opts ^= OPT_NORESOLVE;
144 break;
145 case 'r' :
146 opts ^= OPT_REMOVE;
147 break;
148 case 's' :
149 swapactive();
150 break;
151 case 'T' :
152 if (opendevice(ipfname, 1) >= 0)
153 ipf_dotuning(fd, optarg, ioctl);
154 break;
155 case 'v' :
156 opts += OPT_VERBOSE;
157 break;
158 case 'V' :
159 if (showversion())
160 exit(1);
161 break;
162 case 'y' :
163 ipf_frsync();
164 break;
165 case 'z' :
166 opts ^= OPT_ZERORULEST;
167 break;
168 case 'Z' :
169 zerostats();
170 break;
174 if (optind < 2)
175 usage();
177 if (fd != -1)
178 (void) close(fd);
180 return(0);
181 /* NOTREACHED */
185 static int opendevice(ipfdev, check)
186 char *ipfdev;
187 int check;
189 if (opts & OPT_DONOTHING)
190 return -2;
192 if (check && checkrev(ipfname) == -1) {
193 fprintf(stderr, "User/kernel version check failed\n");
194 return -2;
197 if (!ipfdev)
198 ipfdev = ipfname;
200 if (fd == -1)
201 if ((fd = open(ipfdev, O_RDWR)) == -1)
202 if ((fd = open(ipfdev, O_RDONLY)) == -1)
203 perror("open device");
205 if (setzone(fd) != 0) {
206 close(fd);
207 return -2;
210 return fd;
214 static void closedevice()
216 close(fd);
217 fd = -1;
221 static int get_flags()
223 int i;
225 if ((opendevice(ipfname, 1) != -2) &&
226 (ioctl(fd, SIOCGETFF, &i) == -1)) {
227 perror("SIOCGETFF");
228 return 0;
230 return i;
234 static void set_state(enable)
235 u_int enable;
237 if (opendevice(ipfname, 0) != -2)
238 if (ioctl(fd, SIOCFRENB, &enable) == -1) {
239 if (errno == EBUSY)
240 fprintf(stderr,
241 "IP FIlter: already initialized\n");
242 else
243 perror("SIOCFRENB");
245 return;
249 static void procfile(name, file)
250 char *name, *file;
252 (void) opendevice(ipfname, 1);
254 initparse();
256 ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
258 if (outputc) {
259 printC(0);
260 printC(1);
261 emit(-1, -1, NULL, NULL);
266 static void ipf_interceptadd(fd, ioctlfunc, ptr)
267 int fd;
268 ioctlfunc_t ioctlfunc;
269 void *ptr;
271 if (outputc)
272 printc(ptr);
274 ipf_addrule(fd, ioctlfunc, ptr);
278 static void packetlogon(opt)
279 char *opt;
281 int flag, xfd, logopt, change = 0;
283 flag = get_flags();
284 if (flag != 0) {
285 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
286 printf("log flag is currently %#x\n", flag);
289 flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
291 if (strstr(opt, "pass")) {
292 flag |= FF_LOGPASS;
293 if (opts & OPT_VERBOSE)
294 printf("set log flag: pass\n");
295 change = 1;
297 if (strstr(opt, "nomatch")) {
298 flag |= FF_LOGNOMATCH;
299 if (opts & OPT_VERBOSE)
300 printf("set log flag: nomatch\n");
301 change = 1;
303 if (strstr(opt, "block") || index(opt, 'd')) {
304 flag |= FF_LOGBLOCK;
305 if (opts & OPT_VERBOSE)
306 printf("set log flag: block\n");
307 change = 1;
309 if (strstr(opt, "none")) {
310 if (opts & OPT_VERBOSE)
311 printf("disable all log flags\n");
312 change = 1;
315 if (change == 1) {
316 if (opendevice(ipfname, 1) != -2 &&
317 (ioctl(fd, SIOCSETFF, &flag) != 0))
318 perror("ioctl(SIOCSETFF)");
321 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
322 flag = get_flags();
323 printf("log flags are now %#x\n", flag);
326 if (strstr(opt, "state")) {
327 if (opts & OPT_VERBOSE)
328 printf("set state log flag\n");
329 xfd = open(IPSTATE_NAME, O_RDWR);
330 if (xfd >= 0 && setzone(xfd) != 0) {
331 close(xfd);
332 xfd = -1;
335 if (xfd >= 0) {
336 logopt = 0;
337 if (ioctl(xfd, SIOCGETLG, &logopt))
338 perror("ioctl(SIOCGETLG)");
339 else {
340 logopt = 1 - logopt;
341 if (ioctl(xfd, SIOCSETLG, &logopt))
342 perror("ioctl(SIOCSETLG)");
344 close(xfd);
348 if (strstr(opt, "nat")) {
349 if (opts & OPT_VERBOSE)
350 printf("set nat log flag\n");
351 xfd = open(IPNAT_NAME, O_RDWR);
352 if (xfd >= 0 && setzone(xfd) != 0) {
353 close(xfd);
354 xfd = -1;
357 if (xfd >= 0) {
358 logopt = 0;
359 if (ioctl(xfd, SIOCGETLG, &logopt))
360 perror("ioctl(SIOCGETLG)");
361 else {
362 logopt = 1 - logopt;
363 if (ioctl(xfd, SIOCSETLG, &logopt))
364 perror("ioctl(SIOCSETLG)");
366 close(xfd);
372 static void flushfilter(arg)
373 char *arg;
375 int fl = 0, rem;
377 if (!arg || !*arg)
378 return;
379 if (!strcmp(arg, "s") || !strcmp(arg, "S")) {
380 if (*arg == 'S')
381 fl = FLUSH_TABLE_ALL;
382 else
383 fl = FLUSH_TABLE_CLOSING;
384 rem = fl;
386 closedevice();
387 if (opendevice(IPSTATE_NAME, 1) == -2)
388 exit(1);
390 if (!(opts & OPT_DONOTHING)) {
391 if (use_inet6) {
392 if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
393 perror("ioctl(SIOCIPFL6)");
394 exit(1);
396 } else {
397 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
398 perror("ioctl(SIOCIPFFL)");
399 exit(1);
403 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
404 printf("remove flags %s (%d)\n", arg, rem);
405 printf("removed %d filter rules\n", fl);
407 closedevice();
408 return;
411 #ifdef SIOCIPFFA
412 if (!strcmp(arg, "u")) {
413 closedevice();
415 * Flush auth rules and packets
417 if (opendevice(IPL_AUTH, 1) == -1)
418 perror("open(IPL_AUTH)");
419 else {
420 if (ioctl(fd, SIOCIPFFA, &fl) == -1)
421 perror("ioctl(SIOCIPFFA)");
423 closedevice();
424 return;
426 #endif
428 if (strchr(arg, 'i') || strchr(arg, 'I'))
429 fl = FR_INQUE;
430 if (strchr(arg, 'o') || strchr(arg, 'O'))
431 fl = FR_OUTQUE;
432 if (strchr(arg, 'a') || strchr(arg, 'A'))
433 fl = FR_OUTQUE|FR_INQUE;
434 if (opts & OPT_INACTIVE)
435 fl |= FR_INACTIVE;
436 rem = fl;
438 if (opendevice(ipfname, 1) == -2)
439 exit(1);
441 if (!(opts & OPT_DONOTHING)) {
442 if (use_inet6) {
443 if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
444 perror("ioctl(SIOCIPFL6)");
445 exit(1);
447 } else {
448 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
449 perror("ioctl(SIOCIPFFL)");
450 exit(1);
455 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
456 printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
457 (rem & FR_OUTQUE) ? "O" : "", rem);
458 printf("removed %d filter rules\n", fl);
460 return;
464 static void swapactive()
466 int in = 2;
468 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
469 perror("ioctl(SIOCSWAPA)");
470 else
471 printf("Set %d now inactive\n", in);
475 void ipf_frsync()
477 int frsyn = 0;
479 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
480 perror("SIOCFRSYN");
481 else
482 printf("filter sync'd\n");
486 void zerostats()
488 friostat_t fio;
489 friostat_t *fiop = &fio;
491 if (opendevice(ipfname, 1) != -2) {
492 if (ioctl(fd, SIOCFRZST, &fiop) == -1) {
493 perror("ioctl(SIOCFRZST)");
494 exit(-1);
496 showstats(fiop);
503 * read the kernel stats for packets blocked and passed
505 static void showstats(fp)
506 friostat_t *fp;
508 printf("bad packets:\t\tin %lu\tout %lu\n",
509 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
510 printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
511 fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
512 fp->f_st[0].fr_nom);
513 printf(" counted %lu\n", fp->f_st[0].fr_acct);
514 printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
515 fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
516 fp->f_st[1].fr_nom);
517 printf(" counted %lu\n", fp->f_st[0].fr_acct);
518 printf(" input packets logged:\tblocked %lu passed %lu\n",
519 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
520 printf("output packets logged:\tblocked %lu passed %lu\n",
521 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
522 printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n",
523 fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip,
524 fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip);
528 static int showversion()
530 struct friostat fio;
531 ipfobj_t ipfo;
532 u_32_t flags;
533 char *s;
534 int vfd;
536 bzero((caddr_t)&ipfo, sizeof(ipfo));
537 ipfo.ipfo_rev = IPFILTER_VERSION;
538 ipfo.ipfo_size = sizeof(fio);
539 ipfo.ipfo_ptr = (void *)&fio;
540 ipfo.ipfo_type = IPFOBJ_IPFSTAT;
542 printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
544 if ((vfd = open(ipfname, O_RDONLY)) == -1) {
545 perror("open device");
546 return 1;
549 if (setzone(vfd) != 0) {
550 close(vfd);
551 return 1;
554 if (ioctl(vfd, SIOCGETFS, &ipfo)) {
555 perror("ioctl(SIOCGETFS)");
556 close(vfd);
557 return 1;
559 close(vfd);
560 flags = get_flags();
562 printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version),
563 (int)sizeof(fio.f_version), fio.f_version);
564 printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no");
565 printf("Log Flags: %#x = ", flags);
566 s = "";
567 if (flags & FF_LOGPASS) {
568 printf("pass");
569 s = ", ";
571 if (flags & FF_LOGBLOCK) {
572 printf("%sblock", s);
573 s = ", ";
575 if (flags & FF_LOGNOMATCH) {
576 printf("%snomatch", s);
577 s = ", ";
579 if (flags & FF_BLOCKNONIP) {
580 printf("%snonip", s);
581 s = ", ";
583 if (!*s)
584 printf("none set");
585 putchar('\n');
587 printf("Default: ");
588 if (FR_ISPASS(fio.f_defpass))
589 s = "pass";
590 else if (FR_ISBLOCK(fio.f_defpass))
591 s = "block";
592 else
593 s = "nomatch -> block";
594 printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un");
595 printf("Active list: %d\n", fio.f_active);
596 printf("Feature mask: %#x\n", fio.f_features);
598 return 0;