Update the control.c code to use the new imsg API.
authorclaudio <claudio@openbsd.org>
Wed, 10 Jan 2024 11:08:04 +0000 (11:08 +0000)
committerclaudio <claudio@openbsd.org>
Wed, 10 Jan 2024 11:08:04 +0000 (11:08 +0000)
OK tb@

usr.sbin/bgpd/control.c
usr.sbin/bgpd/session.c
usr.sbin/bgpd/session.h

index 79c548e..300822a 100644 (file)
@@ -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
index c3029ac..8e77c4f 100644 (file)
@@ -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
index b5aa040..dfe9094 100644 (file)
@@ -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 */