summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/pfkey.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2010-12-09 13:50:42 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2010-12-09 13:50:42 +0000
commitf4cb0a1d48212436bd622ab3febfd0a41bcf80fd (patch)
tree42ad7b30b3d1e9fe3fc7a1e256fb09a394b090ce /usr.sbin/bgpd/pfkey.c
parent6558f0a296d5c2a15cbbe5d1db38a2e0ab4b9e90 (diff)
The PF_KEY socket is like the routing socket. It must be polled all the
time to consume broadcasted messages or the socket gets full and own messages that are needed are lost. This fixes an infinit loop in pfkey_reply that happens when bgpd tcp md5sum is used on a system that also runs a larger IPsec setup. OK henning, lot of patience, debuging and testing by Thomas Boernert
Diffstat (limited to 'usr.sbin/bgpd/pfkey.c')
-rw-r--r--usr.sbin/bgpd/pfkey.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/usr.sbin/bgpd/pfkey.c b/usr.sbin/bgpd/pfkey.c
index 653565ad3b8..30ed4131388 100644
--- a/usr.sbin/bgpd/pfkey.c
+++ b/usr.sbin/bgpd/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.40 2009/12/14 17:38:18 claudio Exp $ */
+/* $OpenBSD: pfkey.c,v 1.41 2010/12/09 13:50:41 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -402,6 +402,33 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
}
int
+pfkey_read(int sd, struct sadb_msg *h)
+{
+ struct sadb_msg hdr;
+
+ if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
+ log_warn("pfkey peek");
+ return (-1);
+ }
+
+ /* XXX: Only one message can be outstanding. */
+ if (hdr.sadb_msg_seq == sadb_msg_seq &&
+ hdr.sadb_msg_pid == pid) {
+ if (h)
+ bcopy(&hdr, h, sizeof(hdr));
+ return (0);
+ }
+
+ /* not ours, discard */
+ if (read(sd, &hdr, sizeof(hdr)) == -1) {
+ log_warn("pfkey read");
+ return (-1);
+ }
+
+ return (1);
+}
+
+int
pfkey_reply(int sd, u_int32_t *spip)
{
struct sadb_msg hdr, *msg;
@@ -409,23 +436,13 @@ pfkey_reply(int sd, u_int32_t *spip)
struct sadb_sa *sa;
u_int8_t *data;
ssize_t len;
+ int rv;
- for (;;) {
- if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
- log_warn("pfkey peek");
+ do {
+ rv = pfkey_read(sd, &hdr);
+ if (rv == -1)
return (-1);
- }
-
- if (hdr.sadb_msg_seq == sadb_msg_seq &&
- hdr.sadb_msg_pid == pid)
- break;
-
- /* not ours, discard */
- if (read(sd, &hdr, sizeof(hdr)) == -1) {
- log_warn("pfkey read");
- return (-1);
- }
- }
+ } while (rv);
if (hdr.sadb_msg_errno != 0) {
errno = hdr.sadb_msg_errno;
@@ -721,11 +738,9 @@ pfkey_init(struct bgpd_sysdep *sysdep)
if (errno == EPROTONOSUPPORT) {
log_warnx("PF_KEY not available, disabling ipsec");
sysdep->no_pfkey = 1;
- return (0);
- } else {
- log_warn("PF_KEY socket");
return (-1);
- }
+ } else
+ fatal("pfkey setup failed");
}
- return (0);
+ return (fd);
}