summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/bgpd.c45
-rw-r--r--usr.sbin/bgpd/bgpd.h9
-rw-r--r--usr.sbin/bgpd/buffer.c3
-rw-r--r--usr.sbin/bgpd/mrt.c506
-rw-r--r--usr.sbin/bgpd/mrt.h70
-rw-r--r--usr.sbin/bgpd/parse.y34
-rw-r--r--usr.sbin/bgpd/printconf.c17
-rw-r--r--usr.sbin/bgpd/rde.c85
-rw-r--r--usr.sbin/bgpd/session.c157
9 files changed, 435 insertions, 491 deletions
diff --git a/usr.sbin/bgpd/bgpd.c b/usr.sbin/bgpd/bgpd.c
index b66996e6ce7..01ff6cd1a42 100644
--- a/usr.sbin/bgpd/bgpd.c
+++ b/usr.sbin/bgpd/bgpd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.c,v 1.97 2004/06/20 18:35:11 henning Exp $ */
+/* $OpenBSD: bgpd.c,v 1.98 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -83,11 +83,11 @@ usage(void)
exit(1);
}
-#define POLL_MAX 8
#define PFD_PIPE_SESSION 0
#define PFD_PIPE_ROUTE 1
#define PFD_SOCK_ROUTE 2
-#define PFD_MRT_START 3
+#define POLL_MAX 3
+#define MAX_TIMEOUT 3600
int
main(int argc, char *argv[])
@@ -99,13 +99,13 @@ main(int argc, char *argv[])
struct filter_head *rules_l;
struct network *net;
struct filter_rule *r;
- struct mrt *(mrt[POLL_MAX]), *m;
+ struct mrt *m;
struct listen_addr *la;
struct pollfd pfd[POLL_MAX];
pid_t io_pid = 0, rde_pid = 0, pid;
char *conffile;
int debug = 0;
- int ch, i, j, nfds, timeout;
+ int ch, nfds, timeout;
int pipe_m2s[2];
int pipe_m2r[2];
int pipe_s2r[2];
@@ -236,6 +236,8 @@ main(int argc, char *argv[])
free(la);
}
+ mrt_reconfigure(&mrt_l);
+
while (quit == 0) {
pfd[PFD_PIPE_SESSION].fd = ibuf_se.fd;
pfd[PFD_PIPE_SESSION].events = POLLIN;
@@ -247,10 +249,12 @@ main(int argc, char *argv[])
pfd[PFD_PIPE_ROUTE].events |= POLLOUT;
pfd[PFD_SOCK_ROUTE].fd = rfd;
pfd[PFD_SOCK_ROUTE].events = POLLIN;
- i = PFD_MRT_START;
- i = mrt_select(&mrt_l, pfd, mrt, i, POLL_MAX, &timeout);
- if ((nfds = poll(pfd, i, INFTIM)) == -1)
+ timeout = mrt_timeout(&mrt_l);
+ if (timeout > MAX_TIMEOUT)
+ timeout = MAX_TIMEOUT;
+
+ if ((nfds = poll(pfd, POLL_MAX, timeout * 1000)) == -1)
if (errno != EINTR) {
log_warn("poll error");
quit = 1;
@@ -288,14 +292,6 @@ main(int argc, char *argv[])
quit = 1;
}
- for (j = PFD_MRT_START; j < i && nfds > 0 ; j++) {
- if (pfd[j].revents & POLLOUT) {
- if (mrt_write(mrt[j]) < 0) {
- log_warn("mrt write error");
- }
- }
- }
-
if (reconfig) {
log_info("rereading config");
reconfigure(conffile, &conf, &mrt_l, &peer_l, rules_l);
@@ -329,7 +325,7 @@ main(int argc, char *argv[])
free(p);
}
while ((m = LIST_FIRST(&mrt_l)) != NULL) {
- LIST_REMOVE(m, list);
+ LIST_REMOVE(m, entry);
free(m);
}
@@ -424,6 +420,8 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l,
imsg_compose(&ibuf_rde, IMSG_RECONF_DONE, 0, NULL, 0) == -1)
return (-1);
+ /* mrt changes can be sent out of bound */
+ mrt_reconfigure(mrt_l);
return (0);
}
@@ -431,6 +429,7 @@ int
dispatch_imsg(struct imsgbuf *ibuf, int idx, struct mrt_head *mrt_l)
{
struct imsg imsg;
+ struct mrt mrt;
int n;
if ((n = imsg_read(ibuf)) == -1)
@@ -449,10 +448,14 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx, struct mrt_head *mrt_l)
break;
switch (imsg.hdr.type) {
- case IMSG_MRT_MSG:
- case IMSG_MRT_END:
- if (mrt_queue(mrt_l, &imsg) == -1)
- log_warnx("mrt_queue failed.");
+ case IMSG_MRT_CLOSE:
+ if (imsg.hdr.len != IMSG_HEADER_SIZE +
+ sizeof(struct mrt)) {
+ log_warnx("wrong imsg len");
+ break;
+ }
+ memcpy(&mrt, imsg.data, sizeof(struct mrt));
+ mrt_close(mrt_get(mrt_l, &mrt));
break;
case IMSG_KROUTE_CHANGE:
if (idx != PFD_PIPE_ROUTE)
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 0823e88199d..8b7f35a3a02 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.132 2004/06/25 20:08:46 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.133 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -264,9 +264,9 @@ enum imsg_type {
IMSG_UPDATE_ERR,
IMSG_SESSION_UP,
IMSG_SESSION_DOWN,
- IMSG_MRT_REQ,
- IMSG_MRT_MSG,
- IMSG_MRT_END,
+ IMSG_MRT_OPEN,
+ IMSG_MRT_REOPEN,
+ IMSG_MRT_CLOSE,
IMSG_KROUTE_CHANGE,
IMSG_KROUTE_DELETE,
IMSG_NEXTHOP_ADD,
@@ -551,6 +551,7 @@ struct buf *buf_open(ssize_t);
int buf_add(struct buf *, void *, ssize_t);
void *buf_reserve(struct buf *, ssize_t);
int buf_close(struct msgbuf *, struct buf *);
+int buf_write(int, struct buf *);
void buf_free(struct buf *);
void msgbuf_init(struct msgbuf *);
void msgbuf_clear(struct msgbuf *);
diff --git a/usr.sbin/bgpd/buffer.c b/usr.sbin/bgpd/buffer.c
index a47ced7b15d..6887b793a59 100644
--- a/usr.sbin/bgpd/buffer.c
+++ b/usr.sbin/bgpd/buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: buffer.c,v 1.21 2004/06/20 18:35:12 henning Exp $ */
+/* $OpenBSD: buffer.c,v 1.22 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -29,7 +29,6 @@
#include "bgpd.h"
-int buf_write(int, struct buf *);
void buf_enqueue(struct msgbuf *, struct buf *);
void buf_dequeue(struct msgbuf *, struct buf *);
diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c
index 121800b6eef..e68fccc95d8 100644
--- a/usr.sbin/bgpd/mrt.c
+++ b/usr.sbin/bgpd/mrt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.c,v 1.32 2004/06/22 20:28:58 claudio Exp $ */
+/* $OpenBSD: mrt.c,v 1.33 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -34,17 +34,17 @@
static u_int16_t mrt_attr_length(struct attr_flags *);
static int mrt_attr_dump(void *, u_int16_t, struct attr_flags *);
-static int mrt_dump_entry(struct mrt_config *, struct prefix *,
+static int mrt_dump_entry(struct mrt *, struct prefix *,
u_int16_t, struct peer_config *);
static int mrt_dump_header(struct buf *, u_int16_t, u_int16_t,
u_int32_t);
-static int mrt_open(struct mrt *);
+static int mrt_open(struct mrt *, time_t);
#define DUMP_BYTE(x, b) \
do { \
u_char t = (b); \
- if (imsg_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump1: imsg_add error"); \
+ if (buf_add((x), &t, sizeof(t)) == -1) { \
+ log_warnx("mrt_dump1: buf_add error"); \
return (-1); \
} \
} while (0)
@@ -53,8 +53,8 @@ static int mrt_open(struct mrt *);
do { \
u_int16_t t; \
t = htons((s)); \
- if (imsg_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump2: imsg_add error"); \
+ if (buf_add((x), &t, sizeof(t)) == -1) { \
+ log_warnx("mrt_dump2: buf_add error"); \
return (-1); \
} \
} while (0)
@@ -63,8 +63,8 @@ static int mrt_open(struct mrt *);
do { \
u_int32_t t; \
t = htonl((l)); \
- if (imsg_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump3: imsg_add error"); \
+ if (buf_add((x), &t, sizeof(t)) == -1) { \
+ log_warnx("mrt_dump3: buf_add error"); \
return (-1); \
} \
} while (0)
@@ -72,14 +72,14 @@ static int mrt_open(struct mrt *);
#define DUMP_NLONG(x, l) \
do { \
u_int32_t t = (l); \
- if (imsg_add((x), &t, sizeof(t)) == -1) { \
- log_warnx("mrt_dump4: imsg_add error"); \
+ if (buf_add((x), &t, sizeof(t)) == -1) { \
+ log_warnx("mrt_dump4: buf_add error"); \
return (-1); \
} \
} while (0)
int
-mrt_dump_bgp_msg(struct mrt_config *mrt, void *pkg, u_int16_t pkglen,
+mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
struct peer_config *peer, struct bgpd_config *bgp)
{
struct buf *buf;
@@ -87,15 +87,14 @@ mrt_dump_bgp_msg(struct mrt_config *mrt, void *pkg, u_int16_t pkglen,
len = pkglen + MRT_BGP4MP_HEADER_SIZE;
- if ((buf = imsg_create(mrt->ibuf, IMSG_MRT_MSG, mrt->id,
- len + MRT_HEADER_SIZE)) == NULL) {
- log_warnx("mrt_dump_bgp_msg: imsg_open error");
+ if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) {
+ log_warnx("mrt_dump_bgp_msg: buf_open error");
return (-1);
}
if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE,
len) == -1) {
- log_warnx("mrt_dump_bgp_msg: imsg_add error");
+ log_warnx("mrt_dump_bgp_msg: buf_add error");
return (-1);
}
@@ -106,21 +105,19 @@ mrt_dump_bgp_msg(struct mrt_config *mrt, void *pkg, u_int16_t pkglen,
DUMP_NLONG(buf, peer->local_addr.v4.s_addr);
DUMP_NLONG(buf, peer->remote_addr.v4.s_addr);
- if (imsg_add(buf, pkg, pkglen) == -1) {
- log_warnx("mrt_dump_bgp_msg: imsg_add error");
+ if (buf_add(buf, pkg, pkglen) == -1) {
+ log_warnx("mrt_dump_bgp_msg: buf_add error");
return (-1);
}
- if ((imsg_close(mrt->ibuf, buf)) == -1) {
- log_warnx("mrt_dump_bgp_msg: imsg_close error");
- return (-1);
- }
+ TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry);
+ mrt->queued++;
return (len + MRT_HEADER_SIZE);
}
int
-mrt_dump_state(struct mrt_config *mrt, u_int16_t old_state, u_int16_t new_state,
+mrt_dump_state(struct mrt *mrt, u_int16_t old_state, u_int16_t new_state,
struct peer_config *peer, struct bgpd_config *bgp)
{
struct buf *buf;
@@ -128,15 +125,14 @@ mrt_dump_state(struct mrt_config *mrt, u_int16_t old_state, u_int16_t new_state,
len = 4 + MRT_BGP4MP_HEADER_SIZE;
- if ((buf = imsg_create(mrt->ibuf, IMSG_MRT_MSG, mrt->id,
- len + MRT_HEADER_SIZE)) == NULL) {
- log_warnx("mrt_dump_bgp_state: imsg_open error");
+ if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) {
+ log_warnx("mrt_dump_bgp_state: buf_open error");
return (-1);
}
if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE,
len) == -1) {
- log_warnx("mrt_dump_bgp_state: imsg_add error");
+ log_warnx("mrt_dump_bgp_state: buf_add error");
return (-1);
}
@@ -150,10 +146,8 @@ mrt_dump_state(struct mrt_config *mrt, u_int16_t old_state, u_int16_t new_state,
DUMP_SHORT(buf, old_state);
DUMP_SHORT(buf, new_state);
- if ((imsg_close(mrt->ibuf, buf)) == -1) {
- log_warnx("mrt_dump_bgp_state: imsg_close error");
- return (-1);
- }
+ TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry);
+ mrt->queued++;
return (len + MRT_HEADER_SIZE);
}
@@ -232,7 +226,7 @@ mrt_attr_dump(void *p, u_int16_t len, struct attr_flags *a)
}
static int
-mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum,
+mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum,
struct peer_config *peer)
{
struct buf *buf;
@@ -244,9 +238,8 @@ mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum,
len = MRT_DUMP_HEADER_SIZE + attr_len;
pt_getaddr(p->prefix, &addr);
- if ((buf = imsg_create(mrt->ibuf, IMSG_MRT_MSG, mrt->id,
- len + MRT_HEADER_SIZE)) == NULL) {
- log_warnx("mrt_dump_entry: imsg_open error");
+ if ((buf = buf_open(len + MRT_HEADER_SIZE)) == NULL) {
+ log_warnx("mrt_dump_entry: buf_open error");
return (-1);
}
@@ -277,10 +270,8 @@ mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum,
return (-1);
}
- if ((imsg_close(mrt->ibuf, buf)) == -1) {
- log_warnx("mrt_dump_bgp_state: imsg_close error");
- return (-1);
- }
+ TAILQ_INSERT_TAIL(&mrt->bufs, buf, entry);
+ mrt->queued++;
return (len + MRT_HEADER_SIZE);
}
@@ -296,7 +287,7 @@ mrt_clear_seq(void)
void
mrt_dump_upcall(struct pt_entry *pt, void *ptr)
{
- struct mrt_config *mrtbuf = ptr;
+ struct mrt *mrtbuf = ptr;
struct prefix *p;
/*
@@ -325,6 +316,39 @@ mrt_dump_header(struct buf *buf, u_int16_t type, u_int16_t subtype,
return (0);
}
+int
+mrt_write(struct mrt *mrt)
+{
+ struct buf *b;
+ int r = 0;
+
+ while ((b = TAILQ_FIRST(&mrt->bufs)) &&
+ (r = buf_write(mrt->fd, b)) == 1) {
+ TAILQ_REMOVE(&mrt->bufs, b, entry);
+ mrt->queued--;
+ buf_free(b);
+ }
+ if (r == -1) {
+ log_warn("mrt dump write");
+ mrt_clean(mrt);
+ return (-1);
+ }
+ return (0);
+}
+
+void
+mrt_clean(struct mrt *mrt)
+{
+ struct buf *b;
+
+ close(mrt->fd);
+ while ((b = TAILQ_FIRST(&mrt->bufs))) {
+ TAILQ_REMOVE(&mrt->bufs, b, entry);
+ buf_free(b);
+ }
+ mrt->queued = 0;
+}
+
static struct imsgbuf *mrt_imsgbuf[2];
void
@@ -334,339 +358,147 @@ mrt_init(struct imsgbuf *rde, struct imsgbuf *se)
mrt_imsgbuf[1] = se;
}
-static int
-mrt_open(struct mrt *mrt)
+int
+mrt_open(struct mrt *mrt, time_t now)
{
- time_t now;
+ enum imsg_type type;
+ int i;
- now = time(NULL);
- if (strftime(mrt->file, sizeof(mrt->file), mrt->name,
- localtime(&now)) == 0) {
+ mrt_close(mrt);
+ if (strftime(MRT2MC(mrt)->file, sizeof(MRT2MC(mrt)->file),
+ MRT2MC(mrt)->name, localtime(&now)) == 0) {
log_warnx("mrt_open: strftime conversion failed");
- mrt->msgbuf.fd = -1;
- return (0);
+ mrt->fd = -1;
+ return (-1);
}
- mrt->msgbuf.fd = open(mrt->file,
+ mrt->fd = open(MRT2MC(mrt)->file,
O_WRONLY|O_NONBLOCK|O_CREAT|O_TRUNC, 0644);
- if (mrt->msgbuf.fd == -1) {
- log_warnx("mrt_open %s: %s",
- mrt->file, strerror(errno));
- return (0);
+ if (mrt->fd == -1) {
+ log_warn("mrt_open %s", MRT2MC(mrt)->file);
+ return (1);
}
- return (1);
-}
-static int
-mrt_close(struct mrt *mrt)
-{
- /*
- * close the mrt filedescriptor but first ensure that the last
- * mrt message was written correctly. If not mrt_write needs to do
- * that the next time called.
- * To ensure this we need to fiddle around with internal msgbuf stuff.
- */
- if (msgbuf_unbounded(&mrt->msgbuf))
- return (0);
+ if (MRT2MC(mrt)->state == MRT_STATE_OPEN)
+ type = IMSG_MRT_OPEN;
+ else
+ type = IMSG_MRT_REOPEN;
- if (mrt->msgbuf.fd != -1) {
- close(mrt->msgbuf.fd);
- mrt->msgbuf.fd = -1;
- }
+ i = mrt->type == MRT_TABLE_DUMP ? 0 : 1;
+
+ if (imsg_compose_fdpass(mrt_imsgbuf[i], type, mrt->fd,
+ mrt, sizeof(struct mrt)) == -1)
+ log_warn("mrt_close");
return (1);
}
void
-mrt_abort(struct mrt *mrt)
+mrt_close(struct mrt *mrt)
{
+ if (mrt == NULL)
+ return;
/*
- * something failed horribly. Stop all dumping and go back to start
- * position. Retry after MRT_MIN_RETRY or ReopenTimerInterval. Which-
- * ever is bigger.
+ * this function is normaly called twice. First because of a imsg
+ * form the child to inform the parent to close the fd. The second time
+ * it is called after reconfigure when the mrt file gets removed.
+ * In that case the parent must inform the child to close and remove
+ * this mrt dump descriptor.
*/
- msgbuf_clear(&mrt->msgbuf);
- mrt_close(mrt);
- mrt->state = MRT_STATE_STOPPED;
-
- if (MRT_MIN_RETRY > mrt->ReopenTimerInterval)
- mrt->ReopenTimer = MRT_MIN_RETRY + time(NULL);
- else
- mrt->ReopenTimer = mrt->ReopenTimerInterval + time(NULL);
+ if (MRT2MC(mrt)->state == MRT_STATE_REMOVE)
+ if (imsg_compose(
+ mrt_imsgbuf[mrt->type == MRT_TABLE_DUMP ? 0 : 1],
+ IMSG_MRT_CLOSE, 0, mrt, sizeof(struct mrt)) == -1)
+ log_warn("mrt_close");
+
+ if (mrt->fd == -1)
+ return;
+ close(mrt->fd);
+ mrt->fd = -1;
}
int
-mrt_queue(struct mrt_head *mrtc, struct imsg *imsg)
+mrt_timeout(struct mrt_head *mrt)
{
- struct buf *wbuf;
struct mrt *m;
- ssize_t len;
- int n;
-
- if (imsg->hdr.type != IMSG_MRT_MSG && imsg->hdr.type != IMSG_MRT_END)
- return (-1);
-
- LIST_FOREACH(m, mrtc, list) {
- if (m->conf.id != imsg->hdr.peerid)
- continue;
- if (m->state != MRT_STATE_RUNNING &&
- m->state != MRT_STATE_REOPEN)
- return (0);
-
- if (imsg->hdr.type == IMSG_MRT_END) {
- m->state = MRT_STATE_CLOSE;
- return (0);
- }
-
- len = imsg->hdr.len - IMSG_HEADER_SIZE;
- wbuf = buf_open(len);
- if (wbuf == NULL)
- return (-1);
- if (buf_add(wbuf, imsg->data, len) == -1) {
- buf_free(wbuf);
- return (-1);
- }
- if ((n = buf_close(&m->msgbuf, wbuf)) < 0) {
- buf_free(wbuf);
- return (-1);
- }
- return (n);
- }
- return (0);
-}
-
-int
-mrt_write(struct mrt *mrt)
-{
- int r;
+ time_t now;
+ int timeout = MRT_MAX_TIMEOUT;
- if (mrt->state == MRT_STATE_REOPEN ||
- mrt->state == MRT_STATE_REMOVE)
- r = msgbuf_writebound(&mrt->msgbuf);
- else
- r = msgbuf_write(&mrt->msgbuf);
-
- switch (r) {
- case 1:
- /* only msgbuf_writebound returns 1 */
- break;
- case 0:
- if (mrt->state == MRT_STATE_CLOSE && mrt->msgbuf.queued == 0) {
- if (mrt_close(mrt) != 1) {
- log_warnx("mrt_write: mrt_close failed");
- mrt_abort(mrt);
- return (0);
+ now = time(NULL);
+ LIST_FOREACH(m, mrt, entry) {
+ if (MRT2MC(m)->state == MRT_STATE_RUNNING &&
+ MRT2MC(m)->ReopenTimerInterval != 0) {
+ if (MRT2MC(m)->ReopenTimer <= now) {
+ mrt_open(m, now);
+ MRT2MC(m)->ReopenTimer =
+ now + MRT2MC(m)->ReopenTimerInterval;
}
- mrt->state = MRT_STATE_STOPPED;
- }
- return (0);
- case -1:
- log_warnx("mrt_write: msgbuf_write: %s",
- strerror(errno));
- mrt_abort(mrt);
- return (0);
- case -2:
- log_warnx("mrt_write: msgbuf_write: %s",
- "connection closed");
- mrt_abort(mrt);
- return (0);
- default:
- fatalx("mrt_write: unexpected retval from msgbuf_write");
- }
-
- if (mrt_close(mrt) != 1) {
- log_warnx("mrt_write: mrt_close failed");
- mrt_abort(mrt);
- return (0);
- }
-
- switch (mrt->state) {
- case MRT_STATE_REMOVE:
- /*
- * Remove request: free all left buffers and
- * remove the descriptor.
- */
- msgbuf_clear(&mrt->msgbuf);
- LIST_REMOVE(mrt, list);
- free(mrt);
- return (0);
- case MRT_STATE_REOPEN:
- if (mrt_open(mrt) == 0) {
- mrt_abort(mrt);
- return (0);
- } else {
- if (mrt->ReopenTimerInterval != 0)
- mrt->ReopenTimer = time(NULL) +
- mrt->ReopenTimerInterval;
- mrt->state = MRT_STATE_RUNNING;
+ if (MRT2MC(m)->ReopenTimer - now < timeout)
+ timeout = MRT2MC(m)->ReopenTimer - now;
}
- break;
- default:
- break;
}
- return (1);
+ return (timeout > 0 ? timeout : 0);
}
-int
-mrt_select(struct mrt_head *mc, struct pollfd *pfd, struct mrt **mrt,
- int start, int size, int *timeout)
+void
+mrt_reconfigure(struct mrt_head *mrt)
{
struct mrt *m, *xm;
time_t now;
- int t;
now = time(NULL);
- for (m = LIST_FIRST(mc); m != NULL; m = xm) {
- xm = LIST_NEXT(m, list);
- if (m->state == MRT_STATE_TOREMOVE) {
- imsg_compose(m->ibuf, IMSG_MRT_END, 0,
- &m->conf, sizeof(m->conf));
- if (mrt_close(m) == 0) {
- m->state = MRT_STATE_REMOVE;
- m->ReopenTimer = 0;
- } else {
- msgbuf_clear(&m->msgbuf);
- LIST_REMOVE(m, list);
- free(m);
+ for (m = LIST_FIRST(mrt); m != NULL; m = xm) {
+ xm = LIST_NEXT(m, entry);
+ if (MRT2MC(m)->state == MRT_STATE_OPEN ||
+ MRT2MC(m)->state == MRT_STATE_REOPEN) {
+ if (mrt_open(m, now) == -1)
continue;
- }
- }
- if (m->state == MRT_STATE_OPEN) {
- switch (m->conf.type) {
- case MRT_TABLE_DUMP:
- m->ibuf = mrt_imsgbuf[0];
- break;
- case MRT_ALL_IN:
- case MRT_ALL_OUT:
- case MRT_UPDATE_IN:
- case MRT_UPDATE_OUT:
- m->ibuf = mrt_imsgbuf[1];
- break;
- default:
- continue;
- }
- if (mrt_open(m) == 0) {
- mrt_abort(m);
- t = m->ReopenTimer - now;
- if (*timeout > t)
- *timeout = t;
- continue;
- }
- if (m->ReopenTimerInterval != 0)
- m->ReopenTimer = now + m->ReopenTimerInterval;
- m->state = MRT_STATE_RUNNING;
- imsg_compose(m->ibuf, IMSG_MRT_REQ, 0,
- &m->conf, sizeof(m->conf));
- }
- if (m->state == MRT_STATE_REOPEN) {
- if (mrt_close(m) == 0) {
- m->state = MRT_STATE_REOPEN;
- continue;
- }
- if (mrt_open(m) == 0) {
- mrt_abort(m);
- t = m->ReopenTimer - now;
- if (*timeout > t)
- *timeout = t;
- continue;
- }
- if (m->ReopenTimerInterval != 0)
- m->ReopenTimer = now + m->ReopenTimerInterval;
- m->state = MRT_STATE_RUNNING;
- }
- if (m->ReopenTimer != 0) {
- t = m->ReopenTimer - now;
- if (t <= 0 && (m->state == MRT_STATE_RUNNING ||
- m->state == MRT_STATE_STOPPED)) {
- if (m->state == MRT_STATE_RUNNING) {
- /* reopen file */
- if (mrt_close(m) == 0) {
- m->state = MRT_STATE_REOPEN;
- continue;
- }
- }
- if (mrt_open(m) == 0) {
- mrt_abort(m);
- t = m->ReopenTimer - now;
- if (*timeout > t)
- *timeout = t;
- continue;
- }
- if (m->conf.type == MRT_TABLE_DUMP &&
- m->state == MRT_STATE_STOPPED) {
- imsg_compose(mrt_imsgbuf[0],
- IMSG_MRT_REQ, 0,
- &m->conf, sizeof(m->conf));
- }
-
- m->state = MRT_STATE_RUNNING;
- if (m->ReopenTimerInterval != 0) {
- m->ReopenTimer = now +
- m->ReopenTimerInterval;
- if (*timeout > m->ReopenTimerInterval)
- *timeout = t;
- }
- }
+ if (MRT2MC(m)->ReopenTimerInterval != 0)
+ MRT2MC(m)->ReopenTimer =
+ now + MRT2MC(m)->ReopenTimerInterval;
+ MRT2MC(m)->state = MRT_STATE_RUNNING;
}
- if (m->msgbuf.queued > 0) {
- if (m->msgbuf.fd == -1 ||
- m->state == MRT_STATE_STOPPED) {
- log_warnx("mrt_select: orphaned buffer");
- mrt_abort(m);
- continue;
- }
- if (start < size) {
- pfd[start].fd = m->msgbuf.fd;
- pfd[start].events = POLLOUT;
- mrt[start++] = m;
- }
+ if (MRT2MC(m)->state == MRT_STATE_REMOVE) {
+ mrt_close(m);
+ LIST_REMOVE(m, entry);
+ free(m);
+ continue;
}
}
- return (start);
}
-int
+void
mrt_handler(struct mrt_head *mrt)
{
struct mrt *m;
time_t now;
now = time(NULL);
- LIST_FOREACH(m, mrt, list) {
- if (m->state == MRT_STATE_RUNNING)
- m->state = MRT_STATE_REOPEN;
- if (m->conf.type == MRT_TABLE_DUMP) {
- if (m->state == MRT_STATE_STOPPED) {
- if (mrt_open(m) == 0) {
- mrt_abort(m);
- break;
- }
- imsg_compose(mrt_imsgbuf[0], IMSG_MRT_REQ, 0,
- &m->conf, sizeof(m->conf));
- m->state = MRT_STATE_RUNNING;
- }
+ LIST_FOREACH(m, mrt, entry) {
+ if (MRT2MC(m)->state == MRT_STATE_RUNNING &&
+ (MRT2MC(m)->ReopenTimerInterval != 0 ||
+ m->type == MRT_TABLE_DUMP)) {
+ if (mrt_open(m, now) == -1)
+ continue;
+ MRT2MC(m)->ReopenTimer =
+ now + MRT2MC(m)->ReopenTimerInterval;
}
- if (m->ReopenTimerInterval != 0)
- m->ReopenTimer = now + m->ReopenTimerInterval;
}
- return (0);
}
-static u_int32_t max_id = 1;
-
-static struct mrt *
-getconf(struct mrt_head *c, struct mrt *m)
+struct mrt *
+mrt_get(struct mrt_head *c, struct mrt *m)
{
struct mrt *t;
- LIST_FOREACH(t, c, list) {
- if (t->conf.type != m->conf.type)
+ LIST_FOREACH(t, c, entry) {
+ if (t->type != m->type)
continue;
- if (t->conf.type == MRT_TABLE_DUMP)
- return t;
- if (t->conf.peer_id == m->conf.peer_id &&
- t->conf.group_id == m->conf.group_id)
- return t;
+ if (t->type == MRT_TABLE_DUMP)
+ return (t);
+ if (t->peer_id == m->peer_id &&
+ t->group_id == m->group_id)
+ return (t);
}
return (NULL);
}
@@ -676,33 +508,35 @@ mrt_mergeconfig(struct mrt_head *xconf, struct mrt_head *nconf)
{
struct mrt *m, *xm;
- LIST_FOREACH(m, nconf, list)
- if ((xm = getconf(xconf, m)) == NULL) {
+ LIST_FOREACH(m, nconf, entry) {
+ if ((xm = mrt_get(xconf, m)) == NULL) {
/* NEW */
- if ((xm = calloc(1, sizeof(struct mrt))) == NULL)
+ if ((xm = calloc(1, sizeof(struct mrt_config))) == NULL)
fatal("mrt_mergeconfig");
- memcpy(xm, m, sizeof(struct mrt));
- msgbuf_init(&xm->msgbuf);
- xm->conf.id = max_id++;
- xm->state = MRT_STATE_OPEN;
- LIST_INSERT_HEAD(xconf, xm, list);
+ memcpy(xm, m, sizeof(struct mrt_config));
+ xm->fd = -1;
+ MRT2MC(xm)->state = MRT_STATE_OPEN;
+ LIST_INSERT_HEAD(xconf, xm, entry);
} else {
/* MERGE */
- if (strlcpy(xm->name, m->name, sizeof(xm->name)) >=
- sizeof(xm->name))
+ if (strlcpy(MRT2MC(xm)->name, MRT2MC(xm)->name,
+ sizeof(MRT2MC(xm)->name)) >=
+ sizeof(MRT2MC(xm)->name))
fatalx("mrt_mergeconfig: strlcpy");
- xm->ReopenTimerInterval = m->ReopenTimerInterval;
- xm->state = MRT_STATE_REOPEN;
+ MRT2MC(xm)->ReopenTimerInterval =
+ MRT2MC(m)->ReopenTimerInterval;
+ MRT2MC(xm)->state = MRT_STATE_REOPEN;
}
+ }
- LIST_FOREACH(xm, xconf, list)
- if (getconf(nconf, xm) == NULL)
+ LIST_FOREACH(xm, xconf, entry)
+ if (mrt_get(nconf, xm) == NULL)
/* REMOVE */
- xm->state = MRT_STATE_TOREMOVE;
+ MRT2MC(xm)->state = MRT_STATE_REMOVE;
/* free config */
while ((m = LIST_FIRST(nconf)) != NULL) {
- LIST_REMOVE(m, list);
+ LIST_REMOVE(m, entry);
free(m);
}
diff --git a/usr.sbin/bgpd/mrt.h b/usr.sbin/bgpd/mrt.h
index 8e281461a59..19c457f0edf 100644
--- a/usr.sbin/bgpd/mrt.h
+++ b/usr.sbin/bgpd/mrt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mrt.h,v 1.10 2004/02/25 19:48:18 claudio Exp $ */
+/* $OpenBSD: mrt.h,v 1.11 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -244,56 +244,52 @@ enum mrt_type {
};
enum mrt_state {
- MRT_STATE_STOPPED,
MRT_STATE_RUNNING,
MRT_STATE_OPEN,
- MRT_STATE_CLOSE,
MRT_STATE_REOPEN,
- MRT_STATE_TOREMOVE,
MRT_STATE_REMOVE
};
-LIST_HEAD(mrt_config_head, mrt_config);
-
-struct mrt_config {
- enum mrt_type type;
- u_int32_t id;
- u_int32_t peer_id;
- u_int32_t group_id;
- struct imsgbuf *ibuf;
- LIST_ENTRY(mrt_config) list; /* used in the SE */
+struct mrt {
+ enum mrt_type type;
+ u_int32_t peer_id;
+ u_int32_t group_id;
+ u_int32_t queued;
+ int fd;
+ TAILQ_HEAD(, buf) bufs;
+ LIST_ENTRY(mrt) entry;
};
-struct mrt {
- struct mrt_config conf;
- time_t ReopenTimer;
- time_t ReopenTimerInterval;
- enum mrt_state state;
- struct msgbuf msgbuf;
- struct imsgbuf *ibuf;
- char name[MRT_FILE_LEN]; /* base file name */
- char file[MRT_FILE_LEN]; /* actual file name */
- LIST_ENTRY(mrt) list; /* used in the parent */
+struct mrt_config {
+ struct mrt conf;
+ time_t ReopenTimer;
+ time_t ReopenTimerInterval;
+ enum mrt_state state;
+ char name[MRT_FILE_LEN]; /* base file name */
+ char file[MRT_FILE_LEN]; /* actual file name */
};
+#define MRT2MC(x) ((struct mrt_config *)(x))
+#define MRT_MAX_TIMEOUT 7200
struct prefix;
struct pt_entry;
/* prototypes */
-int mrt_dump_bgp_msg(struct mrt_config *, void *, u_int16_t,
- struct peer_config *, struct bgpd_config *);
-int mrt_dump_state(struct mrt_config *, u_int16_t, u_int16_t,
- struct peer_config *, struct bgpd_config *);
-void mrt_clear_seq(void);
-void mrt_dump_upcall(struct pt_entry *, void *);
-void mrt_init(struct imsgbuf *, struct imsgbuf *);
-void mrt_abort(struct mrt *);
-int mrt_queue(struct mrt_head *, struct imsg *);
-int mrt_write(struct mrt *);
-int mrt_select(struct mrt_head *, struct pollfd *, struct mrt **,
- int, int, int *);
-int mrt_handler(struct mrt_head *);
-int mrt_mergeconfig(struct mrt_head *, struct mrt_head *);
+int mrt_dump_bgp_msg(struct mrt *, void *, u_int16_t,
+ struct peer_config *, struct bgpd_config *);
+int mrt_dump_state(struct mrt *, u_int16_t, u_int16_t,
+ struct peer_config *, struct bgpd_config *);
+void mrt_clear_seq(void);
+void mrt_dump_upcall(struct pt_entry *, void *);
+int mrt_write(struct mrt *);
+void mrt_clean(struct mrt *);
+void mrt_init(struct imsgbuf *, struct imsgbuf *);
+void mrt_close(struct mrt *);
+int mrt_timeout(struct mrt_head *);
+void mrt_reconfigure(struct mrt_head *);
+void mrt_handler(struct mrt_head *);
+struct mrt *mrt_get(struct mrt_head *, struct mrt *);
+int mrt_mergeconfig(struct mrt_head *, struct mrt_head *);
#endif
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index a37537c017f..d970903d46c 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.116 2004/06/23 00:11:27 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.117 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -1573,44 +1573,44 @@ add_mrtconfig(enum mrt_type type, char *name, time_t timeout, struct peer *p)
{
struct mrt *m, *n;
- LIST_FOREACH(m, mrtconf, list) {
+ LIST_FOREACH(m, mrtconf, entry) {
if (p == NULL) {
- if (m->conf.peer_id != 0 || m->conf.group_id != 0)
+ if (m->peer_id != 0 || m->group_id != 0)
continue;
} else {
- if (m->conf.peer_id != p->conf.id ||
- m->conf.group_id != p->conf.groupid)
+ if (m->peer_id != p->conf.id ||
+ m->group_id != p->conf.groupid)
continue;
}
- if (m->conf.type == type) {
+ if (m->type == type) {
yyerror("only one mrtdump per type allowed.");
return (-1);
}
}
- if ((n = calloc(1, sizeof(struct mrt))) == NULL)
+ if ((n = calloc(1, sizeof(struct mrt_config))) == NULL)
fatal("add_mrtconfig");
- n->conf.type = type;
- n->msgbuf.fd = -1;
- if (strlcpy(n->name, name, sizeof(n->name)) >= sizeof(n->name)) {
+ n->type = type;
+ if (strlcpy(MRT2MC(n)->name, name, sizeof(MRT2MC(n)->name)) >=
+ sizeof(MRT2MC(n)->name)) {
yyerror("filename \"%s\" too long: max %u",
- name, sizeof(n->name) - 1);
+ name, sizeof(MRT2MC(n)->name) - 1);
free(n);
return (-1);
}
- n->ReopenTimerInterval = timeout;
+ MRT2MC(n)->ReopenTimerInterval = timeout;
if (p != NULL) {
if (curgroup == p) {
- n->conf.peer_id = 0;
- n->conf.group_id = p->conf.id;
+ n->peer_id = 0;
+ n->group_id = p->conf.id;
} else {
- n->conf.peer_id = p->conf.id;
- n->conf.group_id = 0;
+ n->peer_id = p->conf.id;
+ n->group_id = 0;
}
}
- LIST_INSERT_HEAD(mrtconf, n, list);
+ LIST_INSERT_HEAD(mrtconf, n, entry);
return (0);
}
diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c
index 95871b3b8c6..8f592d246b3 100644
--- a/usr.sbin/bgpd/printconf.c
+++ b/usr.sbin/bgpd/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.22 2004/06/20 18:35:12 henning Exp $ */
+/* $OpenBSD: printconf.c,v 1.23 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -353,16 +353,17 @@ print_mrt(u_int32_t pid, u_int32_t gid, const char *prep)
if (xmrt_l == NULL)
return;
- LIST_FOREACH(m, xmrt_l, list)
- if ((gid != 0 && m->conf.group_id == gid) ||
- (m->conf.peer_id == pid && m->conf.group_id == gid)) {
- if (m->ReopenTimerInterval == 0)
+ LIST_FOREACH(m, xmrt_l, entry)
+ if ((gid != 0 && m->group_id == gid) ||
+ (m->peer_id == pid && m->group_id == gid)) {
+ if (MRT2MC(m)->ReopenTimerInterval == 0)
printf("%sdump %s %s\n", prep,
- mrt_type(m->conf.type), m->name);
+ mrt_type(m->type), MRT2MC(m)->name);
else
printf("%sdump %s %s %d\n", prep,
- mrt_type(m->conf.type),
- m->name, m->ReopenTimerInterval);
+ mrt_type(m->type),
+ MRT2MC(m)->name,
+ MRT2MC(m)->ReopenTimerInterval);
}
}
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c
index 1bc3ee8895c..0a0abd969a1 100644
--- a/usr.sbin/bgpd/rde.c
+++ b/usr.sbin/bgpd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.121 2004/06/24 23:15:58 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.122 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -35,6 +35,7 @@
#define PFD_PIPE_MAIN 0
#define PFD_PIPE_SESSION 1
+#define PFD_MRT_FILE 2
void rde_sighdlr(int);
void rde_dispatch_imsg_session(struct imsgbuf *);
@@ -84,6 +85,7 @@ struct rde_peer peerdynamic;
struct filter_head *rules_l, *newrules;
struct imsgbuf ibuf_se;
struct imsgbuf ibuf_main;
+struct mrt *mrt;
void
rde_sighdlr(int sig)
@@ -107,10 +109,9 @@ rde_main(struct bgpd_config *config, struct network_head *net_l,
{
pid_t pid;
struct passwd *pw;
- struct mrt *m;
struct listen_addr *la;
- struct pollfd pfd[2];
- int nfds;
+ struct pollfd pfd[3];
+ int nfds, i;
switch (pid = fork()) {
case -1:
@@ -153,10 +154,12 @@ rde_main(struct bgpd_config *config, struct network_head *net_l,
imsg_init(&ibuf_main, pipe_m2r[1]);
/* main mrt list and listener list are not used in the SE */
- while ((m = LIST_FIRST(mrt_l)) != NULL) {
- LIST_REMOVE(m, list);
- free(m);
+ while ((mrt = LIST_FIRST(mrt_l)) != NULL) {
+ LIST_REMOVE(mrt, entry);
+ free(mrt);
}
+ mrt = NULL;
+
while ((la = TAILQ_FIRST(config->listen_addrs)) != NULL) {
TAILQ_REMOVE(config->listen_addrs, la, entry);
free(la);
@@ -184,7 +187,14 @@ rde_main(struct bgpd_config *config, struct network_head *net_l,
if (ibuf_se.w.queued > 0)
pfd[PFD_PIPE_SESSION].events |= POLLOUT;
- if ((nfds = poll(pfd, 2, INFTIM)) == -1)
+ i = 2;
+ if (mrt && mrt->queued) {
+ pfd[PFD_MRT_FILE].fd = mrt->fd;
+ pfd[PFD_MRT_FILE].events = POLLOUT;
+ i++;
+ }
+
+ if ((nfds = poll(pfd, i, INFTIM)) == -1)
if (errno != EINTR)
fatal("poll error");
@@ -207,6 +217,15 @@ rde_main(struct bgpd_config *config, struct network_head *net_l,
nfds--;
rde_dispatch_imsg_session(&ibuf_se);
}
+
+ if (nfds > 0 && pfd[PFD_MRT_FILE].revents & POLLOUT) {
+ if (mrt_write(mrt) == -1) {
+ free(mrt);
+ mrt = NULL;
+ } else if (mrt->queued == 0)
+ close(mrt->fd);
+ }
+
rde_update_queue_runner();
}
@@ -334,8 +353,8 @@ void
rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
{
struct imsg imsg;
- struct mrt_config mrt;
struct filter_rule *r;
+ struct mrt *xmrt;
int n;
if ((n = imsg_read(ibuf)) == -1)
@@ -400,18 +419,44 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf)
case IMSG_NEXTHOP_UPDATE:
nexthop_update(imsg.data);
break;
- case IMSG_MRT_REQ:
- memcpy(&mrt, imsg.data, sizeof(mrt));
- mrt.ibuf = &ibuf_main;
- if (mrt.type == MRT_TABLE_DUMP) {
- mrt_clear_seq();
- pt_dump(mrt_dump_upcall, &mrt, AF_UNSPEC);
- if (imsg_compose(&ibuf_main, IMSG_MRT_END,
- mrt.id, NULL, 0) == -1)
- fatalx("imsg_compose error");
+ case IMSG_MRT_OPEN:
+ case IMSG_MRT_REOPEN:
+ if (imsg.hdr.len > IMSG_HEADER_SIZE +
+ sizeof(struct mrt)) {
+ log_warnx("wrong imsg len");
+ break;
+ }
+
+ xmrt = calloc(1, sizeof(struct mrt));
+ if (xmrt == NULL)
+ fatal("rde_dispatch_imsg_parent");
+ memcpy(xmrt, imsg.data, sizeof(struct mrt));
+ TAILQ_INIT(&xmrt->bufs);
+
+ if ((xmrt->fd = imsg_get_fd(ibuf)) == -1)
+ log_warnx("expected to receive fd for mrt dump "
+ "but didn't receive any");
+
+ /* tell parent to close fd */
+ if (imsg_compose(&ibuf_main, IMSG_MRT_CLOSE, 0,
+ xmrt, sizeof(struct mrt)) == -1)
+ log_warn("rde_dispatch_imsg_parent: mrt close");
+
+ if (xmrt->type == MRT_TABLE_DUMP) {
+ /* do not dump if a other is still running */
+ if (mrt == NULL || mrt->queued == 0) {
+ free(mrt);
+ mrt = xmrt;
+ mrt_clear_seq();
+ pt_dump(mrt_dump_upcall, mrt,
+ AF_UNSPEC);
+ break;
+ }
}
+ close(xmrt->fd);
+ free(xmrt);
break;
- case IMSG_MRT_END:
+ case IMSG_MRT_CLOSE:
/* ignore end message because a dump is atomic */
break;
default:
@@ -850,7 +895,7 @@ rde_update_log(const char *message,
if (asprintf(&p, "%s/%u", log_addr(prefix), prefixlen) == -1)
p = NULL;
- log_debug("neighbor %s (AS%u) %s %s/%u %s",
+ log_info("neighbor %s (AS%u) %s %s/%u %s",
log_addr(&peer->conf.remote_addr), peer->conf.remote_as, message,
p ? p : "out of memory", nexthop ? nexthop : "");
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index 00063c8aab8..91fa899164b 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.180 2004/06/22 07:58:19 alexander Exp $ */
+/* $OpenBSD: session.c,v 1.181 2004/07/03 17:19:59 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -94,7 +94,7 @@ int csock = -1;
struct imsgbuf ibuf_rde;
struct imsgbuf ibuf_main;
-struct mrt_config_head mrt_l;
+struct mrt_head mrthead;
void
session_sighdlr(int sig)
@@ -160,16 +160,17 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
struct network_head *net_l, struct filter_head *rules,
struct mrt_head *m_l, int pipe_m2s[2], int pipe_s2r[2])
{
- int nfds, i, j, timeout, idx_peers, idx_listeners;
+ int nfds, i, j, timeout;
+ int idx_peers, idx_listeners, idx_mrts;
pid_t pid;
time_t nextaction;
- u_int pfd_elms = 0, peer_l_elms = 0, new_cnt;
- u_int listener_cnt, peer_cnt, ctl_cnt;
+ u_int pfd_elms = 0, peer_l_elms = 0, mrt_l_elms = 0;
+ u_int listener_cnt, peer_cnt, ctl_cnt, mrt_cnt;
+ u_int new_cnt;
struct passwd *pw;
struct peer *p, **peer_l = NULL, *last, *next;
struct network *net;
- struct mrt *m;
- struct mrt_config *mrt;
+ struct mrt *m, **mrt_l = NULL;
struct filter_rule *r;
struct pollfd *pfd = NULL;
struct ctl_conn *ctl_conn;
@@ -228,7 +229,7 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
imsg_init(&ibuf_main, pipe_m2s[1]);
TAILQ_INIT(&ctl_conns);
csock = control_listen();
- LIST_INIT(&mrt_l);
+ LIST_INIT(&mrthead);
peer_cnt = 0;
ctl_cnt = 0;
@@ -247,7 +248,7 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
/* main mrt list is not used in the SE */
while ((m = LIST_FIRST(m_l)) != NULL) {
- LIST_REMOVE(m, list);
+ LIST_REMOVE(m, entry);
free(m);
}
@@ -300,8 +301,28 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
peer_l_elms = peer_cnt + PEER_L_RESERVE;
}
- new_cnt =
- PFD_LISTENERS_START + listener_cnt + peer_cnt + ctl_cnt;
+ mrt_cnt = 0;
+ LIST_FOREACH(m, &mrthead, entry) {
+ if (m->queued)
+ mrt_cnt++;
+ }
+
+ if (mrt_cnt > mrt_l_elms ||
+ mrt_cnt + 2 * PEER_L_RESERVE < mrt_l_elms) {
+ if ((newp = realloc(mrt_l, sizeof(struct mrt *) *
+ (mrt_cnt + PEER_L_RESERVE))) == NULL) {
+ /* panic for now */
+ log_warn("could not resize mrt_l from %u -> %u"
+ " entries", mrt_l_elms,
+ mrt_cnt + PEER_L_RESERVE);
+ fatalx("exiting");
+ }
+ mrt_l = newp;
+ mrt_l_elms = mrt_cnt + PEER_L_RESERVE;
+ }
+
+ new_cnt = PFD_LISTENERS_START + listener_cnt + peer_cnt +
+ ctl_cnt + mrt_cnt;
if (new_cnt > pfd_elms ||
(new_cnt + 2) * PFD_RESERVE < pfd_elms) {
if ((newp = realloc(pfd, sizeof(struct pollfd) *
@@ -391,6 +412,16 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
idx_peers = i;
+ LIST_FOREACH(m, &mrthead, entry)
+ if (m->queued) {
+ pfd[i].fd = m->fd;
+ pfd[i].events = POLLOUT;
+ mrt_l[i - idx_peers] = m;
+ i++;
+ }
+
+ idx_mrts = i;
+
TAILQ_FOREACH(ctl_conn, &ctl_conns, entry) {
pfd[i].fd = ctl_conn->ibuf.fd;
pfd[i].events = POLLIN;
@@ -442,6 +473,12 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
nfds -= session_dispatch_msg(&pfd[j],
peer_l[j - idx_listeners]);
+ for (; nfds > 0 && j < idx_mrts; j++)
+ if (pfd[j].revents & POLLOUT) {
+ nfds--;
+ mrt_write(mrt_l[j - idx_peers]);
+ }
+
for (; nfds > 0 && j < i; j++)
nfds -= control_dispatch_msg(&pfd[j], &ctl_cnt);
}
@@ -453,9 +490,10 @@ session_main(struct bgpd_config *config, struct peer *cpeers,
free(p);
}
- while ((mrt = LIST_FIRST(&mrt_l)) != NULL) {
- LIST_REMOVE(mrt, list);
- free(mrt);
+ while ((m = LIST_FIRST(&mrthead)) != NULL) {
+ mrt_clean(m);
+ LIST_REMOVE(m, entry);
+ free(m);
}
while ((la = TAILQ_FIRST(conf->listen_addrs)) != NULL) {
@@ -760,7 +798,7 @@ void
change_state(struct peer *peer, enum session_state state,
enum session_events event)
{
- struct mrt_config *mrt;
+ struct mrt *mrt;
switch (state) {
case STATE_IDLE:
@@ -818,7 +856,7 @@ change_state(struct peer *peer, enum session_state state,
}
log_statechange(peer, state, event);
- LIST_FOREACH(mrt, &mrt_l, list) {
+ LIST_FOREACH(mrt, &mrthead, entry) {
if (mrt->type != MRT_ALL_IN && mrt->type != MRT_ALL_OUT)
continue;
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
@@ -1074,7 +1112,7 @@ session_open(struct peer *p)
{
struct msg_open msg;
struct buf *buf;
- struct mrt_config *mrt;
+ struct mrt *mrt;
u_int16_t len;
int errs = 0;
u_int8_t op_type, op_len = 0, optparamlen = 0;
@@ -1154,7 +1192,7 @@ session_open(struct peer *p)
}
if (errs == 0) {
- LIST_FOREACH(mrt, &mrt_l, list) {
+ LIST_FOREACH(mrt, &mrthead, entry) {
if (mrt->type != MRT_ALL_OUT)
continue;
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
@@ -1184,7 +1222,7 @@ session_keepalive(struct peer *peer)
{
struct msg_header msg;
struct buf *buf;
- struct mrt_config *mrt;
+ struct mrt *mrt;
ssize_t len;
int errs = 0;
@@ -1208,7 +1246,7 @@ session_keepalive(struct peer *peer)
return;
}
- LIST_FOREACH(mrt, &mrt_l, list) {
+ LIST_FOREACH(mrt, &mrthead, entry) {
if (mrt->type != MRT_ALL_OUT)
continue;
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
@@ -1234,7 +1272,7 @@ session_update(u_int32_t peerid, void *data, size_t datalen)
struct peer *p;
struct msg_header msg;
struct buf *buf;
- struct mrt_config *mrt;
+ struct mrt *mrt;
ssize_t len;
int errs = 0;
@@ -1267,7 +1305,7 @@ session_update(u_int32_t peerid, void *data, size_t datalen)
return;
}
- LIST_FOREACH(mrt, &mrt_l, list) {
+ LIST_FOREACH(mrt, &mrthead, entry) {
if (mrt->type != MRT_ALL_OUT && mrt->type != MRT_UPDATE_OUT)
continue;
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
@@ -1293,7 +1331,7 @@ session_notification(struct peer *peer, u_int8_t errcode, u_int8_t subcode,
{
struct msg_header msg;
struct buf *buf;
- struct mrt_config *mrt;
+ struct mrt *mrt;
ssize_t len;
int errs = 0;
@@ -1322,7 +1360,7 @@ session_notification(struct peer *peer, u_int8_t errcode, u_int8_t subcode,
return;
}
- LIST_FOREACH(mrt, &mrt_l, list) {
+ LIST_FOREACH(mrt, &mrthead, entry) {
if (mrt->type != MRT_ALL_OUT)
continue;
if ((mrt->peer_id == 0 && mrt->group_id == 0) ||
@@ -1481,7 +1519,7 @@ session_dispatch_msg(struct pollfd *pfd, struct peer *p)
int
parse_header(struct peer *peer, u_char *data, u_int16_t *len, u_int8_t *type)
{
- struct mrt_config *mrt;
+ struct mrt *mrt;
u_char *p;
u_char one = 0xff;
int i;
@@ -1566,7 +1604,7 @@ parse_header(struct peer *peer, u_char *data, u_int16_t *len, u_int8_t *type)
type, 1);
return (-1);
}
- LIST_FOREACH(mrt, &mrt_l, list) {
+ LIST_FOREACH(mrt, &mrthead, entry) {
if (mrt->type != MRT_ALL_IN && (mrt->type != MRT_UPDATE_IN ||
*type != UPDATE))
continue;
@@ -1971,8 +2009,8 @@ void
session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
{
struct imsg imsg;
- struct mrt_config xmrt;
- struct mrt_config *mrt;
+ struct mrt xmrt;
+ struct mrt *mrt;
struct peer_config *pconf;
struct peer *p, *next;
struct listen_addr *la, *nla;
@@ -2118,25 +2156,52 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx, u_int *listener_cnt)
pending_reconf = 0;
log_info("SE reconfigured");
break;
- case IMSG_MRT_REQ:
- if ((mrt = calloc(1, sizeof(struct mrt_config))) ==
- NULL)
- fatal("session_dispatch_imsg");
- memcpy(mrt, imsg.data, sizeof(struct mrt_config));
- mrt->ibuf = &ibuf_main;
- LIST_INSERT_HEAD(&mrt_l, mrt, list);
+ case IMSG_MRT_OPEN:
+ case IMSG_MRT_REOPEN:
+ if (imsg.hdr.len > IMSG_HEADER_SIZE +
+ sizeof(struct mrt)) {
+ log_warnx("wrong imsg len");
+ break;
+ }
+
+ memcpy(&xmrt, imsg.data, sizeof(struct mrt));
+ if ((xmrt.fd = imsg_get_fd(ibuf)) == -1)
+ log_warnx("expected to receive fd for mrt dump "
+ "but didn't receive any");
+
+ mrt = mrt_get(&mrthead, &xmrt);
+ if (mrt == NULL) {
+ /* new dump */
+ mrt = calloc(1, sizeof(struct mrt));
+ if (mrt == NULL)
+ fatal("session_dispatch_imsg");
+ memcpy(mrt, &xmrt, sizeof(struct mrt));
+ TAILQ_INIT(&mrt->bufs);
+ LIST_INSERT_HEAD(&mrthead, mrt, entry);
+ } else {
+ /* old dump reopened */
+ close(mrt->fd);
+ mrt->fd = xmrt.fd;
+ }
+
+ /* tell parent to close fd */
+ if (imsg_compose(&ibuf_main, IMSG_MRT_CLOSE, 0,
+ &xmrt, sizeof(struct mrt)) == -1)
+ log_warn("session_dispatch_imsg: mrt close");
break;
- case IMSG_MRT_END:
- memcpy(&xmrt, imsg.data, sizeof(struct mrt_config));
- LIST_FOREACH(mrt, &mrt_l, list) {
- if (mrt->type != xmrt.type)
- continue;
- if (mrt->peer_id == xmrt.peer_id &&
- mrt->group_id == xmrt.group_id) {
- LIST_REMOVE(mrt, list);
- free(mrt);
- break;
- }
+ case IMSG_MRT_CLOSE:
+ if (imsg.hdr.len > IMSG_HEADER_SIZE +
+ sizeof(struct mrt)) {
+ log_warnx("wrong imsg len");
+ break;
+ }
+
+ memcpy(&xmrt, imsg.data, sizeof(struct mrt));
+ mrt = mrt_get(&mrthead, &xmrt);
+ if (mrt != NULL) {
+ mrt_clean(mrt);
+ LIST_REMOVE(mrt, entry);
+ free(mrt);
}
break;
case IMSG_CTL_KROUTE: