4 * Copyright (C) 2012 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
11 #include <sys/ioctl.h>
12 #include "netinet/ipl.h"
15 static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
16 static const char rcsid[] = "@(#)$Id$";
19 #if !defined(__SVR4) && defined(__GNUC__)
20 extern char *index(const char *, int);
25 extern frentry_t *frtop;
28 void ipf_frsync(void);
30 int main(int, char *[]);
37 static void procfile(char *);
38 static void flushfilter(char *, int *);
39 static void set_state(u_int);
40 static void showstats(friostat_t *);
41 static void packetlogon(char *);
42 static void swapactive(void);
43 static int opendevice(char *, int);
44 static void closedevice(void);
45 static char *ipfname = IPL_NAME;
46 static void usage(void);
47 static int showversion(void);
48 static int get_flags(void);
49 static int ipf_interceptadd(int, ioctlfunc_t, void *);
52 static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl,
56 /* XXX The following was added to satisfy a rescue/rescue/ build
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>]");
70 main(int argc, char *argv[])
72 int c, *filter = NULL;
77 assigndefined(getenv("IPF_PREDEFINED"));
79 while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ")) != -1) {
92 opts &= ~OPT_INACTIVE;
95 if (strcmp(optarg, "c") == 0)
111 flushfilter(optarg, filter);
114 opts ^= OPT_INACTIVE;
120 filter = parseipfexpr(optarg, NULL);
123 opts ^= OPT_DONOTHING|OPT_DONTOPEN;
128 ipfname = IPAUTH_NAME;
131 opts ^= OPT_NORESOLVE;
140 if (opendevice(ipfname, 1) >= 0)
141 ipf_dotuning(fd, optarg, ioctl);
154 opts ^= OPT_ZERORULEST;
174 opendevice(char *ipfdev, int check)
176 if (opts & OPT_DONOTHING)
179 if (check && checkrev(ipfname) == -1) {
180 fprintf(stderr, "User/kernel version check failed\n");
188 if ((fd = open(ipfdev, O_RDWR)) == -1)
189 if ((fd = open(ipfdev, O_RDONLY)) == -1)
190 ipferror(fd, "open device");
208 if ((opendevice(ipfname, 1) != -2) &&
209 (ioctl(fd, SIOCGETFF, &i) == -1)) {
210 ipferror(fd, "SIOCGETFF");
218 set_state(u_int enable)
220 if (opendevice(ipfname, 0) != -2) {
221 if (ioctl(fd, SIOCFRENB, &enable) == -1) {
222 if (errno == EBUSY) {
224 "IP FIlter: already initialized\n");
226 ipferror(fd, "SIOCFRENB");
237 (void) opendevice(ipfname, 1);
241 ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file);
246 emit(-1, -1, NULL, NULL);
252 ipf_interceptadd(int fd, ioctlfunc_t ioctlfunc, void *ptr)
257 if (ipf_addrule(fd, ioctlfunc, ptr) != 0)
264 packetlogon(char *opt)
266 int flag, xfd, logopt, change = 0;
270 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE)
271 printf("log flag is currently %#x\n", flag);
274 flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
276 if (strstr(opt, "pass")) {
278 if (opts & OPT_VERBOSE)
279 printf("set log flag: pass\n");
282 if (strstr(opt, "nomatch")) {
283 flag |= FF_LOGNOMATCH;
284 if (opts & OPT_VERBOSE)
285 printf("set log flag: nomatch\n");
288 if (strstr(opt, "block") || strchr(opt, 'd')) {
290 if (opts & OPT_VERBOSE)
291 printf("set log flag: block\n");
294 if (strstr(opt, "none")) {
295 if (opts & OPT_VERBOSE)
296 printf("disable all log flags\n");
301 if (opendevice(ipfname, 1) != -2 &&
302 (ioctl(fd, SIOCSETFF, &flag) != 0))
303 ipferror(fd, "ioctl(SIOCSETFF)");
306 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
308 printf("log flags are now %#x\n", flag);
311 if (strstr(opt, "state")) {
312 if (opts & OPT_VERBOSE)
313 printf("set state log flag\n");
314 xfd = open(IPSTATE_NAME, O_RDWR);
317 if (ioctl(xfd, SIOCGETLG, &logopt))
318 ipferror(fd, "ioctl(SIOCGETLG)");
321 if (ioctl(xfd, SIOCSETLG, &logopt))
322 ipferror(xfd, "ioctl(SIOCSETLG)");
328 if (strstr(opt, "nat")) {
329 if (opts & OPT_VERBOSE)
330 printf("set nat log flag\n");
331 xfd = open(IPNAT_NAME, O_RDWR);
334 if (ioctl(xfd, SIOCGETLG, &logopt))
335 ipferror(xfd, "ioctl(SIOCGETLG)");
338 if (ioctl(xfd, SIOCSETLG, &logopt))
339 ipferror(xfd, "ioctl(SIOCSETLG)");
348 flushfilter(char *arg, int *filter)
354 if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) {
357 else if (*arg == 's')
364 if (opendevice(IPSTATE_NAME, 1) == -2)
367 if (!(opts & OPT_DONOTHING)) {
370 "IPv6 rules are no longer seperate\n");
371 } else if (filter != NULL) {
374 obj.ipfo_rev = IPFILTER_VERSION;
375 obj.ipfo_size = filter[0] * sizeof(int);
376 obj.ipfo_type = IPFOBJ_IPFEXPR;
377 obj.ipfo_ptr = filter;
378 if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) {
379 ipferror(fd, "ioctl(SIOCMATCHFLUSH)");
382 fl = obj.ipfo_retval;
385 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
386 ipferror(fd, "ioctl(SIOCIPFFL)");
391 if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
392 printf("remove flags %s (%d)\n", arg, rem);
394 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
395 printf("%d state entries removed\n", fl);
399 } else if (strchr(arg, 'i') || strchr(arg, 'I'))
401 else if (strchr(arg, 'o') || strchr(arg, 'O'))
403 else if (strchr(arg, 'a') || strchr(arg, 'A'))
404 fl = FR_OUTQUE|FR_INQUE;
406 fprintf(stderr, "Incorrect flush argument: %s\n", arg);
409 if (opts & OPT_INACTIVE)
413 if (opendevice(ipfname, 1) == -2)
416 if (!(opts & OPT_DONOTHING)) {
418 if (ioctl(fd, SIOCIPFL6, &fl) == -1) {
419 ipferror(fd, "ioctl(SIOCIPFL6)");
423 if (ioctl(fd, SIOCIPFFL, &fl) == -1) {
424 ipferror(fd, "ioctl(SIOCIPFFL)");
430 if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) {
431 printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
432 (rem & FR_OUTQUE) ? "O" : "", rem);
434 if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
435 printf("%d filter rules removed\n", fl);
446 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
447 ipferror(fd, "ioctl(SIOCSWAPA)");
449 printf("Set %d now inactive\n", in);
458 if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1)
459 ipferror(fd, "SIOCFRSYN");
461 printf("filter sync'd\n");
471 obj.ipfo_rev = IPFILTER_VERSION;
472 obj.ipfo_type = IPFOBJ_IPFSTAT;
473 obj.ipfo_size = sizeof(fio);
477 if (opendevice(ipfname, 1) != -2) {
478 if (ioctl(fd, SIOCFRZST, &obj) == -1) {
479 ipferror(fd, "ioctl(SIOCFRZST)");
489 * read the kernel stats for packets blocked and passed
492 showstats(friostat_t *fp)
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,
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,
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);
520 bzero((caddr_t)&ipfo, sizeof(ipfo));
521 ipfo.ipfo_rev = IPFILTER_VERSION;
522 ipfo.ipfo_size = sizeof(fio);
523 ipfo.ipfo_ptr = (void *)&fio;
524 ipfo.ipfo_type = IPFOBJ_IPFSTAT;
526 printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t));
528 if ((vfd = open(ipfname, O_RDONLY)) == -1) {
529 perror("open device");
533 if (ioctl(vfd, SIOCGETFS, &ipfo)) {
534 ipferror(vfd, "ioctl(SIOCGETFS)");
541 printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version),
542 (int)sizeof(fio.f_version), fio.f_version);
543 printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no");
544 printf("Log Flags: %#x = ", flags);
546 if (flags & FF_LOGPASS) {
550 if (flags & FF_LOGBLOCK) {
551 printf("%sblock", s);
554 if (flags & FF_LOGNOMATCH) {
555 printf("%snomatch", s);
558 if (flags & FF_BLOCKNONIP) {
559 printf("%snonip", s);
567 if (FR_ISPASS(fio.f_defpass))
569 else if (FR_ISBLOCK(fio.f_defpass))
572 s = "nomatch -> block";
573 printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un");
574 printf("Active list: %d\n", fio.f_active);
575 printf("Feature mask: %#x\n", fio.f_features);