1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-22 16:42:56 -08:00

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@
This commit is contained in:
claudio 2009-10-26 09:27:58 +00:00
parent 739eccc272
commit 6236702d09
4 changed files with 45 additions and 32 deletions

View File

@ -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);
}
}

View File

@ -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 *);

View File

@ -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);
}

View File

@ -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 *) *