summaryrefslogtreecommitdiffstats
path: root/sbin/pfctl
diff options
context:
space:
mode:
authorkn <kn@openbsd.org>2019-01-28 10:25:20 +0000
committerkn <kn@openbsd.org>2019-01-28 10:25:20 +0000
commit4a32e6d5fb756d8ed3d25a2be6bc05b64260cd62 (patch)
tree67c82c07cca7d2cbf1b6324698119532ddfcdd86 /sbin/pfctl
parentOn i386, produce binaries that are compatible with our W^X implementation. (diff)
downloadwireguard-openbsd-4a32e6d5fb756d8ed3d25a2be6bc05b64260cd62.tar.xz
wireguard-openbsd-4a32e6d5fb756d8ed3d25a2be6bc05b64260cd62.zip
Simplify lookups when killing entries
Killing source tracking or state entries by hostname or CIDR would pass given keys twice to getaddrinfo(3): once to resolve/parse and again to parse the numerical address in case a prefix was specified. Avoid this overhead by making pfctl_addrprefix() resolve, pass and mask in one go and return the list of IPs to the callers. This notably simplifies both logic and sanity checks around prefix length and address family. While here, also pass -N along such that -k and -K can be restricted to not use DNS. Discussed with procter sashan, OK sashan
Diffstat (limited to 'sbin/pfctl')
-rw-r--r--sbin/pfctl/pfctl.c79
1 files changed, 32 insertions, 47 deletions
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 0fee44796c1..2dc5b54e803 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl.c,v 1.366 2019/01/19 11:48:54 kn Exp $ */
+/* $OpenBSD: pfctl.c,v 1.367 2019/01/28 10:25:20 kn Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -66,7 +66,8 @@ void pfctl_clear_interface_flags(int, int);
void pfctl_clear_rules(int, int, char *);
void pfctl_clear_src_nodes(int, int);
void pfctl_clear_states(int, const char *, int);
-void pfctl_addrprefix(char *, struct pf_addr *);
+struct addrinfo *
+ pfctl_addrprefix(char *, struct pf_addr *, int);
void pfctl_kill_src_nodes(int, int);
void pfctl_net_kill_states(int, const char *, int, int);
void pfctl_label_kill_states(int, const char *, int, int);
@@ -354,35 +355,36 @@ pfctl_clear_states(int dev, const char *iface, int opts)
fprintf(stderr, "%d states cleared\n", psk.psk_killed);
}
-void
-pfctl_addrprefix(char *addr, struct pf_addr *mask)
+struct addrinfo *
+pfctl_addrprefix(char *addr, struct pf_addr *mask, int numeric)
{
char *p;
const char *errstr;
int prefix, ret_ga, q, r;
struct addrinfo hints, *res;
- if ((p = strchr(addr, '/')) == NULL)
- return;
-
- *p++ = '\0';
- prefix = strtonum(p, 0, 128, &errstr);
- if (errstr)
- errx(1, "prefix is %s: %s", errstr, p);
-
bzero(&hints, sizeof(hints));
- /* prefix only with numeric addresses */
- hints.ai_flags |= AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_DGRAM; /* dummy */
+ if (numeric)
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if ((p = strchr(addr, '/')) != NULL) {
+ *p++ = '\0';
+ /* prefix only with numeric addresses */
+ hints.ai_flags |= AI_NUMERICHOST;
+ }
if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) {
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
/* NOTREACHED */
}
- if (res->ai_family == AF_INET && prefix > 32)
- errx(1, "prefix too long for AF_INET");
- else if (res->ai_family == AF_INET6 && prefix > 128)
- errx(1, "prefix too long for AF_INET6");
+ if (p == NULL)
+ return res;
+
+ prefix = strtonum(p, 0, res->ai_family == AF_INET6 ? 128 : 32, &errstr);
+ if (errstr)
+ errx(1, "prefix is %s: %s", errstr, p);
q = prefix >> 3;
r = prefix & 7;
@@ -401,7 +403,8 @@ pfctl_addrprefix(char *addr, struct pf_addr *mask)
(0xff00 >> r) & 0xff;
break;
}
- freeaddrinfo(res);
+
+ return res;
}
void
@@ -411,7 +414,6 @@ pfctl_kill_src_nodes(int dev, int opts)
struct addrinfo *res[2], *resp[2];
struct sockaddr last_src, last_dst;
int killed, sources, dests;
- int ret_ga;
killed = sources = dests = 0;
@@ -421,12 +423,9 @@ pfctl_kill_src_nodes(int dev, int opts)
memset(&last_src, 0xff, sizeof(last_src));
memset(&last_dst, 0xff, sizeof(last_dst));
- pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask);
+ res[0] = pfctl_addrprefix(src_node_kill[0],
+ &psnk.psnk_src.addr.v.a.mask, (opts & PF_OPT_NODNS));
- if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) {
- errx(1, "getaddrinfo: %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;
@@ -453,14 +452,9 @@ pfctl_kill_src_nodes(int dev, int opts)
memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
sizeof(psnk.psnk_dst.addr.v.a.mask));
memset(&last_dst, 0xff, sizeof(last_dst));
- pfctl_addrprefix(src_node_kill[1],
- &psnk.psnk_dst.addr.v.a.mask);
- if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL,
- &res[1]))) {
- errx(1, "getaddrinfo: %s",
- gai_strerror(ret_ga));
- /* NOTREACHED */
- }
+ res[1] = pfctl_addrprefix(src_node_kill[1],
+ &psnk.psnk_dst.addr.v.a.mask,
+ (opts & PF_OPT_NODNS));
for (resp[1] = res[1]; resp[1];
resp[1] = resp[1]->ai_next) {
if (resp[1]->ai_addr == NULL)
@@ -513,7 +507,6 @@ pfctl_net_kill_states(int dev, const char *iface, int opts, int rdomain)
struct addrinfo *res[2], *resp[2];
struct sockaddr last_src, last_dst;
int killed, sources, dests;
- int ret_ga;
killed = sources = dests = 0;
@@ -528,12 +521,9 @@ pfctl_net_kill_states(int dev, const char *iface, int opts, int rdomain)
psk.psk_rdomain = rdomain;
- pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask);
+ res[0] = pfctl_addrprefix(state_kill[0],
+ &psk.psk_src.addr.v.a.mask, (opts & PF_OPT_NODNS));
- if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
- errx(1, "getaddrinfo: %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;
@@ -560,14 +550,9 @@ pfctl_net_kill_states(int dev, const char *iface, int opts, int rdomain)
memset(&psk.psk_dst.addr.v.a.mask, 0xff,
sizeof(psk.psk_dst.addr.v.a.mask));
memset(&last_dst, 0xff, sizeof(last_dst));
- pfctl_addrprefix(state_kill[1],
- &psk.psk_dst.addr.v.a.mask);
- if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
- &res[1]))) {
- errx(1, "getaddrinfo: %s",
- gai_strerror(ret_ga));
- /* NOTREACHED */
- }
+ res[1] = pfctl_addrprefix(state_kill[1],
+ &psk.psk_dst.addr.v.a.mask,
+ (opts & PF_OPT_NODNS));
for (resp[1] = res[1]; resp[1];
resp[1] = resp[1]->ai_next) {
if (resp[1]->ai_addr == NULL)