summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkus <markus@openbsd.org>2014-05-05 18:50:36 +0000
committermarkus <markus@openbsd.org>2014-05-05 18:50:36 +0000
commit3f3558dc779e518c0f4899f55b7551557e8e7820 (patch)
treed4910478b62d3678684807256e536d345d3f0ec3
parentinspired by a cloudflare diff, cleanse old memory when expanding a bignum. (diff)
downloadwireguard-openbsd-3f3558dc779e518c0f4899f55b7551557e8e7820.tar.xz
wireguard-openbsd-3f3558dc779e518c0f4899f55b7551557e8e7820.zip
pfkey is unreliable, so add a select-timeout before MSG_PEEK;
similar code is in isakmpd; ok reyk@
-rw-r--r--sbin/iked/pfkey.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/sbin/iked/pfkey.c b/sbin/iked/pfkey.c
index 9cb9703cff1..892d3d03303 100644
--- a/sbin/iked/pfkey.c
+++ b/sbin/iked/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.32 2014/05/05 16:13:12 markus Exp $ */
+/* $OpenBSD: pfkey.c,v 1.33 2014/05/05 18:50:36 markus Exp $ */
/*
* Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
@@ -43,6 +43,7 @@
#define IOV_CNT 20
#define PFKEYV2_CHUNK sizeof(u_int64_t)
+#define PFKEY_REPLY_TIMEOUT 1000
static u_int32_t sadb_msg_seq = 0;
static u_int sadb_decoupled = 0;
@@ -1085,10 +1086,42 @@ pfkey_reply(int sd, u_int8_t **datap, ssize_t *lenp)
{
struct pfkey_message *pm;
struct sadb_msg hdr;
+ struct timeval tv;
ssize_t len;
u_int8_t *data;
+ fd_set *fds;
+ int n;
for (;;) {
+ /*
+ * We should actually expect the reply to get lost
+ * as PF_KEY is an unreliable service per the specs.
+ * Currently we do this by setting a short timeout,
+ * and if it is not readable in that time, we fail
+ * the read.
+ */
+ n = howmany(sd + 1, NFDBITS);
+ if ((fds = calloc(n, sizeof(fd_mask))) == NULL) {
+ log_warn("%s: calloc(%lu, %lu) failed", __func__,
+ (unsigned long) n,
+ (unsigned long) sizeof(fd_mask));
+ return (-1);
+ }
+ FD_SET(sd, fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = PFKEY_REPLY_TIMEOUT;
+ n = select(sd + 1, fds, 0, 0, &tv);
+ free(fds);
+ if (n == -1) {
+ log_warn("%s: select(%d, fds, 0, 0, &tv) failed",
+ __func__, sd + 1);
+ return (-1);
+ }
+ if (n == 0) {
+ log_warnx("%s: no reply from PF_KEY", __func__);
+ return (-1);
+ }
+
if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
log_warn("%s: short recv", __func__);
return (-1);