summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/control.c154
-rw-r--r--usr.sbin/bgpd/session.c23
-rw-r--r--usr.sbin/bgpd/session.h7
3 files changed, 90 insertions, 94 deletions
diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c
index 79c548e48e7..300822ae7b8 100644
--- a/usr.sbin/bgpd/control.c
+++ b/usr.sbin/bgpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.114 2023/11/07 11:18:35 claudio Exp $ */
+/* $OpenBSD: control.c,v 1.115 2024/01/10 11:08:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -219,7 +219,7 @@ int
control_close(struct ctl_conn *c)
{
if (c->terminate && c->ibuf.pid)
- imsg_ctl_rde(IMSG_CTL_TERMINATE, 0, c->ibuf.pid, NULL, 0);
+ imsg_ctl_rde_msg(IMSG_CTL_TERMINATE, 0, c->ibuf.pid);
msgbuf_clear(&c->ibuf.w);
TAILQ_REMOVE(&ctl_conns, c, entry);
@@ -234,12 +234,14 @@ int
control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
{
struct imsg imsg;
+ struct ctl_neighbor neighbor;
+ struct ctl_show_rib_request ribreq;
struct ctl_conn *c;
+ struct peer *p;
ssize_t n;
+ uint32_t type;
+ pid_t pid;
int verbose, matched;
- struct peer *p;
- struct ctl_neighbor *neighbor;
- struct ctl_show_rib_request *ribreq;
if ((c = control_connbyfd(pfd->fd)) == NULL) {
log_warn("control_dispatch_msg: fd %d: not found", pfd->fd);
@@ -250,8 +252,7 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
if (msgbuf_write(&c->ibuf.w) <= 0 && errno != EAGAIN)
return control_close(c);
if (c->throttled && c->ibuf.w.queued < CTL_MSG_LOW_MARK) {
- if (imsg_ctl_rde(IMSG_XON, 0, c->ibuf.pid, NULL, 0) !=
- -1)
+ if (imsg_ctl_rde_msg(IMSG_XON, 0, c->ibuf.pid) != -1)
c->throttled = 0;
}
}
@@ -270,8 +271,10 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
if (n == 0)
break;
+ type = imsg_get_type(&imsg);
+ pid = imsg_get_pid(&imsg);
if (c->restricted) {
- switch (imsg.hdr.type) {
+ switch (type) {
case IMSG_CTL_SHOW_NEIGHBOR:
case IMSG_CTL_SHOW_NEXTHOP:
case IMSG_CTL_SHOW_INTERFACE:
@@ -287,20 +290,25 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
break;
default:
/* clear imsg type to prevent processing */
- imsg.hdr.type = IMSG_NONE;
+ type = IMSG_NONE;
control_result(c, CTL_RES_DENIED);
break;
}
}
- switch (imsg.hdr.type) {
+ /*
+ * TODO: this is wrong and shoud work the other way around.
+ * The imsg.hdr.pid is from the remote end and should not
+ * be trusted.
+ */
+ c->ibuf.pid = pid;
+ switch (type) {
case IMSG_NONE:
/* message was filtered out, nothing to do */
break;
case IMSG_CTL_FIB_COUPLE:
case IMSG_CTL_FIB_DECOUPLE:
- imsg_ctl_parent(imsg.hdr.type, imsg.hdr.peerid,
- 0, NULL, 0);
+ imsg_ctl_parent(&imsg);
break;
case IMSG_CTL_SHOW_TERSE:
RB_FOREACH(p, peer_head, peers)
@@ -309,23 +317,19 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
break;
case IMSG_CTL_SHOW_NEIGHBOR:
- c->ibuf.pid = imsg.hdr.pid;
+ if (imsg_get_data(&imsg, &neighbor,
+ sizeof(neighbor)) == -1)
+ memset(&neighbor, 0, sizeof(neighbor));
- if (imsg.hdr.len == IMSG_HEADER_SIZE +
- sizeof(struct ctl_neighbor)) {
- neighbor = imsg.data;
- } else {
- neighbor = NULL;
- }
matched = 0;
RB_FOREACH(p, peer_head, peers) {
- if (!peer_matched(p, neighbor))
+ if (!peer_matched(p, &neighbor))
continue;
matched = 1;
- if (!neighbor || !neighbor->show_timers) {
- imsg_ctl_rde(imsg.hdr.type, p->conf.id,
- imsg.hdr.pid, NULL, 0);
+ if (!neighbor.show_timers) {
+ imsg_ctl_rde_msg(type,
+ p->conf.id, pid);
} else {
u_int i;
time_t d;
@@ -348,9 +352,8 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
}
if (!matched && RB_EMPTY(peers)) {
control_result(c, CTL_RES_NOSUCHPEER);
- } else if (!neighbor || !neighbor->show_timers) {
- imsg_ctl_rde(IMSG_CTL_END, 0, imsg.hdr.pid,
- NULL, 0);
+ } else if (!neighbor.show_timers) {
+ imsg_ctl_rde_msg(IMSG_CTL_END, 0, pid);
} else {
imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1,
NULL, 0);
@@ -361,23 +364,21 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_CTL_NEIGHBOR_CLEAR:
case IMSG_CTL_NEIGHBOR_RREFRESH:
case IMSG_CTL_NEIGHBOR_DESTROY:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct ctl_neighbor)) {
+ if (imsg_get_data(&imsg, &neighbor,
+ sizeof(neighbor)) == -1) {
log_warnx("got IMSG_CTL_NEIGHBOR_ with "
"wrong length");
break;
}
- neighbor = imsg.data;
-
matched = 0;
RB_FOREACH(p, peer_head, peers) {
- if (!peer_matched(p, neighbor))
+ if (!peer_matched(p, &neighbor))
continue;
matched = 1;
- switch (imsg.hdr.type) {
+ switch (type) {
case IMSG_CTL_NEIGHBOR_UP:
bgp_fsm(p, EVNT_START);
p->conf.down = 0;
@@ -388,22 +389,20 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_DOWN:
- neighbor->reason[
- sizeof(neighbor->reason) - 1] =
- '\0';
+ neighbor.reason[
+ sizeof(neighbor.reason) - 1] = '\0';
strlcpy(p->conf.reason,
- neighbor->reason,
+ neighbor.reason,
sizeof(p->conf.reason));
p->conf.down = 1;
session_stop(p, ERR_CEASE_ADMIN_DOWN);
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_CLEAR:
- neighbor->reason[
- sizeof(neighbor->reason) - 1] =
- '\0';
+ neighbor.reason[
+ sizeof(neighbor.reason) - 1] = '\0';
strlcpy(p->conf.reason,
- neighbor->reason,
+ neighbor.reason,
sizeof(p->conf.reason));
p->IdleHoldTime =
INTERVAL_IDLE_HOLD_INITIAL;
@@ -455,51 +454,40 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_CTL_SHOW_INTERFACE:
case IMSG_CTL_SHOW_FIB_TABLES:
case IMSG_CTL_SHOW_RTR:
- c->ibuf.pid = imsg.hdr.pid;
- imsg_ctl_parent(imsg.hdr.type, 0, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+ imsg_ctl_parent(&imsg);
break;
case IMSG_CTL_KROUTE:
case IMSG_CTL_KROUTE_ADDR:
case IMSG_CTL_SHOW_NEXTHOP:
- c->ibuf.pid = imsg.hdr.pid;
- imsg_ctl_parent(imsg.hdr.type, imsg.hdr.peerid,
- imsg.hdr.pid, imsg.data, imsg.hdr.len -
- IMSG_HEADER_SIZE);
+ imsg_ctl_parent(&imsg);
break;
case IMSG_CTL_SHOW_RIB:
case IMSG_CTL_SHOW_RIB_PREFIX:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct ctl_show_rib_request)) {
+ if (imsg_get_data(&imsg, &ribreq, sizeof(ribreq)) ==
+ -1) {
log_warnx("got IMSG_CTL_SHOW_RIB with "
"wrong length");
break;
}
- ribreq = imsg.data;
- neighbor = &ribreq->neighbor;
-
/* check if at least one neighbor exists */
RB_FOREACH(p, peer_head, peers)
- if (peer_matched(p, neighbor))
+ if (peer_matched(p, &ribreq.neighbor))
break;
if (p == NULL && RB_EMPTY(peers)) {
control_result(c, CTL_RES_NOSUCHPEER);
break;
}
- if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX)
- && (ribreq->prefix.aid == AID_UNSPEC)) {
+ if (type == IMSG_CTL_SHOW_RIB_PREFIX &&
+ ribreq.prefix.aid == AID_UNSPEC) {
/* malformed request, must specify af */
control_result(c, CTL_RES_PARSE_ERROR);
break;
}
- c->ibuf.pid = imsg.hdr.pid;
c->terminate = 1;
-
- imsg_ctl_rde(imsg.hdr.type, 0, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+ imsg_ctl_rde(&imsg);
break;
case IMSG_CTL_SHOW_NETWORK:
case IMSG_CTL_SHOW_FLOWSPEC:
@@ -507,9 +495,7 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
/* FALLTHROUGH */
case IMSG_CTL_SHOW_RIB_MEM:
case IMSG_CTL_SHOW_SET:
- c->ibuf.pid = imsg.hdr.pid;
- imsg_ctl_rde(imsg.hdr.type, 0, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+ imsg_ctl_rde(&imsg);
break;
case IMSG_NETWORK_ADD:
case IMSG_NETWORK_ASPATH:
@@ -522,21 +508,16 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_FLOWSPEC_DONE:
case IMSG_FLOWSPEC_FLUSH:
case IMSG_FILTER_SET:
- imsg_ctl_rde(imsg.hdr.type, 0, 0,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
+ imsg_ctl_rde(&imsg);
break;
case IMSG_CTL_LOG_VERBOSE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(verbose))
+ if (imsg_get_data(&imsg, &verbose, sizeof(verbose)) ==
+ -1)
break;
/* forward to other processes */
- imsg_ctl_parent(imsg.hdr.type, 0, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
- imsg_ctl_rde(imsg.hdr.type, 0, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
-
- memcpy(&verbose, imsg.data, sizeof(verbose));
+ imsg_ctl_parent(&imsg);
+ imsg_ctl_rde(&imsg);
log_setverbose(verbose);
break;
default:
@@ -552,23 +533,28 @@ int
control_imsg_relay(struct imsg *imsg, struct peer *p)
{
struct ctl_conn *c;
+ uint32_t type;
+ pid_t pid;
- if ((c = control_connbypid(imsg->hdr.pid)) == NULL)
+ type = imsg_get_type(imsg);
+ pid = imsg_get_pid(imsg);
+
+ if ((c = control_connbypid(pid)) == NULL)
return (0);
/* special handling for peers since only the stats are sent from RDE */
- if (imsg->hdr.type == IMSG_CTL_SHOW_NEIGHBOR) {
+ if (type == IMSG_CTL_SHOW_NEIGHBOR) {
struct rde_peer_stats stats;
- if (imsg->hdr.len > IMSG_HEADER_SIZE + sizeof(stats)) {
- log_warnx("wrong imsg len");
+ if (p == NULL) {
+ log_warnx("%s: no such peer: id=%u", __func__,
+ imsg_get_id(imsg));
return (0);
}
- if (p == NULL) {
- log_warnx("no such peer: id=%u", imsg->hdr.peerid);
+ if (imsg_get_data(imsg, &stats, sizeof(stats)) == -1) {
+ log_warnx("%s: imsg_get_data", __func__);
return (0);
}
- memcpy(&stats, imsg->data, sizeof(stats));
p->stats.prefix_cnt = stats.prefix_cnt;
p->stats.prefix_out_cnt = stats.prefix_out_cnt;
p->stats.prefix_rcvd_update = stats.prefix_rcvd_update;
@@ -580,21 +566,19 @@ control_imsg_relay(struct imsg *imsg, struct peer *p)
p->stats.pending_update = stats.pending_update;
p->stats.pending_withdraw = stats.pending_withdraw;
- return (imsg_compose(&c->ibuf, imsg->hdr.type, 0,
- imsg->hdr.pid, -1, p, sizeof(*p)));
+ return imsg_compose(&c->ibuf, type, 0, pid, -1, p, sizeof(*p));
}
/* if command finished no need to send exit message */
- if (imsg->hdr.type == IMSG_CTL_END || imsg->hdr.type == IMSG_CTL_RESULT)
+ if (type == IMSG_CTL_END || type == IMSG_CTL_RESULT)
c->terminate = 0;
if (!c->throttled && c->ibuf.w.queued > CTL_MSG_HIGH_MARK) {
- if (imsg_ctl_rde(IMSG_XOFF, 0, imsg->hdr.pid, NULL, 0) != -1)
+ if (imsg_ctl_rde_msg(IMSG_XOFF, 0, pid) != -1)
c->throttled = 1;
}
- return (imsg_compose(&c->ibuf, imsg->hdr.type, 0, imsg->hdr.pid, -1,
- imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE));
+ return (imsg_forward(&c->ibuf, imsg));
}
void
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index c3029ac7f7e..8e77c4f028b 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.456 2023/12/14 13:52:38 claudio Exp $ */
+/* $OpenBSD: session.c,v 1.457 2024/01/10 11:08:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@@ -3576,14 +3576,25 @@ session_up(struct peer *p)
}
int
-imsg_ctl_parent(int type, uint32_t peerid, pid_t pid, void *data,
- uint16_t datalen)
+imsg_ctl_parent(struct imsg *imsg)
{
- return imsg_compose(ibuf_main, type, peerid, pid, -1, data, datalen);
+ return imsg_forward(ibuf_main, imsg);
}
int
-imsg_ctl_rde(int type, uint32_t peerid, pid_t pid, void *data, uint16_t datalen)
+imsg_ctl_rde(struct imsg *imsg)
+{
+ if (ibuf_rde_ctl == NULL)
+ return (0);
+ /*
+ * Use control socket to talk to RDE to bypass the queue of the
+ * regular imsg socket.
+ */
+ return imsg_forward(ibuf_rde_ctl, imsg);
+}
+
+int
+imsg_ctl_rde_msg(int type, uint32_t peerid, pid_t pid)
{
if (ibuf_rde_ctl == NULL)
return (0);
@@ -3592,7 +3603,7 @@ imsg_ctl_rde(int type, uint32_t peerid, pid_t pid, void *data, uint16_t datalen)
* Use control socket to talk to RDE to bypass the queue of the
* regular imsg socket.
*/
- return imsg_compose(ibuf_rde_ctl, type, peerid, pid, -1, data, datalen);
+ return imsg_compose(ibuf_rde_ctl, type, peerid, pid, -1, NULL, 0);
}
int
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index b5aa040ce79..dfe90943b7e 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.164 2023/10/19 07:02:46 claudio Exp $ */
+/* $OpenBSD: session.h,v 1.165 2024/01/10 11:08:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -339,8 +339,9 @@ struct peer *getpeerbydesc(struct bgpd_config *, const char *);
struct peer *getpeerbyip(struct bgpd_config *, struct sockaddr *);
struct peer *getpeerbyid(struct bgpd_config *, uint32_t);
int peer_matched(struct peer *, struct ctl_neighbor *);
-int imsg_ctl_parent(int, uint32_t, pid_t, void *, uint16_t);
-int imsg_ctl_rde(int, uint32_t, pid_t, void *, uint16_t);
+int imsg_ctl_parent(struct imsg *);
+int imsg_ctl_rde(struct imsg *);
+int imsg_ctl_rde_msg(int, uint32_t, pid_t);
void session_stop(struct peer *, uint8_t);
/* timer.c */