diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-10-26 09:27:59 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2009-10-26 09:27:59 +0000 |
commit | ffe97cf2509441d71586f7007e9dcc611c880b76 (patch) | |
tree | 241662a53981ba9563d75ec5f9341b3710f70e47 /usr.sbin/bgpd | |
parent | cd9be4735772653114fdfd639a53fa4c0b876a16 (diff) |
Better error handling when doing mrt dumps (e.g. when there is no more space
on the disk). Before the SE spinned and the RDE may even crash in these events.
Found by Elisa Jasinska. OK henning@
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/mrt.c | 5 | ||||
-rw-r--r-- | usr.sbin/bgpd/mrt.h | 4 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 54 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 14 |
4 files changed, 45 insertions, 32 deletions
diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c index 932fa8d3392..da74d7af86f 100644 --- a/usr.sbin/bgpd/mrt.c +++ b/usr.sbin/bgpd/mrt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.c,v 1.64 2009/07/12 15:36:41 jsg Exp $ */ +/* $OpenBSD: mrt.c,v 1.65 2009/10/26 09:27:58 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -387,7 +387,7 @@ mrt_dump_upcall(struct rib_entry *re, void *ptr) } void -mrt_dump_done(void *ptr) +mrt_done(void *ptr) { struct mrt *mrtbuf = ptr; @@ -541,6 +541,7 @@ mrt_write(struct mrt *mrt) if ((r = buf_write(&mrt->wbuf)) < 0) { log_warn("mrt dump aborted, mrt_write"); mrt_clean(mrt); + mrt_done(mrt); } } diff --git a/usr.sbin/bgpd/mrt.h b/usr.sbin/bgpd/mrt.h index 4f43cd99640..b959afcd352 100644 --- a/usr.sbin/bgpd/mrt.h +++ b/usr.sbin/bgpd/mrt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.h,v 1.23 2009/06/29 12:22:16 claudio Exp $ */ +/* $OpenBSD: mrt.h,v 1.24 2009/10/26 09:27:58 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -303,7 +303,7 @@ void mrt_dump_state(struct mrt *, u_int16_t, u_int16_t, struct peer *); void mrt_clear_seq(void); void mrt_dump_upcall(struct rib_entry *, void *); -void mrt_dump_done(void *); +void mrt_done(void *); void mrt_write(struct mrt *); void mrt_clean(struct mrt *); void mrt_init(struct imsgbuf *, struct imsgbuf *); diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 0a1dbcd2720..7c99313bbe3 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.270 2009/10/12 15:19:30 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.271 2009/10/26 09:27:58 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -121,11 +121,12 @@ struct rde_dump_ctx { }; struct rde_mrt_ctx { - struct mrt mrt; - struct rib_context ribctx; + struct mrt mrt; + struct rib_context ribctx; + LIST_ENTRY(rde_mrt_ctx) entry; }; -struct mrt_head rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts); +LIST_HEAD(, rde_mrt_ctx) rde_mrts = LIST_HEAD_INITIALIZER(rde_mrts); u_int rde_mrt_cnt; void @@ -159,7 +160,8 @@ rde_main(struct bgpd_config *config, struct peer *peer_l, struct filter_set *set; struct nexthop *nh; struct rde_rib *rr; - struct mrt *mrt, *xmrt; + struct rde_mrt_ctx *mctx, *xmctx; + struct mrt *mrt; void *newp; u_int pfd_elms = 0, i, j; int timeout; @@ -288,9 +290,9 @@ rde_main(struct bgpd_config *config, struct peer *peer_l, timeout = 0; i = PFD_PIPE_COUNT; - LIST_FOREACH(mrt, &rde_mrts, entry) { - if (mrt->wbuf.queued) { - pfd[i].fd = mrt->wbuf.fd; + LIST_FOREACH(mctx, &rde_mrts, entry) { + if (mctx->mrt.wbuf.queued) { + pfd[i].fd = mctx->mrt.wbuf.fd; pfd[i].events = POLLOUT; i++; } @@ -326,20 +328,21 @@ rde_main(struct bgpd_config *config, struct peer *peer_l, if (pfd[PFD_PIPE_SESSION_CTL].revents & POLLIN) rde_dispatch_imsg_session(ibuf_se_ctl); - for (j = PFD_PIPE_COUNT, mrt = LIST_FIRST(&rde_mrts); - j < i && mrt != 0; j++) { - xmrt = LIST_NEXT(mrt, entry); - if (pfd[j].fd == mrt->wbuf.fd && + for (j = PFD_PIPE_COUNT, mctx = LIST_FIRST(&rde_mrts); + j < i && mctx != 0; j++) { + xmctx = LIST_NEXT(mctx, entry); + if (pfd[j].fd == mctx->mrt.wbuf.fd && pfd[j].revents & POLLOUT) - mrt_write(mrt); - if (mrt->wbuf.queued == 0 && - mrt->state == MRT_STATE_REMOVE) { - close(mrt->wbuf.fd); - LIST_REMOVE(mrt, entry); - free(mrt); + mrt_write(&mctx->mrt); + if (mctx->mrt.wbuf.queued == 0 && + mctx->mrt.state == MRT_STATE_REMOVE) { + close(mctx->mrt.wbuf.fd); + LIST_REMOVE(&mctx->ribctx, entry); + LIST_REMOVE(mctx, entry); + free(mctx); rde_mrt_cnt--; } - mrt = xmrt; + mctx = xmctx; } rde_update_queue_runner(); @@ -352,10 +355,11 @@ rde_main(struct bgpd_config *config, struct peer *peer_l, if (debug) rde_shutdown(); - while ((mrt = LIST_FIRST(&rde_mrts)) != NULL) { - msgbuf_clear(&mrt->wbuf); - close(mrt->wbuf.fd); - LIST_REMOVE(mrt, entry); + while ((mctx = LIST_FIRST(&rde_mrts)) != NULL) { + msgbuf_clear(&mctx->mrt.wbuf); + close(mctx->mrt.wbuf.fd); + LIST_REMOVE(&mctx->ribctx, entry); + LIST_REMOVE(mctx, entry); free(mrt); } @@ -2030,10 +2034,10 @@ rde_dump_mrt_new(struct mrt *mrt, pid_t pid, int fd) ctx->ribctx.ctx_count = RDE_RUNNER_ROUNDS; ctx->ribctx.ctx_rib = &ribs[id]; ctx->ribctx.ctx_upcall = mrt_dump_upcall; - ctx->ribctx.ctx_done = mrt_dump_done; + ctx->ribctx.ctx_done = mrt_done; ctx->ribctx.ctx_arg = &ctx->mrt; ctx->ribctx.ctx_af = AF_UNSPEC; - LIST_INSERT_HEAD(&rde_mrts, &ctx->mrt, entry); + LIST_INSERT_HEAD(&rde_mrts, ctx, entry); rde_mrt_cnt++; rib_dump_r(&ctx->ribctx); } diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 68bf9d53985..3ed0195cfcf 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.298 2009/09/22 14:07:53 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.299 2009/10/26 09:27:58 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -189,7 +189,7 @@ session_main(struct bgpd_config *config, struct peer *cpeers, struct passwd *pw; struct peer *p, **peer_l = NULL, *last, *next; struct network *net; - struct mrt *m, **mrt_l = NULL; + struct mrt *m, *xm, **mrt_l = NULL; struct filter_rule *r; struct pollfd *pfd = NULL; struct ctl_conn *ctl_conn; @@ -345,9 +345,17 @@ session_main(struct bgpd_config *config, struct peer *cpeers, } mrt_cnt = 0; - LIST_FOREACH(m, &mrthead, entry) + for (m = LIST_FIRST(&mrthead); m != NULL; m = xm) { + xm = LIST_NEXT(m, entry); + if (m->state == MRT_STATE_REMOVE) { + mrt_clean(m); + LIST_REMOVE(m, entry); + free(m); + continue; + } if (m->wbuf.queued) mrt_cnt++; + } if (mrt_cnt > mrt_l_elms) { if ((newp = realloc(mrt_l, sizeof(struct mrt *) * |