4 * Copyright (C) 2012 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>
20 #include <sys/ioctl.h>
21 #include "netinet/ipl.h"
24 static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
25 static const char rcsid[] = "@(#)$Id$";
28 #if !defined(__SVR4) && defined(__GNUC__)
29 extern char *index __P((const char *, int));
34 extern frentry_t *frtop;
37 void ipf_frsync __P((void));
38 void zerostats __P((void));
39 int main __P((int, char *[]));
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 *));
61 static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
65 /* XXX The following was added to satisfy a rescue/rescue/ build
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>]");
82 int c, *filter = NULL;
87 assigndefined(getenv("IPF_PREDEFINED"));
89 while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ")) != -1) {
102 opts &= ~OPT_INACTIVE;
105 if (strcmp(optarg, "c") == 0)
121 flushfilter(optarg, filter);
124 opts ^= OPT_INACTIVE;
130 filter = parseipfexpr(optarg, NULL);
133 opts ^= OPT_DONOTHING|OPT_DONTOPEN;
138 ipfname = IPAUTH_NAME;
141 opts ^= OPT_NORESOLVE;
150 if (opendevice(ipfname, 1) >= 0)
151 ipf_dotuning(fd, optarg, ioctl);
164 opts ^= OPT_ZERORULEST;
183 static int opendevice(ipfdev, check)
187 if (opts & OPT_DONOTHING)
190 if (check && checkrev(ipfname) == -1) {
191 fprintf(stderr, "User/kernel version check failed\n");
199 if ((fd = open(ipfdev, O_RDWR)) == -1)
200 if ((fd = open(ipfdev, O_RDONLY)) == -1)
201 ipferror(fd, "open device");
206 static void closedevice()
213 static int get_flags()
217 if ((opendevice(ipfname, 1) != -2) &&
218 (ioctl(fd, SIOCGETFF, &i) == -1)) {
219 ipferror(fd, "SIOCGETFF");
226 static void set_state(enable)
229 if (opendevice(ipfname, 0) != -2) {
230 if (ioctl(fd, SIOCFRENB, &enable) == -1) {
231 if (errno == EBUSY) {
233 "IP FIlter: already initialized\n");
235 ipferror(fd, "SIOCFRENB");
243 static void procfile(file)
246 (void) opendevice(ipfname, 1);
250 ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
255 emit(-1, -1, NULL, NULL);
260 static int ipf_interceptadd(fd, ioctlfunc, ptr)
262 ioctlfunc_t ioctlfunc;
268 if (ipf_addrule(fd, ioctlfunc, ptr) != 0)
274 static void packetlogon(opt)
277 int flag, xfd, logopt, change = 0;
281 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
282 printf("log flag is currently %#x\n", flag);
285 flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
287 if (strstr(opt, "pass")) {
289 if (opts & OPT_VERBOSE)
290 printf("set log flag: pass\n");
293 if (strstr(opt, "nomatch")) {
294 flag |= FF_LOGNOMATCH;
295 if (opts & OPT_VERBOSE)
296 printf("set log flag: nomatch\n");
299 if (strstr(opt, "block") || strchr(opt, 'd')) {
301 if (opts & OPT_VERBOSE)
302 printf("set log flag: block\n");
305 if (strstr(opt, "none")) {
306 if (opts & OPT_VERBOSE)
307 printf("disable all log flags\n");
312 if (opendevice(ipfname, 1) != -2 &&
313 (ioctl(fd, SIOCSETFF, &flag) != 0))
314 ipferror(fd, "ioctl(SIOCSETFF)");
317 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
319 printf("log flags are now %#x\n", flag);
322 if (strstr(opt, "state")) {
323 if (opts & OPT_VERBOSE)
324 printf("set state log flag\n");
325 xfd = open(IPSTATE_NAME, O_RDWR);
328 if (ioctl(xfd, SIOCGETLG, &logopt))
329 ipferror(fd, "ioctl(SIOCGETLG)");
332 if (ioctl(xfd, SIOCSETLG, &logopt))
333 ipferror(xfd, "ioctl(SIOCSETLG)");
339 if (strstr(opt, "nat")) {
340 if (opts & OPT_VERBOSE)
341 printf("set nat log flag\n");
342 xfd = open(IPNAT_NAME, O_RDWR);
345 if (ioctl(xfd, SIOCGETLG, &logopt))
346 ipferror(xfd, "ioctl(SIOCGETLG)");
349 if (ioctl(xfd, SIOCSETLG, &logopt))
350 ipferror(xfd, "ioctl(SIOCSETLG)");
358 static void flushfilter(arg, filter)
366 if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) {
369 else if (*arg == 's')
376 if (opendevice(IPSTATE_NAME, 1) == -2)
379 if (!(opts & OPT_DONOTHING)) {
382 "IPv6 rules are no longer seperate\n");
383 } else if (filter != NULL) {
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)");
394 fl = obj.ipfo_retval;
397 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
398 ipferror(fd, "ioctl(SIOCIPFFL)");
403 if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
404 printf("remove flags %s (%d)\n", arg, rem);
406 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
407 printf("%d state entries removed\n", fl);
411 } else if (strchr(arg, 'i') || strchr(arg, 'I'))
413 else if (strchr(arg, 'o') || strchr(arg, 'O'))
415 else if (strchr(arg, 'a') || strchr(arg, 'A'))
416 fl = FR_OUTQUE|FR_INQUE;
418 fprintf(stderr, "Incorrect flush argument: %s\n", arg);
421 if (opts & OPT_INACTIVE)
425 if (opendevice(ipfname, 1) == -2)
428 if (!(opts & OPT_DONOTHING)) {
430 if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
431 ipferror(fd, "ioctl(SIOCIPFL6)");
435 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
436 ipferror(fd, "ioctl(SIOCIPFFL)");
442 if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
443 printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
444 (rem & FR_OUTQUE) ? "O" : "", rem);
446 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
447 printf("%d filter rules removed\n", fl);
453 static void swapactive()
457 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
458 ipferror(fd, "ioctl(SIOCSWAPA)");
460 printf("Set %d now inactive\n", in);
468 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
469 ipferror(fd, "SIOCFRSYN");
471 printf("filter sync'd\n");
480 obj.ipfo_rev = IPFILTER_VERSION;
481 obj.ipfo_type = IPFOBJ_IPFSTAT;
482 obj.ipfo_size = sizeof(fio);
486 if (opendevice(ipfname, 1) != -2) {
487 if (ioctl(fd, SIOCFRZST, &obj) == -1) {
488 ipferror(fd, "ioctl(SIOCFRZST)");
498 * read the kernel stats for packets blocked and passed
500 static void showstats(fp)
503 printf("bad packets:\t\tin %lu\tout %lu\n",
504 fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
505 printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
506 fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
508 printf(" counted %lu\n", fp->f_st[0].fr_acct);
509 printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
510 fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
512 printf(" counted %lu\n", fp->f_st[0].fr_acct);
513 printf(" input packets logged:\tblocked %lu passed %lu\n",
514 fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
515 printf("output packets logged:\tblocked %lu passed %lu\n",
516 fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
520 static int showversion()
528 bzero((caddr_t)&ipfo, sizeof(ipfo));
529 ipfo.ipfo_rev = IPFILTER_VERSION;
530 ipfo.ipfo_size = sizeof(fio);
531 ipfo.ipfo_ptr = (void *)&fio;
532 ipfo.ipfo_type = IPFOBJ_IPFSTAT;
534 printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
536 if ((vfd = open(ipfname, O_RDONLY)) == -1) {
537 perror("open device");
541 if (ioctl(vfd, SIOCGETFS, &ipfo)) {
542 ipferror(vfd, "ioctl(SIOCGETFS)");
549 printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version),
550 (int)sizeof(fio.f_version), fio.f_version);
551 printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no");
552 printf("Log Flags: %#x = ", flags);
554 if (flags & FF_LOGPASS) {
558 if (flags & FF_LOGBLOCK) {
559 printf("%sblock", s);
562 if (flags & FF_LOGNOMATCH) {
563 printf("%snomatch", s);
566 if (flags & FF_BLOCKNONIP) {
567 printf("%snonip", s);
575 if (FR_ISPASS(fio.f_defpass))
577 else if (FR_ISBLOCK(fio.f_defpass))
580 s = "nomatch -> block";
581 printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un");
582 printf("Active list: %d\n", fio.f_active);
583 printf("Feature mask: %#x\n", fio.f_features);