diff options
author | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2001-06-25 17:17:07 +0000 |
---|---|---|
committer | Daniel Hartmeier <dhartmei@cvs.openbsd.org> | 2001-06-25 17:17:07 +0000 |
commit | 594496da2fc970f542b137f3525105a219d48378 (patch) | |
tree | 11225b9eb32defeee3f5e459ff076aad4f18e64f /sbin/pfctl/pfctl.c | |
parent | c8fea6f2d455ebb4f7324f4dc5e46a4ad5c8f340 (diff) |
revised ioctl interface, first getopt version of pfctl
Diffstat (limited to 'sbin/pfctl/pfctl.c')
-rw-r--r-- | sbin/pfctl/pfctl.c | 603 |
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); +} |