Index | Thread | Search

From:
Rafael Sadowski <rafael@sizeofvoid.org>
Subject:
[3/7] relayd: convert control imsg forwarding to imsg_forward()
To:
tech@openbsd.org
Date:
Sun, 7 Jun 2026 09:01:24 +0200

Download raw body.

Thread
  • Rafael Sadowski:

    [3/7] relayd: convert control imsg forwarding to imsg_forward()

This is a series of commits for an imsg APIv2 rework in relayd. These
were committed and tested individually. They can be reviewed in their
entirety here:

gothub: https://rsadowski.gothub.org/?action=summary&headref=imsg_v2&path=relayd.git
PR: https://codeberg.org/rsadowski/relayd/pulls/1/files

commit cdac3e43ca7856c92948a16de7bd0e4ec3e12f26
Author: Rafael Sadowski <rafael@sizeofvoid.org>
Date:   Sat Jun 6 16:22:49 2026 +0200

    relayd: convert control imsg forwarding to imsg_forward()
    
    Rework control_imsg_forward() to forward the message unaltered via
    imsg_forward() instead of rebuilding it with imsg_compose_event().
    
    read the type via imsg_get_type(), dropping the manual header-length
    Switch to use read the payload with imsg_get_data() and checks and the
    memcpy() that wrote the data back into the imsg before forwarding.

diff --git a/control.c b/control.c
index 6c29f2b..fe829ce 100644
--- a/control.c
+++ b/control.c
@@ -228,7 +228,7 @@ control_dispatch_imsg(int fd, short event, void *arg)
 	struct imsg		 imsg;
 	struct ctl_id		 id;
 	int			 n;
-	int			 verbose;
+	int			 verb;
 	struct relayd		*env = cs->cs_env;
 	struct privsep		*ps = env->sc_ps;
 
