summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/mrt.c140
-rw-r--r--usr.sbin/bgpd/mrt.h18
-rw-r--r--usr.sbin/bgpd/parse.y68
-rw-r--r--usr.sbin/bgpd/rde.c20
-rw-r--r--usr.sbin/bgpd/session.c120
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: