From f4cb0a1d48212436bd622ab3febfd0a41bcf80fd Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Thu, 9 Dec 2010 13:50:42 +0000 Subject: 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 --- usr.sbin/bgpd/pfkey.c | 57 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 21 deletions(-) (limited to 'usr.sbin/bgpd/pfkey.c') 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 @@ -401,6 +401,33 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, return (0); } +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) { @@ -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); } -- cgit v1.2.3