@@ -238,7 +238,11 @@ control_dispatch_imsg(int fd, short event, void *arg)
 	}
 
 	if (event & EV_READ) {
-		if (imsgbuf_read(&c->iev.ibuf) != 1) {
+		switch (imsgbuf_read(&c->iev.ibuf)) {
+		case -1:
+			fatal("%s: imsgbuf_read", __func__);
+			break;
+		case 0:
 			control_close(fd, cs);
 			return;
 		}
@@ -262,13 +266,13 @@ control_dispatch_imsg(int fd, short event, void *arg)
 
 		if (c->waiting) {
 			log_debug("%s: unexpected imsg %d",
-			    __func__, imsg.hdr.type);
+			    __func__, imsg_get_type(&imsg));
 			imsg_free(&imsg);
 			control_close(fd, cs);
 			return;
 		}
 
-		switch (imsg.hdr.type) {
+		switch (imsg_get_type(&imsg)) {
 		case IMSG_CTL_SHOW_SUM:
 			show(c);
 			break;
@@ -276,85 +280,79 @@ control_dispatch_imsg(int fd, short event, void *arg)
 			show_sessions(c);
 			break;
 		case IMSG_CTL_RDR_DISABLE:
-			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
-				fatalx("invalid imsg header len");
-			memcpy(&id, imsg.data, sizeof(id));
+			if (imsg_get_data(&imsg, &id, sizeof(id)) == -1)
+				fatalx("%s: imsg_get_data", __func__);
+
 			if (disable_rdr(c, &id))
 				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			else {
-				memcpy(imsg.data, &id, sizeof(id));
-				control_imsg_forward(ps, &imsg);
+				control_imsg_forward(&imsg);
 				imsg_compose_event(&c->iev, IMSG_CTL_OK,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			}
 			break;
 		case IMSG_CTL_RDR_ENABLE:
-			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
-				fatalx("invalid imsg header len");
-			memcpy(&id, imsg.data, sizeof(id));
+			if (imsg_get_data(&imsg, &id, sizeof(id)) == -1)
+				fatalx("%s: imsg_get_data", __func__);
+
 			if (enable_rdr(c, &id))
 				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			else {
-				memcpy(imsg.data, &id, sizeof(id));
-				control_imsg_forward(ps, &imsg);
+				control_imsg_forward(&imsg);
 				imsg_compose_event(&c->iev, IMSG_CTL_OK,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			}
 			break;
 		case IMSG_CTL_TABLE_DISABLE:
-			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
-				fatalx("invalid imsg header len");
-			memcpy(&id, imsg.data, sizeof(id));
+			if (imsg_get_data(&imsg, &id, sizeof(id)) == -1)
+				fatalx("%s: imsg_get_data", __func__);
+
 			if (disable_table(c, &id))
 				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			else {
-				memcpy(imsg.data, &id, sizeof(id));
-				control_imsg_forward(ps, &imsg);
+				control_imsg_forward(&imsg);
 				imsg_compose_event(&c->iev, IMSG_CTL_OK,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			}
 			break;
 		case IMSG_CTL_TABLE_ENABLE:
-			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
-				fatalx("invalid imsg header len");
-			memcpy(&id, imsg.data, sizeof(id));
+			if (imsg_get_data(&imsg, &id, sizeof(id)) == -1)
+				fatalx("%s: imsg_get_data", __func__);
+
 			if (enable_table(c, &id))
 				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			else {
-				memcpy(imsg.data, &id, sizeof(id));
-				control_imsg_forward(ps, &imsg);
+				control_imsg_forward(&imsg);
 				imsg_compose_event(&c->iev, IMSG_CTL_OK,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			}
 			break;
 		case IMSG_CTL_HOST_DISABLE:
-			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
-				fatalx("invalid imsg header len");
-			memcpy(&id, imsg.data, sizeof(id));
+			if (imsg_get_data(&imsg, &id, sizeof(id)) == -1)
+				fatalx("%s: imsg_get_data", __func__);
+
 			if (disable_host(c, &id, NULL))
 				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			else {
-				memcpy(imsg.data, &id, sizeof(id));
-				control_imsg_forward(ps, &imsg);
+				control_imsg_forward(&imsg);
 				imsg_compose_event(&c->iev, IMSG_CTL_OK,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			}
 			break;
 		case IMSG_CTL_HOST_ENABLE:
-			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
-				fatalx("invalid imsg header len");
-			memcpy(&id, imsg.data, sizeof(id));
+			if (imsg_get_data(&imsg, &id, sizeof(id)) == -1)
+				fatalx("%s: imsg_get_data", __func__);
+
 			if (enable_host(c, &id, NULL))
 				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			else {
-				memcpy(imsg.data, &id, sizeof(id));
-				control_imsg_forward(ps, &imsg);
+				control_imsg_forward(&imsg);
 				imsg_compose_event(&c->iev, IMSG_CTL_OK,
 				    0, ps->ps_instance + 1, -1, NULL, 0);
 			}
@@ -381,21 +379,19 @@ control_dispatch_imsg(int fd, short event, void *arg)
 			c->flags |= CTL_CONN_NOTIFY;
 			break;
 		case IMSG_CTL_VERBOSE:
-			IMSG_SIZE_CHECK(&imsg, &verbose);
-
-			memcpy(&verbose, imsg.data, sizeof(verbose));
+			if (imsg_get_data(&imsg, &verb, sizeof(verb)) == -1)
+				fatalx("%s: imsg_get_data", __func__);
 
 			proc_forward_imsg(env->sc_ps, &imsg, PROC_PARENT);
 			proc_forward_imsg(env->sc_ps, &imsg, PROC_HCE);
 			proc_forward_imsg(env->sc_ps, &imsg, PROC_RELAY);
 
-			memcpy(imsg.data, &verbose, sizeof(verbose));
-			control_imsg_forward(ps, &imsg);
-			log_setverbose(verbose);
+			control_imsg_forward(&imsg);
+			log_setverbose(verb);
 			break;
 		default:
 			log_debug("%s: error handling imsg %d",
-			    __func__, imsg.hdr.type);
+			    __func__, imsg_get_type(&imsg));
 			break;
 		}
 		imsg_free(&imsg);
@@ -405,13 +401,15 @@ control_dispatch_imsg(int fd, short event, void *arg)
 }
 
 void
-control_imsg_forward(struct privsep *ps, struct imsg *imsg)
+control_imsg_forward(struct imsg *imsg)
 {
-	struct ctl_conn *c;
+        struct ctl_conn *c;
 
-	TAILQ_FOREACH(c, &ctl_conns, entry)
-		if (c->flags & CTL_CONN_NOTIFY)
-			imsg_compose_event(&c->iev, imsg->hdr.type,
-			    0, ps->ps_instance + 1, -1, imsg->data,
-			    imsg->hdr.len - IMSG_HEADER_SIZE);
+	TAILQ_FOREACH(c, &ctl_conns, entry) {
+		if (c->flags & CTL_CONN_NOTIFY) {
+			if (imsg_forward(&c->iev.ibuf, imsg) == -1)
+				fatal("%s: imsg_forward", __func__);
+			imsg_event_add(&c->iev);
+		}
+	}
 }
diff --git a/pfe.c b/pfe.c
index 0f865b8..0856ae9 100644
--- a/pfe.c
+++ b/pfe.c
@@ -124,7 +124,7 @@ pfe_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg)
 	struct table		*table;
 	struct ctl_status	 st;
 
-	control_imsg_forward(p->p_ps, imsg);
+	control_imsg_forward(imsg);
 
 	switch (imsg_get_type(imsg)) {
 	case IMSG_HOST_STATUS:
@@ -737,7 +737,7 @@ pfe_sync(void)
 			imsg.hdr.len = sizeof(id) + IMSG_HEADER_SIZE;
 			imsg.data = &id;
 			sync_table(env, rdr, active);
-			control_imsg_forward(env->sc_ps, &imsg);
+			control_imsg_forward(&imsg);
 		}
 
 		if (rdr->conf.flags & F_DOWN) {
@@ -750,7 +750,7 @@ pfe_sync(void)
 				imsg.hdr.len = sizeof(id) + IMSG_HEADER_SIZE;
 				imsg.data = &id;
 				sync_ruleset(env, rdr, 0);
-				control_imsg_forward(env->sc_ps, &imsg);
+				control_imsg_forward(&imsg);
 			}
 		} else if (!(rdr->conf.flags & F_ACTIVE_RULESET)) {
 			log_debug("%s: enabling ruleset", __func__);
@@ -760,7 +760,7 @@ pfe_sync(void)
 			imsg.hdr.len = sizeof(id) + IMSG_HEADER_SIZE;
 			imsg.data = &id;
 			sync_ruleset(env, rdr, 1);
-			control_imsg_forward(env->sc_ps, &imsg);
+			control_imsg_forward(&imsg);
 		}
 	}
 
diff --git a/relayd.h b/relayd.h
index 16fe2bf..373255e 100644
--- a/relayd.h
+++ b/relayd.h
@@ -1154,7 +1154,7 @@ int	 control_init(struct privsep *, struct control_sock *);
 int	 control_listen(struct control_sock *);
 void	 control_cleanup(struct control_sock *);
 void	 control_dispatch_imsg(int, short, void *);
-void	 control_imsg_forward(struct privsep *ps, struct imsg *);
+void	 control_imsg_forward(struct imsg *);
 struct ctl_conn	*
 	 control_connbyfd(int);