diff options
author | Mike Frantzen <frantzen@cvs.openbsd.org> | 2002-03-25 22:05:50 +0000 |
---|---|---|
committer | Mike Frantzen <frantzen@cvs.openbsd.org> | 2002-03-25 22:05:50 +0000 |
commit | 2c17a6c4c9dcacc6f7bd77dd2fbe1186204c519b (patch) | |
tree | e97a1a9f6f77122754611e3e0fe3a2f56a34cc15 /sbin/pfctl/pfctl.c | |
parent | 89db73fcfbfdf3a4b8dd0dc89403d028a8d26d6d (diff) |
add -k option to shootdown all the state entries from the specified host
ok dhartmei@
Diffstat (limited to 'sbin/pfctl/pfctl.c')
-rw-r--r-- | sbin/pfctl/pfctl.c | 121 |
1 files changed, 119 insertions, 2 deletions
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 9f52a11fc9a..e2a61319938 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl.c,v 1.55 2002/03/11 22:22:57 dhartmei Exp $ */ +/* $OpenBSD: pfctl.c,v 1.56 2002/03/25 22:05:49 frantzen Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -36,6 +36,7 @@ #include <net/if.h> #include <netinet/in.h> #include <net/pfvar.h> +#include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> @@ -45,6 +46,7 @@ #include <errno.h> #include <err.h> #include <limits.h> +#include <netdb.h> #include "pfctl_parser.h" @@ -82,6 +84,8 @@ char *showopt; char *timeoutopt; char *limitopt; char *debugopt; +int state_killers; +char *state_kill[2]; char *infile; @@ -263,6 +267,107 @@ pfctl_clear_states(int dev, int opts) } int +pfctl_kill_states(int dev, int opts) +{ + struct pfioc_state_kill psk; + struct addrinfo *res[2], *resp[2]; + struct sockaddr last_src, last_dst; + int killed, sources, dests; + int ret_ga; + + killed = sources = dests = 0; + + memset(&psk, 0, sizeof(psk)); + memset(&psk.psk_src.mask, 0xff, sizeof(psk.psk_src.mask)); + memset(&last_src, 0xff, sizeof(last_src)); + memset(&last_dst, 0xff, sizeof(last_dst)); + + if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { + errx(1, "%s", gai_strerror(ret_ga)); + /* NOTREACHED */ + } + for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { + if (resp[0]->ai_addr == NULL) + continue; + /* We get lots of duplicates. Catch the easy ones */ + if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) + continue; + last_src = *(struct sockaddr *)resp[0]->ai_addr; + + psk.psk_af = resp[0]->ai_family; + sources++; + + if (psk.psk_af == AF_INET) + psk.psk_src.addr.v4 = + ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; + else if (psk.psk_af == AF_INET6) + psk.psk_src.addr.v6 = + ((struct sockaddr_in6 *)resp[0]->ai_addr)-> + sin6_addr; + else + errx(1, "Unknown address family!?!?!"); + + if (state_killers > 1) { + dests = 0; + memset(&psk.psk_dst.mask, 0xff, + sizeof(psk.psk_dst.mask)); + memset(&last_dst, 0xff, sizeof(last_dst)); + if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, + &res[1]))) { + errx(1, "%s", gai_strerror(ret_ga)); + /* NOTREACHED */ + } + for (resp[1] = res[1]; resp[1]; + resp[1] = resp[1]->ai_next) { + if (resp[1]->ai_addr == NULL) + continue; + if (psk.psk_af != resp[1]->ai_family) + continue; + + if (memcmp(&last_dst, resp[1]->ai_addr, + sizeof(last_dst)) == 0) + continue; + last_dst = *(struct sockaddr *)resp[1]->ai_addr; + + dests++; + + if (psk.psk_af == AF_INET) + psk.psk_dst.addr.v4 = + ((struct sockaddr_in *)resp[1]-> + ai_addr)->sin_addr; + else if (psk.psk_af == AF_INET6) + psk.psk_dst.addr.v6 = + ((struct sockaddr_in6 *)resp[1]-> + ai_addr)->sin6_addr; + else + errx(1, "Unknown address family!?!?!"); + + if (ioctl(dev, DIOCKILLSTATES, &psk)) + err(1, "DIOCKILLSTATES"); + killed += psk.psk_af; + /* fixup psk.psk_af */ + psk.psk_af = resp[1]->ai_family; + } + } else { + if (ioctl(dev, DIOCKILLSTATES, &psk)) + err(1, "DIOCKILLSTATES"); + killed += psk.psk_af; + /* fixup psk.psk_af */ + psk.psk_af = res[0]->ai_family; + } + } + + freeaddrinfo(res[0]); + if (res[1]) + freeaddrinfo(res[1]); + + if ((opts & PF_OPT_QUIET) == 0) + printf("killed %d states from %d sources and %d destinations\n", + killed, sources, dests); + return 0; +} + +int pfctl_show_rules(int dev, int opts, int format) { struct pfioc_rule pr; @@ -817,7 +922,8 @@ main(int argc, char *argv[]) if (argc < 2) usage(); - while ((ch = getopt(argc, argv, "deqF:hl:m:nN:O:rR:s:t:vx:z")) != -1) { + while ((ch = getopt(argc, argv, "deqF:hk:l:m:nN:O:rR:s:t:vx:z")) != -1) + { switch (ch) { case 'd': opts |= PF_OPT_DISABLE; @@ -834,6 +940,15 @@ main(int argc, char *argv[]) clearopt = optarg; mode = O_RDWR; break; + case 'k': + if (state_killers >= 2) { + warnx("can only specify -k twice"); + usage(); + /* NOTREACHED */ + } + state_kill[state_killers++] = optarg; + mode = O_RDWR; + break; case 'l': logopt = optarg; mode = O_RDWR; @@ -934,6 +1049,8 @@ main(int argc, char *argv[]) error = 1; } } + if (state_killers) + pfctl_kill_states(dev, opts); if (rulesopt != NULL) if (pfctl_rules(dev, rulesopt, opts)) |