diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-12-09 13:50:42 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-12-09 13:50:42 +0000 |
commit | f4cb0a1d48212436bd622ab3febfd0a41bcf80fd (patch) | |
tree | 42ad7b30b3d1e9fe3fc7a1e256fb09a394b090ce /usr.sbin/bgpd/pfkey.c | |
parent | 6558f0a296d5c2a15cbbe5d1db38a2e0ab4b9e90 (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.c | 57 |
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); } |