diff options
-rw-r--r-- | usr.sbin/bgpd/mrt.c | 140 | ||||
-rw-r--r-- | usr.sbin/bgpd/mrt.h | 18 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 68 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 20 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 120 |
5 files changed, 192 insertions, 174 deletions
diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c index bc2cb13a4d4..d2c3cdf3a1b 100644 --- a/usr.sbin/bgpd/mrt.c +++ b/usr.sbin/bgpd/mrt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.c,v 1.26 2004/02/19 13:54:58 claudio Exp $ */ +/* $OpenBSD: mrt.c,v 1.27 2004/02/25 19:48:18 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -28,16 +28,10 @@ #include "bgpd.h" #include "rde.h" -#include "session.h" /* needed for MSGSIZE_HEADER et al. */ +#include "session.h" #include "mrt.h" -/* - * XXX These functions break the imsg encapsulation. - * XXX The imsg API is way to basic, we need something like - * XXX imsg_create(), imsg_add(), imsg_close() ... - */ - 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 *, @@ -49,9 +43,8 @@ static int mrt_open(struct mrt *); #define DUMP_BYTE(x, b) \ do { \ u_char t = (b); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump1: buf_add error"); \ - buf_free((x)); \ + if (imsg_add((x), &t, sizeof(t)) == -1) { \ + log_warnx("mrt_dump1: imsg_add error"); \ return (-1); \ } \ } while (0) @@ -60,9 +53,8 @@ static int mrt_open(struct mrt *); do { \ u_int16_t t; \ t = htons((s)); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump2: buf_add error"); \ - buf_free((x)); \ + if (imsg_add((x), &t, sizeof(t)) == -1) { \ + log_warnx("mrt_dump2: imsg_add error"); \ return (-1); \ } \ } while (0) @@ -71,9 +63,8 @@ static int mrt_open(struct mrt *); do { \ u_int32_t t; \ t = htonl((l)); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump3: buf_add error"); \ - buf_free((x)); \ + if (imsg_add((x), &t, sizeof(t)) == -1) { \ + log_warnx("mrt_dump3: imsg_add error"); \ return (-1); \ } \ } while (0) @@ -81,41 +72,30 @@ static int mrt_open(struct mrt *); #define DUMP_NLONG(x, l) \ do { \ u_int32_t t = (l); \ - if (buf_add((x), &t, sizeof(t)) == -1) { \ - log_warnx("mrt_dump4: buf_add error"); \ - buf_free((x)); \ + if (imsg_add((x), &t, sizeof(t)) == -1) { \ + log_warnx("mrt_dump4: imsg_add error"); \ return (-1); \ } \ } while (0) int -mrt_dump_bgp_msg(struct mrt_config *mrt, void *pkg, u_int16_t pkglen, int type, +mrt_dump_bgp_msg(struct mrt_config *mrt, void *pkg, u_int16_t pkglen, struct peer_config *peer, struct bgpd_config *bgp) { struct buf *buf; - struct imsg_hdr hdr; - int i, n; u_int16_t len; - len = pkglen + MRT_BGP4MP_HEADER_SIZE + (type > 0 ? MSGSIZE_HEADER : 0); + len = pkglen + MRT_BGP4MP_HEADER_SIZE; - hdr.len = len + IMSG_HEADER_SIZE + MRT_HEADER_SIZE; - hdr.type = IMSG_MRT_MSG; - hdr.peerid = mrt->id; - buf = buf_open(hdr.len); - if (buf == NULL) { - log_warnx("mrt_dump_bgp_msg: buf_open error"); - return (-1); - } - if (buf_add(buf, &hdr, sizeof(hdr)) == -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); - buf_free(buf); + 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"); return (-1); } - if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, len) == - -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); + if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE, + len) == -1) { + log_warnx("mrt_dump_bgp_msg: imsg_add error"); return (-1); } @@ -126,27 +106,17 @@ mrt_dump_bgp_msg(struct mrt_config *mrt, void *pkg, u_int16_t pkglen, int type, DUMP_NLONG(buf, peer->local_addr.v4.s_addr); DUMP_NLONG(buf, peer->remote_addr.v4.s_addr); - /* bgp header was chopped off so glue a new one together. */ - if (type > 0) { - for (i = 0; i < MSGSIZE_HEADER_MARKER; i++) - DUMP_BYTE(buf, 0xff); - DUMP_SHORT(buf, pkglen + MSGSIZE_HEADER); - DUMP_BYTE(buf, type); - } - - if (buf_add(buf, pkg, pkglen) == -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); - buf_free(buf); + if (imsg_add(buf, pkg, pkglen) == -1) { + log_warnx("mrt_dump_bgp_msg: imsg_add error"); return (-1); } - if ((n = buf_close(mrt->msgbuf, buf)) < 0) { - log_warnx("mrt_dump_bgp_msg: buf_close error"); - buf_free(buf); + if ((imsg_close(mrt->ibuf, buf)) == -1) { + log_warnx("mrt_dump_bgp_msg: imsg_close error"); return (-1); } - return (n); + return (len + MRT_HEADER_SIZE); } int @@ -154,28 +124,19 @@ mrt_dump_state(struct mrt_config *mrt, u_int16_t old_state, u_int16_t new_state, struct peer_config *peer, struct bgpd_config *bgp) { struct buf *buf; - struct imsg_hdr hdr; - int n; u_int16_t len; len = 4 + MRT_BGP4MP_HEADER_SIZE; - hdr.len = len + IMSG_HEADER_SIZE + MRT_HEADER_SIZE; - hdr.type = IMSG_MRT_MSG; - hdr.peerid = mrt->id; - buf = buf_open(hdr.len); - if (buf == NULL) { - log_warnx("mrt_dump_bgp_msg: buf_open error"); - return (-1); - } - if (buf_add(buf, &hdr, sizeof(hdr)) == -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); - buf_free(buf); + + 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"); return (-1); } if (mrt_dump_header(buf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE, len) == -1) { - log_warnx("mrt_dump_bgp_msg: buf_add error"); + log_warnx("mrt_dump_bgp_state: imsg_add error"); return (-1); } @@ -189,14 +150,12 @@ 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 ((n = buf_close(mrt->msgbuf, buf)) < 0) { - log_warnx("mrt_dump_bgp_msg: buf_close error"); - buf_free(buf); + if ((imsg_close(mrt->ibuf, buf)) == -1) { + log_warnx("mrt_dump_bgp_state: imsg_close error"); return (-1); } - return (n); - + return (len + MRT_HEADER_SIZE); } static u_int16_t @@ -278,24 +237,14 @@ mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum, { struct buf *buf; void *bptr; - struct imsg_hdr hdr; u_int16_t len, attr_len; - int n; attr_len = mrt_attr_length(&p->aspath->flags); len = MRT_DUMP_HEADER_SIZE + attr_len; - hdr.len = len + IMSG_HEADER_SIZE + MRT_HEADER_SIZE; - hdr.type = IMSG_MRT_MSG; - hdr.peerid = mrt->id; - buf = buf_open(hdr.len); - if (buf == NULL) { - log_warnx("mrt_dump_entry: buf_open error"); - return (-1); - } - if (buf_add(buf, &hdr, sizeof(hdr)) == -1) { - log_warnx("mrt_dump_entry: buf_add error"); - buf_free(buf); + if ((buf = imsg_create(mrt->ibuf, IMSG_MRT_MSG, mrt->id, + len + MRT_HEADER_SIZE)) == NULL) { + log_warnx("mrt_dump_entry: imsg_open error"); return (-1); } @@ -326,13 +275,12 @@ mrt_dump_entry(struct mrt_config *mrt, struct prefix *p, u_int16_t snum, return (-1); } - if ((n = buf_close(mrt->msgbuf, buf)) < 0) { - log_warnx("mrt_dump_entry: buf_close error"); - buf_free(buf); + if ((imsg_close(mrt->ibuf, buf)) == -1) { + log_warnx("mrt_dump_bgp_state: imsg_close error"); return (-1); } - return (n); + return (len + MRT_HEADER_SIZE); } static u_int16_t sequencenum = 0; @@ -583,10 +531,12 @@ mrt_select(struct mrt_head *mc, struct pollfd *pfd, struct mrt **mrt, if (m->state == MRT_STATE_OPEN) { switch (m->conf.type) { case MRT_TABLE_DUMP: - case MRT_FILTERED_IN: 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: @@ -709,11 +659,10 @@ getconf(struct mrt_head *c, struct mrt *m) LIST_FOREACH(t, c, list) { if (t->conf.type != m->conf.type) continue; - if (t->conf.type == MRT_TABLE_DUMP || - t->conf.type == MRT_ALL_IN || - t->conf.type == MRT_FILTERED_IN) + if (t->conf.type == MRT_TABLE_DUMP) return t; - if (t->conf.peer_id == m->conf.peer_id) + if (t->conf.peer_id == m->conf.peer_id && + t->conf.group_id == m->conf.group_id) return t; } return (NULL); @@ -727,8 +676,7 @@ mrt_mergeconfig(struct mrt_head *xconf, struct mrt_head *nconf) LIST_FOREACH(m, nconf, list) if ((xm = getconf(xconf, m)) == NULL) { /* NEW */ - if ((xm = calloc(1, sizeof(struct mrt))) == - NULL) + if ((xm = calloc(1, sizeof(struct mrt))) == NULL) fatal("mrt_mergeconfig"); memcpy(xm, m, sizeof(struct mrt)); msgbuf_init(&xm->msgbuf); diff --git a/usr.sbin/bgpd/mrt.h b/usr.sbin/bgpd/mrt.h index 62a87539728..8e281461a59 100644 --- a/usr.sbin/bgpd/mrt.h +++ b/usr.sbin/bgpd/mrt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mrt.h,v 1.9 2004/01/18 00:44:44 deraadt Exp $ */ +/* $OpenBSD: mrt.h,v 1.10 2004/02/25 19:48:18 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -237,10 +237,10 @@ enum MRT_BGP_TYPES { enum mrt_type { MRT_NONE, MRT_TABLE_DUMP, - MRT_FILTERED_IN, MRT_ALL_IN, - MRT_SESSION_IN, - MRT_SESSION_OUT + MRT_ALL_OUT, + MRT_UPDATE_IN, + MRT_UPDATE_OUT }; enum mrt_state { @@ -253,11 +253,15 @@ enum mrt_state { 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; - struct msgbuf *msgbuf; + u_int32_t group_id; + struct imsgbuf *ibuf; + LIST_ENTRY(mrt_config) list; /* used in the SE */ }; struct mrt { @@ -269,7 +273,7 @@ struct mrt { struct imsgbuf *ibuf; char name[MRT_FILE_LEN]; /* base file name */ char file[MRT_FILE_LEN]; /* actual file name */ - LIST_ENTRY(mrt) list; + LIST_ENTRY(mrt) list; /* used in the parent */ }; @@ -277,7 +281,7 @@ struct prefix; struct pt_entry; /* prototypes */ -int mrt_dump_bgp_msg(struct mrt_config *, void *, u_int16_t, int, +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 *); diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 6afc6fbd027..75b42ad9c5a 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.59 2004/02/25 14:25:22 henning Exp $ */ +/* $OpenBSD: parse.y,v 1.60 2004/02/25 19:48:18 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -64,7 +64,7 @@ int yylex(void); struct peer *alloc_peer(void); struct peer *new_peer(void); struct peer *new_group(void); -int add_mrtconfig(enum mrt_type, char *, time_t); +int add_mrtconfig(enum mrt_type, char *, time_t, struct peer *); int get_id(struct peer *); int expand_rule(struct filter_rule *, struct filter_peers *, struct filter_match *, struct filter_set *); @@ -100,7 +100,7 @@ typedef struct { %token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE %token GROUP NEIGHBOR NETWORK %token REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX ANNOUNCE -%token DUMP MSG IN TABLE +%token DUMP TABLE IN OUT %token LOG %token TCP MD5SIG PASSWORD KEY %token ALLOW DENY MATCH @@ -110,7 +110,7 @@ typedef struct { %token SET LOCALPREF MED NEXTHOP PREPEND %token ERROR %token <v.string> STRING -%type <v.number> number optnumber yesno +%type <v.number> number optnumber yesno inout %type <v.string> string %type <v.addr> address %type <v.u8> action quick direction @@ -213,24 +213,6 @@ conf_main : AS number { else YYERROR; } - | DUMP MSG STRING IN STRING optnumber { - int action; - - if (!strcmp($3, "all")) - action = MRT_ALL_IN; - else if (!strcmp($3, "filtered")) - action = MRT_FILTERED_IN; - else { - yyerror("unknown mrt msg dump type"); - YYERROR; - } - if (add_mrtconfig(action, $5, $6) == -1) - YYERROR; - } - | DUMP TABLE STRING optnumber { - if (add_mrtconfig(MRT_TABLE_DUMP, $3, $4) == -1) - YYERROR; - } | NETWORK address '/' number { struct network *n; @@ -244,6 +226,31 @@ conf_main : AS number { n->net.prefixlen = $4; TAILQ_INSERT_TAIL(netconf, n, network_l); } + | DUMP TABLE STRING optnumber { + if (add_mrtconfig(MRT_TABLE_DUMP, $3, $4, NULL) == -1) + YYERROR; + } + | mrtdump + ; + +mrtdump : DUMP STRING inout STRING optnumber { + int action; + + if (!strcmp($2, "all")) + action = $3 ? MRT_ALL_IN : MRT_ALL_OUT; + else if (!strcmp($2, "updates")) + action = $3 ? MRT_UPDATE_IN : MRT_UPDATE_OUT; + else { + yyerror("unknown mrt msg dump type"); + YYERROR; + } + if (add_mrtconfig(action, $4, $5, curpeer) == -1) + YYERROR; + } + ; + +inout : IN { $$ = 1; } + | OUT { $$ = 0; } ; address : STRING { @@ -426,6 +433,7 @@ peeropts : REMOTEAS number { memcpy(&curpeer->conf.attrset, &$1, sizeof(curpeer->conf.attrset)); } + | mrtdump ; filterrule : action quick direction filter_peer filter_match filter_set @@ -692,12 +700,12 @@ lookup(char *s) { "md5sig", MD5SIG}, { "med", MED}, { "min", YMIN}, - { "msg", MSG}, { "multihop", MULTIHOP}, { "neighbor", NEIGHBOR}, { "network", NETWORK}, { "nexthop", NEXTHOP}, { "on", ON}, + { "out", OUT}, { "passive", PASSIVE}, { "password", PASSWORD}, { "prefix", PREFIX}, @@ -1131,11 +1139,19 @@ new_group(void) } int -add_mrtconfig(enum mrt_type type, char *name, time_t timeout) +add_mrtconfig(enum mrt_type type, char *name, time_t timeout, struct peer *p) { struct mrt *m, *n; LIST_FOREACH(m, mrtconf, list) { + if (p == NULL) { + if (m->conf.peer_id != 0 || m->conf.group_id != 0) + continue; + } else { + if (m->conf.peer_id != p->conf.id || + m->conf.group_id != p->conf.groupid) + continue; + } if (m->conf.type == type) { yyerror("only one mrtdump per type allowed."); return (-1); @@ -1154,6 +1170,10 @@ add_mrtconfig(enum mrt_type type, char *name, time_t timeout) return (-1); } n->ReopenTimerInterval = timeout; + if (p != NULL) { + n->conf.peer_id = p->conf.id; + n->conf.group_id = p->conf.groupid; + } LIST_INSERT_HEAD(mrtconf, n, list); diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 36f65314729..29bd7828fa4 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.85 2004/02/24 15:43:03 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.86 2004/02/25 19:48:18 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -69,9 +69,6 @@ struct filter_head *rules_l, *newrules; struct imsgbuf ibuf_se; struct imsgbuf ibuf_main; -int mrt_flagfilter = 0; -struct mrt_config mrt_filter; - void rde_sighdlr(int sig) { @@ -314,25 +311,17 @@ rde_dispatch_imsg_parent(struct imsgbuf *ibuf) break; case IMSG_MRT_REQ: memcpy(&mrt, imsg.data, sizeof(mrt)); - mrt.msgbuf = &ibuf_main.w; + mrt.ibuf = &ibuf_main; if (mrt.type == MRT_TABLE_DUMP) { mrt_clear_seq(); pt_dump(mrt_dump_upcall, &mrt); if (imsg_compose(&ibuf_main, IMSG_MRT_END, mrt.id, NULL, 0) == -1) fatalx("imsg_compose error"); - } else if (mrt.type == MRT_FILTERED_IN) { - mrt_flagfilter = 1; - memcpy(&mrt_filter, &mrt, sizeof(mrt_filter)); } break; case IMSG_MRT_END: - memcpy(&mrt, imsg.data, sizeof(mrt)); /* ignore end message because a dump is atomic */ - if (mrt.type == MRT_FILTERED_IN) { - mrt_flagfilter = 0; - bzero(&mrt_filter, sizeof(mrt_filter)); - } break; default: break; @@ -362,11 +351,6 @@ rde_update_dispatch(struct imsg *imsg) if (peer->state != PEER_UP) return (-1); /* peer is not yet up, cannot happen */ - if (mrt_flagfilter == 1) - mrt_dump_bgp_msg(&mrt_filter, imsg->data, - imsg->hdr.len - IMSG_HEADER_SIZE, UPDATE, - &peer->conf, conf); - p = imsg->data; memcpy(&len, p, 2); diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 793146f739e..53fec83f75b 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.119 2004/02/21 15:45:14 henning Exp $ */ +/* $OpenBSD: session.c,v 1.120 2004/02/25 19:48:18 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -92,8 +92,7 @@ int csock = -1; struct imsgbuf ibuf_rde; struct imsgbuf ibuf_main; -int mrt_flagall = 0; -struct mrt_config mrt_allin; +struct mrt_config_head mrt_l; void session_sighdlr(int sig) @@ -196,6 +195,7 @@ session_main(struct bgpd_config *config, struct peer *cpeers, int pipe_m2s[2], imsg_init(&ibuf_main, pipe_m2s[1]); TAILQ_INIT(&ctl_conns); csock = control_listen(); + LIST_INIT(&mrt_l); while (session_quit == 0) { bzero(&pfd, sizeof(pfd)); @@ -644,6 +644,8 @@ void change_state(struct peer *peer, enum session_state state, enum session_events event) { + struct mrt_config *mrt; + switch (state) { case STATE_IDLE: /* @@ -692,10 +694,15 @@ change_state(struct peer *peer, enum session_state state, } log_statechange(peer, state, event); - if (mrt_flagall == 1) - mrt_dump_state(&mrt_allin, peer->state, state, - &peer->conf, conf); - /* XXX mrt dump per peer */ + LIST_FOREACH(mrt, &mrt_l, list) { + if (mrt->type != MRT_ALL_IN && mrt->type != MRT_ALL_OUT) + continue; + if ((mrt->peer_id == 0 && mrt->group_id == 0) || + mrt->peer_id == peer->conf.id || + mrt->group_id == peer->conf.groupid) + mrt_dump_state(mrt, peer->state, state, + &peer->conf, conf); + } peer->state = state; } @@ -885,10 +892,11 @@ session_tcp_established(struct peer *peer) void session_open(struct peer *p) { - struct msg_open msg; - struct buf *buf; - u_int16_t len; - int errs = 0, n; + struct msg_open msg; + struct buf *buf; + struct mrt_config *mrt; + u_int16_t len; + int errs = 0, n; len = MSGSIZE_OPEN_MIN; @@ -918,6 +926,16 @@ session_open(struct peer *p) errs += buf_add(buf, &msg.optparamlen, sizeof(msg.optparamlen)); if (errs == 0) { + LIST_FOREACH(mrt, &mrt_l, list) { + if (mrt->type != MRT_ALL_OUT) + continue; + if ((mrt->peer_id == 0 && mrt->group_id == 0) || + mrt->peer_id == p->conf.id || + mrt->group_id == p->conf.groupid) + mrt_dump_bgp_msg(mrt, buf->buf, len, + &p->conf, conf); + } + if ((n = buf_close(&p->wbuf, buf)) == -1) { log_peer_warn(&p->conf, "session_open buf_close"); buf_free(buf); @@ -938,6 +956,7 @@ session_keepalive(struct peer *peer) { struct msg_header msg; struct buf *buf; + struct mrt_config *mrt; ssize_t len; int errs = 0, n; @@ -961,6 +980,15 @@ session_keepalive(struct peer *peer) return; } + LIST_FOREACH(mrt, &mrt_l, list) { + if (mrt->type != MRT_ALL_OUT) + continue; + if ((mrt->peer_id == 0 && mrt->group_id == 0) || + mrt->peer_id == peer->conf.id || + mrt->group_id == peer->conf.groupid) + mrt_dump_bgp_msg(mrt, buf->buf, len, &peer->conf, conf); + } + if ((n = buf_close(&peer->wbuf, buf)) == -1) { log_peer_warn(&peer->conf, "session_keepalive buf_close"); buf_free(buf); @@ -978,6 +1006,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; ssize_t len; int errs = 0, n; @@ -1007,6 +1036,15 @@ session_update(u_int32_t peerid, void *data, size_t datalen) return; } + LIST_FOREACH(mrt, &mrt_l, list) { + if (mrt->type != MRT_ALL_OUT && mrt->type != MRT_UPDATE_OUT) + continue; + if ((mrt->peer_id == 0 && mrt->group_id == 0) || + mrt->peer_id == p->conf.id || + mrt->group_id == p->conf.groupid) + mrt_dump_bgp_msg(mrt, buf->buf, len, &p->conf, conf); + } + if ((n = buf_close(&p->wbuf, buf)) == -1) { log_peer_warn(&p->conf, "session_update: buf_close"); buf_free(buf); @@ -1024,6 +1062,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; ssize_t len; int errs = 0, n; @@ -1052,6 +1091,15 @@ session_notification(struct peer *peer, u_int8_t errcode, u_int8_t subcode, return; } + LIST_FOREACH(mrt, &mrt_l, list) { + if (mrt->type != MRT_ALL_OUT) + continue; + if ((mrt->peer_id == 0 && mrt->group_id == 0) || + mrt->peer_id == peer->conf.id || + mrt->group_id == peer->conf.groupid) + mrt_dump_bgp_msg(mrt, buf->buf, len, &peer->conf, conf); + } + if ((n = buf_close(&peer->wbuf, buf)) == -1) { log_peer_warn(&peer->conf, "session_notification: buf_close"); buf_free(buf); @@ -1199,10 +1247,11 @@ 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) { - u_char *p; - u_char one = 0xff; - int i; - u_int16_t olen; + struct mrt_config *mrt; + u_char *p; + u_char one = 0xff; + int i; + u_int16_t olen; /* caller MUST make sure we are getting 19 bytes! */ p = data; @@ -1274,9 +1323,15 @@ parse_header(struct peer *peer, u_char *data, u_int16_t *len, u_int8_t *type) type, 1); return (-1); } - if (mrt_flagall == 1) - mrt_dump_bgp_msg(&mrt_allin, data, *len, 0, &peer->conf, conf); - /* XXX mrt dump per peer */ + LIST_FOREACH(mrt, &mrt_l, list) { + if (mrt->type != MRT_ALL_IN && (mrt->type != MRT_UPDATE_IN || + *type != UPDATE)) + continue; + if ((mrt->peer_id == 0 && mrt->group_id == 0) || + mrt->peer_id == peer->conf.id || + mrt->group_id == peer->conf.groupid) + mrt_dump_bgp_msg(mrt, data, *len, &peer->conf, conf); + } return (0); } @@ -1420,7 +1475,8 @@ void session_dispatch_imsg(struct imsgbuf *ibuf, int idx) { struct imsg imsg; - struct mrt_config mrt; + struct mrt_config xmrt; + struct mrt_config *mrt; struct peer_config *pconf; struct peer *p, *next; u_char *data; @@ -1497,18 +1553,24 @@ session_dispatch_imsg(struct imsgbuf *ibuf, int idx) log_info("SE reconfigured"); break; case IMSG_MRT_REQ: - memcpy(&mrt, imsg.data, sizeof(mrt)); - mrt.msgbuf = &ibuf_main.w; - if (mrt.type == MRT_ALL_IN) { - mrt_flagall = 1; - memcpy(&mrt_allin, &mrt, sizeof(mrt_allin)); - } + 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); break; case IMSG_MRT_END: - memcpy(&mrt, imsg.data, sizeof(mrt)); - if (mrt.type == MRT_ALL_IN) { - mrt_flagall = 0; - bzero(&mrt_allin, sizeof(mrt_allin)); + 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; + } } break; case IMSG_CTL_KROUTE: |