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 | |
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')
-rw-r--r-- | usr.sbin/bgpd/pfkey.c | 57 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 20 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 3 |
3 files changed, 53 insertions, 27 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); } diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 770296c5230..79a2b2ef33f 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.314 2010/11/18 12:51:24 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.315 2010/12/09 13:50:41 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -50,7 +50,8 @@ #define PFD_PIPE_ROUTE_CTL 2 #define PFD_SOCK_CTL 3 #define PFD_SOCK_RCTL 4 -#define PFD_LISTENERS_START 5 +#define PFD_SOCK_PFKEY 5 +#define PFD_LISTENERS_START 6 void session_sighdlr(int); int setup_listeners(u_int *); @@ -177,7 +178,7 @@ pid_t session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], int pipe_s2rctl[2]) { - int nfds, timeout; + int nfds, timeout, pfkeysock; unsigned int i, j, idx_peers, idx_listeners, idx_mrts; pid_t pid; u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0; @@ -213,8 +214,7 @@ session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], setproctitle("session engine"); bgpd_process = PROC_SE; - if (pfkey_init(&sysdep) == -1) - fatalx("pfkey setup failed"); + pfkeysock = pfkey_init(&sysdep); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || @@ -376,6 +376,8 @@ session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], pfd[PFD_SOCK_CTL].events = POLLIN; pfd[PFD_SOCK_RCTL].fd = rcsock; pfd[PFD_SOCK_RCTL].events = POLLIN; + pfd[PFD_SOCK_PFKEY].fd = pfkeysock; + pfd[PFD_SOCK_PFKEY].events = POLLIN; i = PFD_LISTENERS_START; TAILQ_FOREACH(la, conf->listen_addrs, entry) { @@ -509,6 +511,14 @@ session_main(int pipe_m2s[2], int pipe_s2r[2], int pipe_m2r[2], ctl_cnt += control_accept(rcsock, 1); } + if (nfds > 0 && pfd[PFD_SOCK_PFKEY].revents & POLLIN) { + nfds--; + if (pfkey_read(pfkeysock, NULL) == -1) { + log_warnx("pfkey_read failed, exiting..."); + session_quit = 1; + } + } + for (j = PFD_LISTENERS_START; nfds > 0 && j < idx_listeners; j++) if (pfd[j].revents & POLLIN) { diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h index 7cc312bf851..2bfa138c944 100644 --- a/usr.sbin/bgpd/session.h +++ b/usr.sbin/bgpd/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.110 2010/11/18 12:51:25 claudio Exp $ */ +/* $OpenBSD: session.h,v 1.111 2010/12/09 13:50:41 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -273,6 +273,7 @@ int control_dispatch_msg(struct pollfd *, u_int *); unsigned int control_accept(int, int); /* pfkey.c */ +int pfkey_read(int, struct sadb_msg *); int pfkey_establish(struct peer *); int pfkey_remove(struct peer *); int pfkey_init(struct bgpd_sysdep *); |