summaryrefslogtreecommitdiff
path: root/sbin/pfctl/pfctl.c
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2001-06-25 17:17:07 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2001-06-25 17:17:07 +0000
commit594496da2fc970f542b137f3525105a219d48378 (patch)
tree11225b9eb32defeee3f5e459ff076aad4f18e64f /sbin/pfctl/pfctl.c
parentc8fea6f2d455ebb4f7324f4dc5e46a4ad5c8f340 (diff)
revised ioctl interface, first getopt version of pfctl
Diffstat (limited to 'sbin/pfctl/pfctl.c')
-rw-r--r--sbin/pfctl/pfctl.c603
1 files changed, 352 insertions, 251 deletions
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 9586094faf0..7908642a536 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.8 2001/06/25 10:14:07 deraadt Exp $ */
+/* $OpenBSD: pfctl.c,v 1.9 2001/06/25 17:17:06 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -46,42 +46,37 @@
#include "pfctl_parser.h"
-void printerror(char *);
-void usage(char *);
+void print_error(char *);
+void usage();
char *load_file(char *, size_t *);
+int pfctl_enable(int);
+int pfctl_disable(int);
+int pfctl_clear_rules(int);
+int pfctl_clear_nat(int);
+int pfctl_clear_states(int);
+int pfctl_show_rules(int);
+int pfctl_show_nat(int);
+int pfctl_show_states(int, u_int8_t);
+int pfctl_show_status(int);
+int pfctl_rules(int, char *);
+int pfctl_nat(int, char *);
+int pfctl_log(int, char *);
int main(int, char *[]);
void
-printerror(char *s)
+print_error(char *s)
{
fprintf(stderr, "ERROR: %s: %s\n", s, strerror(errno));
return;
}
void
-usage(char *argv0)
+usage()
{
- 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");
+ extern char *__progname;
+
+ fprintf(stderr, "usage: %s [-d] [-c set] [-r file]", __progname);
+ fprintf(stderr, " [-n file] [-s set] [-l if] [-e]\n");
}
char *
@@ -116,257 +111,363 @@ load_file(char *name, size_t *len)
}
int
-main(int argc, char *argv[])
+pfctl_enable(int dev)
{
- int dev;
- struct pfioc *ub;
- u_int16_t n = 0;
+ if (ioctl(dev, DIOCSTART)) {
+ print_error("DIOCSTART");
+ return 1;
+ }
+ printf("pf enabled\n");
+ return 0;
+}
- ub = malloc(sizeof(struct pfioc));
- if (ub == NULL) {
- printf("ERROR: malloc() failed\n");
- return (1);
+int
+pfctl_disable(int dev)
+{
+ if (ioctl(dev, DIOCSTOP)) {
+ print_error("DIOCSTOP");
+ return 1;
}
- ub->size = 131072;
- ub->buffer = malloc(ub->size);
- if (ub->buffer == NULL) {
- printf("ERROR: malloc() failed\n");
+ printf("pf disabled\n");
+ return 0;
+}
+
+int
+pfctl_clear_rules(int dev)
+{
+ struct pfioc_rule pr;
+
+ if (ioctl(dev, DIOCBEGINRULES, &pr.ticket)) {
+ print_error("DIOCBEGINRULES");
return (1);
- }
- memset(ub->buffer, 0, ub->size);
- ub->entries = 0;
- if (argc < 2) {
- usage(argv[0]);
+ } else if (ioctl(dev, DIOCCOMMITRULES, &pr.ticket)) {
+ print_error("DIOCCOMMITRULES");
return (1);
}
- dev = open("/dev/pf", O_RDWR);
- if (dev < 0) {
- printerror("open(/dev/pf)");
+ printf("rules cleared\n");
+ return (0);
+}
+
+int
+pfctl_clear_nat(int dev)
+{
+ struct pfioc_nat pn;
+ struct pfioc_rdr pr;
+
+ if (ioctl(dev, DIOCBEGINNATS, &pn.ticket)) {
+ print_error("DIOCBEGINNATS");
+ return (1);
+ } else if (ioctl(dev, DIOCCOMMITNATS, &pn.ticket)) {
+ print_error("DIOCCOMMITNATS");
+ return (1);
+ } else if (ioctl(dev, DIOCBEGINRDRS, &pr.ticket)) {
+ print_error("DIOCBEGINRDRS");
+ return (1);
+ } else if (ioctl(dev, DIOCCOMMITRDRS, &pr.ticket)) {
+ print_error("DIOCCOMMITRDRS");
return (1);
}
- if (!strcmp(argv[1], "start")) {
- if (ioctl(dev, DIOCSTART))
- printerror("DIOCSTART");
- else
- printf("packetfilter started\n");
+ printf("nat cleared\n");
+ return (0);
+}
+
+int
+pfctl_clear_states(int dev)
+{
+ if (ioctl(dev, DIOCCLRSTATES)) {
+ print_error("DIOCCLRSTATES");
+ return (1);
}
- else if (!strcmp(argv[1], "stop")) {
- if (ioctl(dev, DIOCSTOP))
- printerror("DIOCSTOP");
- else
- printf("packetfilter stopped\n");
+ printf("states cleared\n");
+ return (0);
+}
+
+int
+pfctl_show_rules(int dev)
+{
+ struct pfioc_rule pr;
+ u_int32_t nr, mnr;
+
+ if (ioctl(dev, DIOCGETRULES, &pr)) {
+ print_error("DIOCGETRULES");
+ return (1);
}
- else if (!strcmp(argv[1], "show")) {
- if (argc < 3) {
- close(dev);
- usage(argv[0]);
+ mnr = pr.nr;
+ for (nr = 0; nr < mnr; ++nr) {
+ pr.nr = nr;
+ if (ioctl(dev, DIOCGETRULE, &pr)) {
+ print_error("DIOCGETRULE");
return (1);
}
- if (!strcmp(argv[2], "rules")) {
- struct pf_rule *rule = ub->buffer;
-
- ub->entries = ub->size / sizeof(struct pf_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 pf_nat *nat = ub->buffer;
- struct pf_rdr *rdr = ub->buffer;
-
- ub->entries = ub->size / sizeof(struct pf_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 pf_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 pf_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 pf_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 pf_status *status = ub->buffer;
+ printf("@%u ", nr + 1);
+ print_rule(&pr.rule);
+ }
+ return (0);
+}
- ub->entries = 1;
- if (ioctl(dev, DIOCGETSTATUS, ub))
- printerror("DIOCGETSTATUS");
- print_status(status);
- }
- else {
- close(dev);
- usage(argv[0]);
- return (1);
- }
+int
+pfctl_show_nat(int dev)
+{
+ struct pfioc_nat pn;
+ struct pfioc_rdr pr;
+ u_int32_t mnr, nr;
+
+ if (ioctl(dev, DIOCGETNATS, &pn)) {
+ print_error("DIOCGETNATS");
+ 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]);
+ mnr = pn.nr;
+ for (nr = 0; nr < mnr; ++nr) {
+ pn.nr = nr;
+ if (ioctl(dev, DIOCGETNAT, &pn)) {
+ print_error("DIOCGETNAT");
return (1);
}
+ print_nat(&pn.nat);
}
- 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]);
+ if (ioctl(dev, DIOCGETRDRS, &pr)) {
+ print_error("DIOCGETRDRS");
+ return (1);
}
- 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]);
+ mnr = pr.nr;
+ for (nr = 0; nr < mnr; ++nr) {
+ pr.nr = nr;
+ if (ioctl(dev, DIOCGETRDR, &pr)) {
+ print_error("DIOCGETRDR");
return (1);
}
- buf = load_file(argv[3], &len);
- if (buf == NULL)
- return (1);
+ print_rdr(&pr.rdr);
+ }
+ return (0);
+}
- if (!strcmp(argv[2], "rules")) {
- struct pf_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 pf_nat *nat = ub->buffer;
- struct pf_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);
- }
+int
+pfctl_show_states(int dev, u_int8_t proto)
+{
+ struct pfioc_state ps;
+
+ ps.nr = 0;
+ while (!ioctl(dev, DIOCGETSTATE, &ps)) {
+ if (!proto || (ps.state.proto == proto))
+ print_state(&ps.state);
+ ps.nr++;
+ }
+ return (0);
+}
+
+int
+pfctl_show_status(int dev)
+{
+ struct pf_status status;
+ if (ioctl(dev, DIOCGETSTATUS, &status)) {
+ print_error("DIOCGETSTATUS");
+ return (1);
+ }
+ print_status(&status);
+ return (0);
+}
+
+int
+pfctl_rules(int dev, char *filename)
+{
+ struct pfioc_rule pr;
+ char *buf, *s;
+ size_t len;
+ unsigned n, nr;
+
+ buf = load_file(filename, &len);
+ if (buf == NULL)
+ return (1);
+ if (ioctl(dev, DIOCBEGINRULES, &pr.ticket)) {
+ print_error("DIOCBEGINRULES");
free(buf);
+ return (1);
}
- else {
- close(dev);
- usage(argv[0]);
+ n = 0;
+ nr = 0;
+ s = buf;
+ do {
+ char *line = next_line(&s);
+ nr++;
+ if (*line && (*line != '#'))
+ if (parse_rule(nr, line, &pr.rule)) {
+ if (ioctl(dev, DIOCADDRULE, &pr)) {
+ print_error("DIOCADDRULE");
+ free(buf);
+ return (1);
+ }
+ n++;
+ }
+ } while (s < (buf + len));
+ free(buf);
+ if (ioctl(dev, DIOCCOMMITRULES, &pr.ticket)) {
+ print_error("DIOCCOMMITRULES");
return (1);
}
- close(dev);
- free(ub->buffer);
- free(ub);
+ printf("%u rules loaded\n", n);
+ return (0);
+}
+
+int
+pfctl_nat(int dev, char *filename)
+{
+ struct pfioc_nat pn;
+ struct pfioc_rdr pr;
+ char *buf, *s;
+ size_t len;
+ unsigned n, nr;
+
+ if (ioctl(dev, DIOCBEGINNATS, &pn.ticket)) {
+ print_error("DIOCBEGINNATS");
+ return (1);
+ }
+ buf = load_file(filename, &len);
+ if (buf == NULL)
+ return (1);
+ n = 0;
+ nr = 0;
+ s = buf;
+ do {
+ char *line = next_line(&s);
+ nr++;
+ if (*line && (*line == 'n'))
+ if (parse_nat(nr, line, &pn.nat)) {
+ if (ioctl(dev, DIOCADDNAT, &pn)) {
+ print_error("DIOCADDNAT");
+ free(buf);
+ return (1);
+ }
+ n++;
+ }
+ } while (s < (buf + len));
+ free(buf);
+ if (ioctl(dev, DIOCCOMMITNATS, &pn.ticket)) {
+ print_error("DIOCCOMMITNATS");
+ return (1);
+ }
+ printf("%u nat entries loaded\n", n);
+
+ if (ioctl(dev, DIOCBEGINRDRS, &pr.ticket)) {
+ print_error("DIOCBEGINRDRS");
+ return 1;
+ }
+ buf = load_file(filename, &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, &pr.rdr)) {
+ if (ioctl(dev, DIOCADDRDR, &pr)) {
+ print_error("DIOCADDRDR");
+ free(buf);
+ return (1);
+ }
+ n++;
+ }
+ } while (s < (buf + len));
+ free(buf);
+ if (ioctl(dev, DIOCCOMMITRDRS, &pr.ticket)) {
+ print_error("DIOCCOMMITRDRS");
+ return (1);
+ }
+ printf("%u rdr entries loaded\n", n);
+ return (0);
+}
+
+int
+pfctl_log(int dev, char *ifname)
+{
+ struct pfioc_if pi;
+
+ strncpy(pi.ifname, ifname, 16);
+ if (ioctl(dev, DIOCSETSTATUSIF, &pi)) {
+ print_error("DIOCSETSTATUSIF");
+ return (1);
+ }
+ printf("now logging %s\n", pi.ifname);
return (0);
}
+int
+main(int argc, char *argv[])
+{
+ extern char *optarg;
+ extern int optind;
+ int error = 0;
+ int dev;
+ int ch;
+
+ if (argc <= 1) {
+ usage();
+ return (0);
+ }
+ dev = open("/dev/pf", O_RDWR);
+ if (dev < 0) {
+ print_error("open(/dev/pf)");
+ return (1);
+ }
+ while (!error && (ch = getopt(argc, argv, "dc:r:n:s:l:e")) != -1) {
+ switch (ch) {
+ case 'd':
+ if (pfctl_disable(dev))
+ error = 1;
+ break;
+ case 'c':
+ if (!strcmp(optarg, "rules")) {
+ if (pfctl_clear_rules(dev))
+ error = 1;
+ } else if (!strcmp(optarg, "nat")) {
+ if (pfctl_clear_nat(dev))
+ error = 1;
+ } else if (!strcmp(optarg, "states")) {
+ if (pfctl_clear_states(dev))
+ error = 1;
+ } else
+ error = 1;
+ break;
+ case 'r':
+ if (pfctl_rules(dev, optarg))
+ error = 1;
+ break;
+ case 'n':
+ if (pfctl_nat(dev, optarg))
+ error = 1;
+ break;
+ case 's':
+ if (!strcmp(optarg, "rules")) {
+ if (pfctl_show_rules(dev))
+ error = 1;
+ } else if (!strcmp(optarg, "nat")) {
+ if (pfctl_show_nat(dev))
+ error = 1;
+ } else if (!strcmp(optarg, "states")) {
+ if (pfctl_show_states(dev, 0))
+ error = 1;
+ } else if (!strcmp(optarg, "status")) {
+ if (pfctl_show_status(dev))
+ error = 1;
+ } else
+ error = 1;
+ break;
+ case 'l':
+ if (pfctl_log(dev, optarg))
+ error = 1;
+ break;
+ case 'e':
+ if (pfctl_enable(dev))
+ error = 1;
+ break;
+ default:
+ usage();
+ error = 1;
+ }
+ }
+ close(dev);
+ return (error);
+}