4 * Copyright (C) 2001-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 # ifndef __FreeBSD_cc_version
10 # include <osreldate.h>
12 # if __FreeBSD_cc_version < 430000
13 # include <osreldate.h>
19 #include <sys/ioctl.h>
20 #include "netinet/ipl.h"
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 $";
27 #if !defined(__SVR4) && defined(__GNUC__)
28 extern char *index __P((const char *, int));
33 extern frentry_t *frtop;
36 void ipf_frsync __P((void));
37 void zerostats __P((void));
38 int main __P((int, char *[]));
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 *));
56 static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
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>]");
79 while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) {
91 opts &= ~OPT_INACTIVE;
94 if (strcmp(optarg, "c") == 0)
107 procfile(argv[0], optarg);
113 opts ^= OPT_INACTIVE;
119 opts ^= OPT_DONOTHING;
124 ipfname = IPAUTH_NAME;
127 opts ^= OPT_NORESOLVE;
136 if (opendevice(ipfname, 1) >= 0)
137 ipf_dotuning(fd, optarg, ioctl);
150 opts ^= OPT_ZERORULEST;
169 static int opendevice(ipfdev, check)
173 if (opts & OPT_DONOTHING)
176 if (check && checkrev(ipfname) == -1) {
177 fprintf(stderr, "User/kernel version check failed\n");
185 if ((fd = open(ipfdev, O_RDWR)) == -1)
186 if ((fd = open(ipfdev, O_RDONLY)) == -1)
187 perror("open device");
192 static void closedevice()
199 static int get_flags()
203 if ((opendevice(ipfname, 1) != -2) &&
204 (ioctl(fd, SIOCGETFF, &i) == -1)) {
212 static void set_state(enable)
215 if (opendevice(ipfname, 0) != -2)
216 if (ioctl(fd, SIOCFRENB, &enable) == -1) {
219 "IP FIlter: already initialized\n");
227 static void procfile(name, file)
230 (void) opendevice(ipfname, 1);
234 ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
239 emit(-1, -1, NULL, NULL);
244 static void ipf_interceptadd(fd, ioctlfunc, ptr)
246 ioctlfunc_t ioctlfunc;
252 ipf_addrule(fd, ioctlfunc, ptr);
256 static void packetlogon(opt)
259 int flag, xfd, logopt, change = 0;
263 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
264 printf("log flag is currently %#x\n", flag);
267 flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
269 if (strstr(opt, "pass")) {
271 if (opts & OPT_VERBOSE)
272 printf("set log flag: pass\n");
275 if (strstr(opt, "nomatch")) {
276 flag |= FF_LOGNOMATCH;
277 if (opts & OPT_VERBOSE)
278 printf("set log flag: nomatch\n");
281 if (strstr(opt, "block") || index(opt, 'd')) {
283 if (opts & OPT_VERBOSE)
284 printf("set log flag: block\n");
287 if (strstr(opt, "none")) {
288 if (opts & OPT_VERBOSE)
289 printf("disable all log flags\n");
294 if (opendevice(ipfname, 1) != -2 &&
295 (ioctl(fd, SIOCSETFF, &flag) != 0))
296 perror("ioctl(SIOCSETFF)");
299 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
301 printf("log flags are now %#x\n", flag);
304 if (strstr(opt, "state")) {
305 if (opts & OPT_VERBOSE)
306 printf("set state log flag\n");
307 xfd = open(IPSTATE_NAME, O_RDWR);
310 if (ioctl(xfd, SIOCGETLG, &logopt))
311 perror("ioctl(SIOCGETLG)");
314 if (ioctl(xfd, SIOCSETLG, &logopt))
315 perror("ioctl(SIOCSETLG)");
321 if (strstr(opt, "nat")) {
322 if (opts & OPT_VERBOSE)
323 printf("set nat log flag\n");
324 xfd = open(IPNAT_NAME, O_RDWR);
327 if (ioctl(xfd, SIOCGETLG, &logopt))
328 perror("ioctl(SIOCGETLG)");
331 if (ioctl(xfd, SIOCSETLG, &logopt))
332 perror("ioctl(SIOCSETLG)");
340 static void flushfilter(arg)
347 if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) {
350 else if (*arg == 's')
357 if (opendevice(IPSTATE_NAME, 1) == -2)
360 if (!(opts & OPT_DONOTHING)) {
362 if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
363 perror("ioctl(SIOCIPFL6)");
367 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
368 perror("ioctl(SIOCIPFFL)");
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);
382 if (!strcmp(arg, "u")) {
385 * Flush auth rules and packets
387 if (opendevice(IPL_AUTH, 1) == -1)
388 perror("open(IPL_AUTH)");
390 if (ioctl(fd, SIOCIPFFA, &fl) == -1)
391 perror("ioctl(SIOCIPFFA)");
398 if (strchr(arg, 'i') || strchr(arg, 'I'))
400 if (strchr(arg, 'o') || strchr(arg, 'O'))
402 if (strchr(arg, 'a') || strchr(arg, 'A'))
403 fl = FR_OUTQUE|FR_INQUE;
404 if (opts & OPT_INACTIVE)
408 if (opendevice(ipfname, 1) == -2)
411 if (!(opts & OPT_DONOTHING)) {
413 if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
414 perror("ioctl(SIOCIPFL6)");
418 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
419 perror("ioctl(SIOCIPFFL)");
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);
434 static void swapactive()
438 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
439 perror("ioctl(SIOCSWAPA)");
441 printf("Set %d now inactive\n", in);
449 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
452 printf("filter sync'd\n");
461 obj.ipfo_rev = IPFILTER_VERSION;
462 obj.ipfo_type = IPFOBJ_IPFSTAT;
463 obj.ipfo_size = sizeof(fio);
467 if (opendevice(ipfname, 1) != -2) {
468 if (ioctl(fd, SIOCFRZST, &obj) == -1) {
469 perror("ioctl(SIOCFRZST)");
479 * read the kernel stats for packets blocked and passed
481 static void showstats(fp)
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,
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,
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);
504 static int showversion()
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;
518 printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
520 if ((vfd = open(ipfname, O_RDONLY)) == -1) {
521 perror("open device");
525 if (ioctl(vfd, SIOCGETFS, &ipfo)) {
526 perror("ioctl(SIOCGETFS)");
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);
538 if (flags & FF_LOGPASS) {
542 if (flags & FF_LOGBLOCK) {
543 printf("%sblock", s);
546 if (flags & FF_LOGNOMATCH) {
547 printf("%snomatch", s);
550 if (flags & FF_BLOCKNONIP) {
551 printf("%snonip", s);
559 if (FR_ISPASS(fio.f_defpass))
561 else if (FR_ISBLOCK(fio.f_defpass))
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);