aboutsummaryrefslogtreecommitdiff
path: root/contrib/ipfilter/ipf.c
diff options
context:
space:
mode:
authorDarren Reed <darrenr@FreeBSD.org>1997-02-09 22:50:16 +0000
committerDarren Reed <darrenr@FreeBSD.org>1997-02-09 22:50:16 +0000
commitb4ebec5bf8828aa1cc3f5a1a50faf812b5b6ba48 (patch)
tree93c7db298b1fd70f9e27663b3fd527da063d0008 /contrib/ipfilter/ipf.c
Notes
Diffstat (limited to 'contrib/ipfilter/ipf.c')
-rw-r--r--contrib/ipfilter/ipf.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/contrib/ipfilter/ipf.c b/contrib/ipfilter/ipf.c
new file mode 100644
index 000000000000..da6baa244648
--- /dev/null
+++ b/contrib/ipfilter/ipf.c
@@ -0,0 +1,434 @@
+/*
+ * (C)opyright 1993,1994,1995 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#if !defined(__SVR4) && !defined(__GNUC__)
+#include <strings.h>
+#endif
+#if !defined(__SVR4) && defined(__GNUC__)
+extern char *index();
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <net/if.h>
+#include <netinet/ip.h>
+#include "ip_fil.h"
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include "ipf.h"
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-1995 Darren Reed";
+static char rcsid[] = "$Id: ipf.c,v 2.0.1.2 1997/02/04 14:37:46 darrenr Exp $";
+#endif
+
+#if SOLARIS
+void frsync(), blockunknown();
+#endif
+void zerostats();
+
+extern char *optarg;
+
+int opts = 0;
+
+static int fd = -1;
+
+static void procfile(), flushfilter(), set_state();
+static void packetlogon(), swapactive(), showstats();
+static char *getline();
+
+int main(argc,argv)
+int argc;
+char *argv[];
+{
+ char c;
+
+ while ((c = getopt(argc, argv, "AdDEf:F:Il:noprsUvyzZ")) != -1) {
+ switch (c)
+ {
+ case 'E' :
+ set_state(1);
+ break;
+ case 'D' :
+ set_state(0);
+ break;
+ case 'A' :
+ opts &= ~OPT_INACTIVE;
+ break;
+ case 'd' :
+ opts |= OPT_DEBUG;
+ break;
+ case 'f' :
+ procfile(argv[0], optarg);
+ break;
+ case 'F' :
+ flushfilter(optarg);
+ break;
+ case 'I' :
+ opts |= OPT_INACTIVE;
+ break;
+ case 'l' :
+ packetlogon(optarg);
+ break;
+ case 'n' :
+ opts |= OPT_DONOTHING;
+ break;
+ case 'o' :
+ opts |= OPT_OUTQUE;
+ break;
+ case 'p' :
+ opts |= OPT_PRINTFR;
+ break;
+ case 'r' :
+ opts |= OPT_REMOVE;
+ break;
+ case 's' :
+ swapactive();
+ break;
+#if SOLARIS
+ case 'U' :
+ blockunknown();
+ break;
+#endif
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+#if SOLARIS
+ case 'y' :
+ frsync();
+ break;
+#endif
+ case 'z' :
+ opts |= OPT_ZERORULEST;
+ break;
+ case 'Z' :
+ zerostats();
+ break;
+ }
+ }
+
+ if (fd != -1)
+ (void) close(fd);
+
+ exit(0);
+ /* NOTREACHED */
+}
+
+
+static int opendevice()
+{
+ if (opts & OPT_DONOTHING)
+ return -2;
+
+ if (!(opts & OPT_DONOTHING) && fd == -1)
+ if ((fd = open(IPL_NAME, O_RDWR)) == -1)
+ if ((fd = open(IPL_NAME, O_RDONLY)) == -1)
+ perror("open device");
+ return fd;
+}
+
+
+static void set_state(enable)
+u_int enable;
+{
+ if (opendevice() != -2)
+ if (ioctl(fd, SIOCFRENB, &enable) == -1)
+ perror("SIOCFRENB");
+ return;
+}
+
+static void procfile(name, file)
+char *name, *file;
+{
+ FILE *fp;
+ char line[513], *s;
+ struct frentry *fr;
+ u_int add = SIOCADAFR, del = SIOCRMAFR;
+
+ (void) opendevice();
+
+ if (opts & OPT_INACTIVE) {
+ add = SIOCADIFR;
+ del = SIOCRMIFR;
+ }
+ if (opts & OPT_DEBUG)
+ printf("add %x del %x\n", add, del);
+
+ initparse();
+
+ if (!strcmp(file, "-"))
+ fp = stdin;
+ else if (!(fp = fopen(file, "r"))) {
+ fprintf(stderr, "%s: fopen(%s) failed: %s\n", name, file,
+ STRERROR(errno));
+ exit(1);
+ }
+
+ while (getline(line, sizeof(line)-1, fp)) {
+ /*
+ * treat both CR and LF as EOL
+ */
+ if ((s = index(line, '\n')))
+ *s = '\0';
+ if ((s = index(line, '\r')))
+ *s = '\0';
+ /*
+ * # is comment marker, everything after is a ignored
+ */
+ if ((s = index(line, '#')))
+ *s = '\0';
+
+ if (!*line)
+ continue;
+
+ if (opts & OPT_VERBOSE)
+ (void)fprintf(stderr, "[%s]\n",line);
+
+ fr = parse(line);
+ (void)fflush(stdout);
+
+ if (fr) {
+ if (opts & OPT_ZERORULEST)
+ add = SIOCZRLST;
+ else if (opts & OPT_INACTIVE)
+ add = fr->fr_hits ? SIOCINIFR : SIOCADIFR;
+ else
+ add = fr->fr_hits ? SIOCINAFR : SIOCADAFR;
+ if (fr->fr_hits)
+ fr->fr_hits--;
+ if (fr && (opts & OPT_VERBOSE))
+ printfr(fr);
+ if (fr && (opts & OPT_OUTQUE))
+ fr->fr_flags |= FR_OUTQUE;
+
+ if (opts & OPT_DEBUG)
+ binprint(fr);
+
+ if ((opts & OPT_ZERORULEST) &&
+ !(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, add, fr) == -1)
+ perror("ioctl(SIOCZRLST)");
+ else {
+ printf("hits %ld bytes %ld ",
+ fr->fr_hits, fr->fr_bytes);
+ printfr(fr);
+ }
+ } else if ((opts & OPT_REMOVE) &&
+ !(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, del, fr) == -1)
+ perror("ioctl(SIOCDELFR)");
+ } else if (!(opts & OPT_DONOTHING)) {
+ if (ioctl(fd, add, fr) == -1)
+ perror("ioctl(SIOCADDFR)");
+ }
+ }
+ }
+ (void)fclose(fp);
+}
+
+/*
+ * Similar to fgets(3) but can handle '\\'
+ */
+static char *getline(str, size, file)
+register char *str;
+size_t size;
+FILE *file;
+{
+ register char *p;
+
+ do {
+ for (p = str;; p+= strlen(p) - 1) {
+ if (!fgets(p, size, file))
+ return(NULL);
+ p[strlen(p) -1] = '\0';
+ if (p[strlen(p) - 1] != '\\')
+ break;
+ }
+ } while (*str == '\0' || *str == '\n');
+ return(str);
+}
+
+
+static void packetlogon(opt)
+char *opt;
+{
+ int err, flag = 0;
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if ((err = ioctl(fd, SIOCGETFF, &flag)))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is currently %#x\n", flag);
+ }
+
+ flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK);
+
+ if (index(opt, 'p')) {
+ flag |= FF_LOGPASS;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: pass\n");
+ }
+ if (index(opt, 'm') && (*opt == 'n' || *opt == 'N')) {
+ flag |= FF_LOGNOMATCH;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: nomatch\n");
+ }
+ if (index(opt, 'b') || index(opt, 'd')) {
+ flag |= FF_LOGBLOCK;
+ if (opts & OPT_VERBOSE)
+ printf("set log flag: block\n");
+ }
+
+ if (opendevice() != -2 && (err = ioctl(fd, SIOCSETFF, &flag)))
+ perror("ioctl(SIOCSETFF)");
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if ((err = ioctl(fd, SIOCGETFF, &flag)))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is now %#x\n", flag);
+ }
+}
+
+
+static void flushfilter(arg)
+char *arg;
+{
+ int fl = 0, rem;
+
+ if (!arg || !*arg)
+ return;
+ if (strchr(arg, 'i') || strchr(arg, 'I'))
+ fl = FR_INQUE;
+ if (strchr(arg, 'o') || strchr(arg, 'O'))
+ fl = FR_OUTQUE;
+ if (strchr(arg, 'a') || strchr(arg, 'A'))
+ fl = FR_OUTQUE|FR_INQUE;
+ fl |= (opts & FR_INACTIVE);
+ rem = fl;
+
+ if (opendevice() != -2 && ioctl(fd, SIOCIPFFL, &fl) == -1)
+ perror("ioctl(SIOCIPFFL)");
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "",
+ (rem & FR_OUTQUE) ? "O" : "", rem);
+ printf("removed %d filter rules\n", fl);
+ }
+ return;
+}
+
+
+static void swapactive()
+{
+ int in = 2;
+
+ if (opendevice() != -2 && ioctl(fd, SIOCSWAPA, &in) == -1)
+ perror("ioctl(SIOCSWAPA)");
+ else
+ printf("Set %d now inactive\n", in);
+}
+
+
+#if defined(sun) && (defined(__SVR4) || defined(__svr4__))
+void frsync()
+{
+ if (opendevice() != -2 && ioctl(fd, SIOCFRSYN, 0) == -1)
+ perror("SIOCFRSYN");
+ else
+ printf("filter sync'd\n");
+}
+#endif
+
+
+void zerostats()
+{
+ friostat_t fio;
+
+ if (opendevice() != -2) {
+ if (ioctl(fd, SIOCFRZST, &fio) == -1) {
+ perror("ioctl(SIOCFRZST)");
+ exit(-1);
+ }
+ showstats(&fio);
+ }
+
+}
+
+
+/*
+ * read the kernel stats for packets blocked and passed
+ */
+static void showstats(fp)
+friostat_t *fp;
+{
+#if SOLARIS
+ printf("dropped packets:\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_drop, fp->f_st[1].fr_drop);
+ printf("non-ip packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_notip, fp->f_st[1].fr_notip);
+ printf(" bad packets:\t\tin %lu\tout %lu\n",
+ fp->f_st[0].fr_bad, fp->f_st[1].fr_bad);
+#endif
+ printf(" input packets:\t\tblocked %lu passed %lu nomatch %lu",
+ fp->f_st[0].fr_block, fp->f_st[0].fr_pass,
+ fp->f_st[0].fr_nom);
+ printf(" counted %lu\n", fp->f_st[0].fr_acct);
+ printf("output packets:\t\tblocked %lu passed %lu nomatch %lu",
+ fp->f_st[1].fr_block, fp->f_st[1].fr_pass,
+ fp->f_st[1].fr_nom);
+ printf(" counted %lu\n", fp->f_st[0].fr_acct);
+ printf(" input packets logged:\tblocked %lu passed %lu\n",
+ fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl);
+ printf("output packets logged:\tblocked %lu passed %lu\n",
+ fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl);
+ printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n",
+ fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip,
+ fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip);
+}
+
+
+#if SOLARIS
+void blockunknown()
+{
+ int flag;
+
+ if (opendevice() == -1)
+ return;
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if (ioctl(fd, SIOCGETFF, &flag))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is currently %#x\n", flag);
+ }
+
+ flag ^= FF_BLOCKNONIP;
+
+ if (opendevice() != -2 && ioctl(fd, SIOCSETFF, &flag))
+ perror("ioctl(SIOCSETFF)");
+
+ if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) {
+ if (ioctl(fd, SIOCGETFF, &flag))
+ perror("ioctl(SIOCGETFF)");
+
+ printf("log flag is now %#x\n", flag);
+ }
+}
+#endif