summaryrefslogtreecommitdiff
path: root/sbin/pfctl/pfctl.c
diff options
context:
space:
mode:
authorKjell Wooding <kjell@cvs.openbsd.org>2001-06-24 21:04:21 +0000
committerKjell Wooding <kjell@cvs.openbsd.org>2001-06-24 21:04:21 +0000
commitbeb2ed44a9d221c847249602b2a461b4ebbe2517 (patch)
tree3d10b4627ec4bd95aa181ac6a166eda387975602 /sbin/pfctl/pfctl.c
parenta8e7ede44bdc1df0f4533b916123f47ef374c6fe (diff)
Move and rename packet filter userland.
grr. CVS: making easy things difficult, and directory operations impossible.
Diffstat (limited to 'sbin/pfctl/pfctl.c')
-rw-r--r--sbin/pfctl/pfctl.c371
1 files changed, 371 insertions, 0 deletions
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
new file mode 100644
index 00000000000..ae98842d61e
--- /dev/null
+++ b/sbin/pfctl/pfctl.c
@@ -0,0 +1,371 @@
+/* $OpenBSD: pfctl.c,v 1.1 2001/06/24 21:04:15 kjell Exp $ */
+
+/*
+ * Copyright (c) 2001, Daniel Hartmeier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#include "pfctl_parser.h"
+
+static void printerror(char *);
+static void usage(char *);
+static char *load_file(char *, size_t *);
+int main(int, char *[]);
+
+static char *errormsg[] = {
+ "invalid operation", /* ERROR_INVALID_OP */
+ "packetfilter is running", /* ERROR_ALREADY_RUNNING */
+ "packetfilter not running", /* ERROR_NOT_RUNNING */
+ "invalid parameters", /* ERROR_INVALID_PARAMETERS */
+ "memory allocation failed" /* ERROR_MALLOC */
+};
+
+static void
+printerror(char *s)
+{
+ char *msg;
+ if ((errno >= 100) && (errno < MAX_ERROR_NUM))
+ msg = errormsg[errno-100];
+ else
+ msg = strerror(errno);
+ fprintf(stderr, "ERROR: %s: %s\n", s, msg);
+ return;
+}
+
+static void
+usage(char *argv0)
+{
+ char *n = rindex(argv0, '/');
+ if (n != NULL)
+ n++;
+ else
+ n = argv0;
+ fprintf(stderr, "Usage: %s command argument\n", n);
+ fprintf(stderr, "\tstart\t\t\tStart packet filter\n");
+ fprintf(stderr, "\tstop\t\t\tStop packet filter\n");
+ fprintf(stderr, "\tshow\trules\t\tShow filter rules\n");
+ fprintf(stderr, "\t\tnat\t\t NAT/RDR rules\n");
+ fprintf(stderr, "\t\tstates [proto]\t list of active states\n");
+ fprintf(stderr, "\t\tstatus\t\t status\n");
+ fprintf(stderr, "\tclear\trules\t\tClear filter rules\n");
+ fprintf(stderr, "\t\tnat\t\t NAT/RDR rules\n");
+ fprintf(stderr, "\t\tstates\t\t states\n");
+ fprintf(stderr, "\tparse\trules\t<file>\tCheck syntax of filter rules\n");
+ fprintf(stderr, "\t\tnat\t<file>\t NAT/RDR rules\n");
+ fprintf(stderr, "\tload\trules\t<file>\tLoad filter rules\n");
+ fprintf(stderr, "\t\tnat\t<file>\t NAT/RDR rules\n");
+ fprintf(stderr, "\tlog\t\t<if>\tSet interface to log\n");
+}
+
+static char *
+load_file(char *name, size_t *len)
+{
+ char *buf = 0;
+ FILE *file = fopen(name, "r");
+ *len = 0;
+ if (file == NULL) {
+ fprintf(stderr, "ERROR: couldn't open file %s (%s)\n",
+ name, strerror(errno));
+ return 0;
+ }
+ fseek(file, 0, SEEK_END);
+ *len = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ buf = malloc(*len);
+ if (buf == NULL) {
+ fclose(file);
+ fprintf(stderr, "ERROR: malloc() failed\n");
+ return 0;
+ }
+ if (fread(buf, 1, *len, file) != *len) {
+ free(buf);
+ fclose(file);
+ fprintf(stderr, "ERROR: fread() failed\n");
+ return 0;
+ }
+ fclose(file);
+ return buf;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int dev;
+ struct ioctlbuffer *ub;
+ u_int16_t n = 0;
+ ub = malloc(sizeof(struct ioctlbuffer));
+ if (ub == NULL) {
+ printf("ERROR: malloc() failed\n");
+ return 1;
+ }
+ ub->size = 131072;
+ ub->buffer = malloc(ub->size);
+ if (ub->buffer == NULL) {
+ printf("ERROR: malloc() failed\n");
+ return 1;
+ }
+ memset(ub->buffer, 0, ub->size);
+ ub->entries = 0;
+ if (argc < 2) {
+ usage(argv[0]);
+ return 1;
+ }
+ dev = open("/dev/pf", O_RDWR);
+ if (dev < 0) {
+ printerror("open(/dev/pf)");
+ return 1;
+ }
+ if (!strcmp(argv[1], "start")) {
+ if (ioctl(dev, DIOCSTART))
+ printerror("DIOCSTART");
+ else
+ printf("packetfilter started\n");
+ }
+ else if (!strcmp(argv[1], "stop")) {
+ if (ioctl(dev, DIOCSTOP))
+ printerror("DIOCSTOP");
+ else
+ printf("packetfilter stopped\n");
+ }
+ else if (!strcmp(argv[1], "show")) {
+ if (argc < 3) {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ if (!strcmp(argv[2], "rules")) {
+ struct rule *rule = ub->buffer;
+ ub->entries = ub->size / sizeof(struct rule);
+ if (ioctl(dev, DIOCGETRULES, ub))
+ printerror("DIOCGETRULES");
+ for (n = 0; n < ub->entries; ++n) {
+ printf("@%u ", n + 1);
+ print_rule(rule + n);
+ }
+ }
+ else if (!strcmp(argv[2], "nat")) {
+ struct nat *nat = ub->buffer;
+ struct rdr *rdr = ub->buffer;
+ ub->entries = ub->size / sizeof(struct nat);
+ if (ioctl(dev, DIOCGETNAT, ub))
+ printerror("DIOCGETNAT");
+ for (n = 0; n < ub->entries; ++n)
+ print_nat(nat + n);
+ ub->entries = ub->size / sizeof(struct rdr);
+ if (ioctl(dev, DIOCGETRDR, ub))
+ printerror("DIOCGETRDR");
+ for (n = 0; n < ub->entries; ++n)
+ print_rdr(rdr + n);
+ }
+ else if (!strcmp(argv[2], "states")) {
+ u_int8_t proto = 0;
+ struct state *state = ub->buffer;
+ if (argc >= 4) {
+ if (!strcmp(argv[3], "tcp"))
+ proto = IPPROTO_TCP;
+ else if (!strcmp(argv[3], "udp"))
+ proto = IPPROTO_UDP;
+ else if (!strcmp(argv[3], "icmp"))
+ proto = IPPROTO_ICMP;
+ else {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ ub->entries = ub->size / sizeof(struct state);
+ if (ioctl(dev, DIOCGETSTATES, ub))
+ printerror("DIOCGETSTATES");
+ for (n = ub->entries; n > 0; --n)
+ if (!proto || (state[n - 1].proto == proto))
+ print_state(state + n - 1);
+ }
+ else if (!strcmp(argv[2], "status")) {
+ struct status *status = ub->buffer;
+ ub->entries = 1;
+ if (ioctl(dev, DIOCGETSTATUS, ub))
+ printerror("DIOCGETSTATUS");
+ print_status(status);
+ }
+ else {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ else if (!strcmp(argv[1], "clear")) {
+ if (argc < 3) {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ ub->entries = 0;
+ if (!strcmp(argv[2], "rules")) {
+ if (ioctl(dev, DIOCSETRULES, ub))
+ printerror("DIOCSETRULES");
+ else printf("rules cleared\n");
+ }
+ else if (!strcmp(argv[2], "nat")) {
+ if (ioctl(dev, DIOCSETNAT, ub))
+ printerror("DIOCSETNAT");
+ else if (ioctl(dev, DIOCSETRDR, ub))
+ printerror("DIOCSETRDR");
+ else printf("nat cleared\n");
+ }
+ else if (!strcmp(argv[2], "states")) {
+ if (ioctl(dev, DIOCCLRSTATES))
+ printerror("DIOCCLRSTATES");
+ else
+ printf("states cleared\n");
+ }
+ else {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ else if (!strcmp(argv[1], "log")) {
+ if (argc < 3) {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ strncpy(ub->buffer, argv[2], 16);
+ if (ioctl(dev, DIOCSETSTATUSIF, ub))
+ printerror("DIOCSETSTATUSIF");
+ else
+ printf("now logging %s\n", argv[2]);
+ }
+ else if (!strcmp(argv[1], "parse") || !strcmp(argv[1], "load")) {
+ int load = !strcmp(argv[1], "load");
+ char *buf, *s;
+ size_t len;
+ unsigned nr = 0;
+ if ((argc < 4) || (strcmp(argv[2], "nat") &&
+ strcmp(argv[2], "rules"))) {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ buf = load_file(argv[3], &len);
+ if (buf == NULL)
+ return 1;
+
+ if (!strcmp(argv[2], "rules")) {
+ struct rule *rule = ub->buffer;
+ n = 0;
+ nr = 0;
+ s = buf;
+ do {
+ char *line = next_line(&s);
+ nr++;
+ if (*line && (*line != '#'))
+ if (parse_rule(nr, line, rule + n))
+ n++;
+ } while (s < (buf + len));
+ ub->entries = n;
+ if (load) {
+ if (ioctl(dev, DIOCSETRULES, ub))
+ printerror("DIOCSETRULES");
+ else
+ printf("%u rules loaded\n",
+ ub->entries);
+ } else
+ for (n = 0; n < ub->entries; ++n)
+ print_rule(rule + n);
+ } else {
+ struct nat *nat = ub->buffer;
+ struct rdr *rdr = ub->buffer;
+ n = 0;
+ nr = 0;
+ s = buf;
+ do {
+ char *line = next_line(&s);
+ nr++;
+ if (*line && (*line == 'n'))
+ if (parse_nat(nr, line, nat + n))
+ n++;
+ } while (s < (buf + len));
+ ub->entries = n;
+ if (load) {
+ if (ioctl(dev, DIOCSETNAT, ub))
+ printerror("DIOCSETNAT");
+ else
+ printf("%u nat entries loaded\n",
+ ub->entries);
+ } else
+ for (n = 0; n < ub->entries; ++n)
+ print_nat(nat + n);
+ free(buf);
+ buf = load_file(argv[3], &len);
+ if (buf == NULL)
+ return 1;
+ n = 0;
+ nr = 0;
+ s = buf;
+ do {
+ char *line = next_line(&s);
+ nr++;
+ if (*line && (*line == 'r'))
+ if (parse_rdr(nr, line, rdr + n))
+ n++;
+ } while (s < (buf + len));
+ ub->entries = n;
+ if (load) {
+ if (ioctl(dev, DIOCSETRDR, ub))
+ printerror("DIOCSETRDR");
+ else
+ printf("%u rdr entries loaded\n",
+ ub->entries);
+ } else
+ for (n = 0; n < ub->entries; ++n)
+ print_rdr(rdr + n);
+ }
+
+ free(buf);
+ }
+ else {
+ close(dev);
+ usage(argv[0]);
+ return 1;
+ }
+ close(dev);
+ free(ub->buffer);
+ free(ub);
+ return 0;
+}
+