b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3] alfred: introduce 'server status' IPC call
@ 2022-02-09 16:43 Marek Lindner
  2022-02-20  9:20 ` Sven Eckelmann
  0 siblings, 1 reply; 2+ messages in thread
From: Marek Lindner @ 2022-02-09 16:43 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Marek Lindner

The 'server status' call exports the 'mode' as well as interface
status via IPC. Both parameters can be modified at runtime via the
IPC and as such, the current configuration is dynamic and not
necessarily obvious.

The server status 'request' and 'reply' packet types are added
to allow the IPC client to initiate the status retrieval. The
server will respond with the 'reply' message.

The information is encapsulated in TLV data chunks allowing for
future backward compatible extension of the server status call.

Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
---
v3:
 - close client socket at the end of unix_sock_server_status()

 alfred.h     |   2 +
 client.c     | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++
 main.c       |   9 +++-
 man/alfred.8 |   3 ++
 packet.h     |  65 +++++++++++++++++++++++++++++
 unix_sock.c  |  90 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 284 insertions(+), 1 deletion(-)

diff --git a/alfred.h b/alfred.h
index 9ab92a2..3d1d72a 100644
--- a/alfred.h
+++ b/alfred.h
@@ -93,6 +93,7 @@ enum clientmode {
 	CLIENT_MODESWITCH,
 	CLIENT_CHANGE_INTERFACE,
 	CLIENT_CHANGE_BAT_IFACE,
+	CLIENT_SERVER_STATUS,
 };
 
 struct interface {
@@ -155,6 +156,7 @@ int alfred_client_set_data(struct globals *globals);
 int alfred_client_modeswitch(struct globals *globals);
 int alfred_client_change_interface(struct globals *globals);
 int alfred_client_change_bat_iface(struct globals *globals);
+int alfred_client_server_status(struct globals *globals);
 /* recv.c */
 int recv_alfred_packet(struct globals *globals, struct interface *interface,
 		       int recv_sock);
diff --git a/client.c b/client.c
index b5d8943..41ee640 100644
--- a/client.c
+++ b/client.c
@@ -325,3 +325,119 @@ int alfred_client_change_bat_iface(struct globals *globals)
 
 	return 0;
 }
+
+int alfred_client_server_status(struct globals *globals)
+{
+	struct alfred_server_status_net_iface *status_net_iface;
+	struct alfred_server_status_bat_iface *status_bat_iface;
+	struct alfred_server_status_op_mode *status_op_mode;
+	struct alfred_server_status_req_v0 status_req;
+	struct alfred_server_status_rep_v0 *status_rep;
+	int ret, tlvsize, headsize, len, consumed;
+	struct alfred_tlv *status_tlv;
+	uint8_t buf[MAX_PAYLOAD];
+
+	if (unix_sock_open_client(globals))
+		return -1;
+
+	len = sizeof(status_req);
+	memset(&status_req, 0, len);
+
+	status_req.header.type = ALFRED_SERVER_STATUS;
+	status_req.header.version = ALFRED_VERSION;
+	status_req.header.length = 0;
+
+	ret = write(globals->unix_sock, (unsigned char *)&status_req, len);
+	if (ret != len)
+		fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+			__func__, ret, len, strerror(errno));
+
+	len = read(globals->unix_sock, buf, sizeof(buf));
+	if (len <= 0) {
+		perror("read from unix socket failed");
+		goto err;
+	}
+
+	ret = -1;
+	status_rep = (struct alfred_server_status_rep_v0 *)buf;
+
+	/* drop too small packets */
+	headsize = sizeof(status_rep->header);
+	if (len < headsize) {
+		perror("unexpected header size received from unix socket");
+		goto err;
+	}
+
+	if ((len - headsize) < ((int)ntohs(status_rep->header.length))) {
+		perror("unexpected packet size received from unix socket");
+		goto err;
+	}
+
+	if (status_rep->header.version != ALFRED_VERSION) {
+		perror("alfred version mismatch");
+		goto err;
+	}
+
+	headsize = ntohs(status_rep->header.length);
+
+	if (headsize < (int)(sizeof(*status_rep) - sizeof(status_rep->header)))
+		goto err;
+
+	consumed = sizeof(*status_rep);
+
+	while (len - consumed > 0) {
+		if (len - consumed < (int)sizeof(*status_tlv))
+			break;
+
+		status_tlv = (struct alfred_tlv *)(buf + consumed);
+		consumed += sizeof(*status_tlv);
+
+		tlvsize = ntohs(status_tlv->length);
+		if (len - consumed < tlvsize)
+			break;
+
+		switch (status_tlv->type) {
+		case ALFRED_SERVER_OP_MODE:
+			if (tlvsize != sizeof(*status_op_mode))
+				break;
+
+			status_op_mode = (struct alfred_server_status_op_mode *)(buf + consumed);
+
+			switch (status_op_mode->mode) {
+			case ALFRED_MODESWITCH_SECONDARY:
+				fprintf(stdout, "- mode: secondary\n");
+				break;
+			case ALFRED_MODESWITCH_PRIMARY:
+				fprintf(stdout, "- mode: primary\n");
+				break;
+			default:
+				fprintf(stderr, "- mode: unknown\n");
+				break;
+			}
+
+			break;
+		case ALFRED_SERVER_NET_IFACE:
+			if (tlvsize != sizeof(struct alfred_server_status_net_iface))
+				break;
+
+			status_net_iface = (struct alfred_server_status_net_iface *)(buf + consumed);
+			fprintf(stderr, "- interface: %s\n", status_net_iface->net_iface);
+			fprintf(stderr, "\t- status: %s\n",
+				status_net_iface->active == 1 ? "active" : "inactive");
+			break;
+		case ALFRED_SERVER_BAT_IFACE:
+			if (tlvsize != sizeof(struct alfred_server_status_bat_iface))
+				break;
+
+			status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + consumed);
+			fprintf(stdout, "- batman-adv interface: %s\n", status_bat_iface->bat_iface);
+			break;
+		}
+
+		consumed += tlvsize;
+	}
+
+err:
+	unix_sock_close(globals);
+	return 0;
+}
diff --git a/main.c b/main.c
index d40a0cc..68d6efd 100644
--- a/main.c
+++ b/main.c
@@ -38,6 +38,7 @@ static void alfred_usage(void)
 	printf("                   secondary          switch daemon to mode secondary\n");
 	printf("  -I, --change-interface [interface]  change to the specified interface(s)\n");
 	printf("  -B, --change-bat-iface [interface]  change to the specified batman-adv interface\n");
+	printf("  -S, --server-status                 request server status info such as mode & interfaces\n");
 	printf("\n");
 	printf("server mode options:\n");
 	printf("  -i, --interface                     specify the interface (or comma separated list of interfaces) to listen on\n");
@@ -162,6 +163,7 @@ static struct globals *alfred_init(int argc, char *argv[])
 		{"modeswitch",		required_argument,	NULL,	'M'},
 		{"change-interface",	required_argument,	NULL,	'I'},
 		{"change-bat-iface",	required_argument,	NULL,	'B'},
+		{"server-status",	required_argument,	NULL,	'S'},
 		{"unix-path",		required_argument,	NULL,	'u'},
 		{"update-command",	required_argument,	NULL,	'c'},
 		{"version",		no_argument,		NULL,	'v'},
@@ -196,7 +198,7 @@ static struct globals *alfred_init(int argc, char *argv[])
 
 	time_random_seed();
 
-	while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:u:dc:p:4:f", long_options,
+	while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:Su:dc:p:4:f", long_options,
 				  &opt_ind)) != -1) {
 		switch (opt) {
 		case 'r':
@@ -258,6 +260,9 @@ static struct globals *alfred_init(int argc, char *argv[])
 			globals->clientmode = CLIENT_CHANGE_BAT_IFACE;
 			globals->mesh_iface = strdup(optarg);
 			break;
+		case 'S':
+			globals->clientmode = CLIENT_SERVER_STATUS;
+			break;
 		case 'u':
 			globals->unix_path = optarg;
 			break;
@@ -321,6 +326,8 @@ int main(int argc, char *argv[])
 		return alfred_client_change_interface(globals);
 	case CLIENT_CHANGE_BAT_IFACE:
 		return alfred_client_change_bat_iface(globals);
+	case CLIENT_SERVER_STATUS:
+		return alfred_client_server_status(globals);
 	}
 
 	return 0;
diff --git a/man/alfred.8 b/man/alfred.8
index 74814e0..cf0eafc 100644
--- a/man/alfred.8
+++ b/man/alfred.8
@@ -94,6 +94,9 @@ Change the alfred server to use the new \fBinterface\fP(s)
 .TP
 \fB\-B\fP, \fB\-\-change\-bat\-iface\fP \fIinterface\fP
 Change the alfred server to use the new \fBbatman-adv interface\fP
+.TP
+\fB\-S\fP, \fB\-\-server\-status\fP
+Request server status information such as mode & interfaces\fP
 .
 .SH SERVER OPTIONS
 .TP
diff --git a/packet.h b/packet.h
index 94c6a77..4b6bde5 100644
--- a/packet.h
+++ b/packet.h
@@ -69,6 +69,7 @@ enum alfred_packet_type {
 	ALFRED_MODESWITCH = 5,
 	ALFRED_CHANGE_INTERFACE = 6,
 	ALFRED_CHANGE_BAT_IFACE = 7,
+	ALFRED_SERVER_STATUS = 8,
 };
 
 /* packets */
@@ -159,6 +160,70 @@ struct alfred_change_interface_v0 {
 struct alfred_change_bat_iface_v0 {
 	struct alfred_tlv header;
 	char bat_iface[IFNAMSIZ];
+};
+
+/**
+ * enum alfred_packet_type - Types of packet stored in the main alfred_tlv
+ * @ALFRED_SERVER_MODE: Contains alfred mode information*
+ * @ALFRED_SERVER_NET_IFACE: Contains alfred network interface information*
+ * @ALFRED_SERVER_BAT_IFACE: Contains alfred batman interface information*
+ */
+enum alfred_server_status_type {
+	ALFRED_SERVER_OP_MODE = 0,
+	ALFRED_SERVER_NET_IFACE = 1,
+	ALFRED_SERVER_BAT_IFACE = 2,
+};
+
+/**
+ * struct alfred_server_status_req_v0 - server status request
+ * @header: TLV header describing the complete packet
+ *
+ * Sent to the daemon by client
+ */
+struct alfred_server_status_req_v0 {
+	struct alfred_tlv header;
+} __packed;
+
+/**
+ * struct alfred_server_status_op_mode - server op mode status information
+ * @op_mode: active op mode
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_op_mode {
+	uint8_t mode;
+} __packed;
+
+/**
+ * struct alfred_server_status_net_iface - server net iface status information
+ * @net_iface: configured network interface
+ * @active: network interface active/inactive status info
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_net_iface {
+	char net_iface[IFNAMSIZ];
+	uint8_t active;
+} __packed;
+
+/**
+ * struct alfred_server_status_bat_iface - server bat iface status information
+ * @op_mode: configured batman interface
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_bat_iface {
+	char bat_iface[IFNAMSIZ];
+} __packed;
+
+/**
+ * struct alfred_server_status_rep_v0 - server status reply
+ * @header: TLV header describing the complete packet
+ *
+ * Sent by the daemon to client in response to status request
+ */
+struct alfred_server_status_rep_v0 {
+	struct alfred_tlv header;
 } __packed;
 
 /**
diff --git a/unix_sock.c b/unix_sock.c
index bc39199..9d4b1ca 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -366,6 +366,93 @@ err:
 	return ret;
 }
 
+static int unix_sock_server_status(struct globals *globals, int client_sock)
+{
+	struct alfred_server_status_net_iface *status_net_iface;
+	struct alfred_server_status_bat_iface *status_bat_iface;
+	struct alfred_server_status_op_mode *status_op_mode;
+	struct alfred_server_status_rep_v0 *status_rep;
+	struct alfred_tlv *status_tlv;
+	struct interface *interface;
+	uint8_t buf[MAX_PAYLOAD];
+	int ret, len;
+
+	len = sizeof(*status_rep);
+
+	status_rep = (struct alfred_server_status_rep_v0 *)buf;
+	status_rep->header.type = ALFRED_SERVER_STATUS;
+	status_rep->header.version = ALFRED_VERSION;
+	status_rep->header.length = len;
+
+	status_tlv = (struct alfred_tlv *)(buf + len);
+	status_tlv->type = ALFRED_SERVER_OP_MODE;
+	status_tlv->version = ALFRED_VERSION;
+	status_tlv->length = htons(sizeof(*status_op_mode));
+	len += sizeof(*status_tlv);
+
+	status_op_mode = (struct alfred_server_status_op_mode *)(buf + len);
+
+	switch (globals->opmode) {
+	case OPMODE_SECONDARY:
+		status_op_mode->mode = ALFRED_MODESWITCH_SECONDARY;
+		break;
+	case OPMODE_PRIMARY:
+		status_op_mode->mode = ALFRED_MODESWITCH_PRIMARY;
+		break;
+	default:
+		break;
+	}
+
+	len += sizeof(*status_op_mode);
+
+	list_for_each_entry(interface, &globals->interfaces, list) {
+		status_tlv = (struct alfred_tlv *)(buf + len);
+		status_tlv->type = ALFRED_SERVER_NET_IFACE;
+		status_tlv->version = ALFRED_VERSION;
+		status_tlv->length = htons(sizeof(*status_net_iface));
+		len += sizeof(*status_tlv);
+
+		status_net_iface = (struct alfred_server_status_net_iface *)(buf + len);
+		strncpy(status_net_iface->net_iface, interface->interface,
+			sizeof(status_net_iface->net_iface));
+		status_net_iface->net_iface[sizeof(status_net_iface->net_iface) - 1] = '\0';
+		if (interface->netsock > -1)
+			status_net_iface->active = 1;
+		else
+			status_net_iface->active = 0;
+		len += sizeof(*status_net_iface);
+	}
+
+	status_tlv = (struct alfred_tlv *)(buf + len);
+	status_tlv->type = ALFRED_SERVER_BAT_IFACE;
+	status_tlv->version = ALFRED_VERSION;
+	status_tlv->length = htons(sizeof(*status_bat_iface));
+	len += sizeof(*status_tlv);
+
+	status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + len);
+	strncpy(status_bat_iface->bat_iface, globals->mesh_iface,
+		sizeof(status_bat_iface->bat_iface));
+	status_bat_iface->bat_iface[sizeof(status_bat_iface->bat_iface) - 1] = '\0';
+	len += sizeof(*status_bat_iface);
+
+	status_rep->header.length = htons(len - sizeof(status_rep->header));
+
+	ret = write(client_sock, buf, len);
+
+	if (ret != len) {
+		fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+			__func__, ret, len, strerror(errno));
+		ret = -1;
+		goto err;
+	}
+
+	ret = 0;
+
+err:
+	close(client_sock);
+	return ret;
+}
+
 int unix_sock_read(struct globals *globals)
 {
 	int client_sock;
@@ -428,6 +515,9 @@ int unix_sock_read(struct globals *globals)
 						 (struct alfred_change_bat_iface_v0 *)packet,
 						 client_sock);
 		break;
+	case ALFRED_SERVER_STATUS:
+		ret = unix_sock_server_status(globals, client_sock);
+		break;
 	default:
 		/* unknown packet type */
 		ret = -1;
-- 
2.32.0.rc0

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v3] alfred: introduce 'server status' IPC call
  2022-02-09 16:43 [PATCH v3] alfred: introduce 'server status' IPC call Marek Lindner
@ 2022-02-20  9:20 ` Sven Eckelmann
  0 siblings, 0 replies; 2+ messages in thread
From: Sven Eckelmann @ 2022-02-20  9:20 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Marek Lindner


[-- Attachment #1.1: Type: text/plain, Size: 1052 bytes --]

On Wednesday, 9 February 2022 17:43:54 CET Marek Lindner wrote:
> The 'server status' call exports the 'mode' as well as interface
> status via IPC. Both parameters can be modified at runtime via the
> IPC and as such, the current configuration is dynamic and not
> necessarily obvious.
> 
> The server status 'request' and 'reply' packet types are added
> to allow the IPC client to initiate the status retrieval. The
> server will respond with the 'reply' message.
> 
> The information is encapsulated in TLV data chunks allowing for
> future backward compatible extension of the server status call.
> 
> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
> ---
> v3:
>  - close client socket at the end of unix_sock_server_status()

Things I've noticed are:

* there are no safety checks for the buffer size in the server code
* the packet/tlv type definitions don't include the header (unlike the rest of 
  the code)
* version checks for the "sub tlv" types is missing

Attached is a rough sketch of potential changes.

Kind regards,
	Sven

[-- Attachment #1.2: include-tlv-in-packet.patch --]
[-- Type: text/x-patch, Size: 8074 bytes --]

diff --git a/client.c b/client.c
index 41ee640..6a58196 100644
--- a/client.c
+++ b/client.c
@@ -328,9 +328,9 @@ int alfred_client_change_bat_iface(struct globals *globals)
 
 int alfred_client_server_status(struct globals *globals)
 {
-	struct alfred_server_status_net_iface *status_net_iface;
-	struct alfred_server_status_bat_iface *status_bat_iface;
-	struct alfred_server_status_op_mode *status_op_mode;
+	struct alfred_server_status_net_iface_v0 *status_net_iface;
+	struct alfred_server_status_bat_iface_v0 *status_bat_iface;
+	struct alfred_server_status_op_mode_v0 *status_op_mode;
 	struct alfred_server_status_req_v0 status_req;
 	struct alfred_server_status_rep_v0 *status_rep;
 	int ret, tlvsize, headsize, len, consumed;
@@ -390,9 +390,11 @@ int alfred_client_server_status(struct globals *globals)
 			break;
 
 		status_tlv = (struct alfred_tlv *)(buf + consumed);
-		consumed += sizeof(*status_tlv);
+		if (status_tlv->version != ALFRED_VERSION)
+			break;
 
 		tlvsize = ntohs(status_tlv->length);
+		tlvsize += sizeof(*status_tlv);
 		if (len - consumed < tlvsize)
 			break;
 
@@ -401,7 +403,7 @@ int alfred_client_server_status(struct globals *globals)
 			if (tlvsize != sizeof(*status_op_mode))
 				break;
 
-			status_op_mode = (struct alfred_server_status_op_mode *)(buf + consumed);
+			status_op_mode = (struct alfred_server_status_op_mode_v0 *)(buf + consumed);
 
 			switch (status_op_mode->mode) {
 			case ALFRED_MODESWITCH_SECONDARY:
@@ -417,19 +419,19 @@ int alfred_client_server_status(struct globals *globals)
 
 			break;
 		case ALFRED_SERVER_NET_IFACE:
-			if (tlvsize != sizeof(struct alfred_server_status_net_iface))
+			if (tlvsize != sizeof(*status_net_iface))
 				break;
 
-			status_net_iface = (struct alfred_server_status_net_iface *)(buf + consumed);
+			status_net_iface = (struct alfred_server_status_net_iface_v0 *)(buf + consumed);
 			fprintf(stderr, "- interface: %s\n", status_net_iface->net_iface);
 			fprintf(stderr, "\t- status: %s\n",
 				status_net_iface->active == 1 ? "active" : "inactive");
 			break;
 		case ALFRED_SERVER_BAT_IFACE:
-			if (tlvsize != sizeof(struct alfred_server_status_bat_iface))
+			if (tlvsize != sizeof(*status_bat_iface))
 				break;
 
-			status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + consumed);
+			status_bat_iface = (struct alfred_server_status_bat_iface_v0 *)(buf + consumed);
 			fprintf(stdout, "- batman-adv interface: %s\n", status_bat_iface->bat_iface);
 			break;
 		}
diff --git a/packet.h b/packet.h
index 4b6bde5..0c1a2eb 100644
--- a/packet.h
+++ b/packet.h
@@ -185,34 +185,37 @@ struct alfred_server_status_req_v0 {
 } __packed;
 
 /**
- * struct alfred_server_status_op_mode - server op mode status information
+ * struct alfred_server_status_op_mode_v0 - server op mode status information
  * @op_mode: active op mode
  *
  * Sent to the client by daemon in response to status request
  */
-struct alfred_server_status_op_mode {
+struct alfred_server_status_op_mode_v0 {
+	struct alfred_tlv header;
 	uint8_t mode;
 } __packed;
 
 /**
- * struct alfred_server_status_net_iface - server net iface status information
+ * struct alfred_server_status_net_iface_v0 - server net iface status information
  * @net_iface: configured network interface
  * @active: network interface active/inactive status info
  *
  * Sent to the client by daemon in response to status request
  */
-struct alfred_server_status_net_iface {
+struct alfred_server_status_net_iface_v0 {
+	struct alfred_tlv header;
 	char net_iface[IFNAMSIZ];
 	uint8_t active;
 } __packed;
 
 /**
- * struct alfred_server_status_bat_iface - server bat iface status information
+ * struct alfred_server_status_bat_iface_v0 - server bat iface status information
  * @op_mode: configured batman interface
  *
  * Sent to the client by daemon in response to status request
  */
-struct alfred_server_status_bat_iface {
+struct alfred_server_status_bat_iface_v0 {
+	struct alfred_tlv header;
 	char bat_iface[IFNAMSIZ];
 } __packed;
 
diff --git a/unix_sock.c b/unix_sock.c
index af5206b..b2727ad 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -370,29 +370,38 @@ err:
 
 static int unix_sock_server_status(struct globals *globals, int client_sock)
 {
-	struct alfred_server_status_net_iface *status_net_iface;
-	struct alfred_server_status_bat_iface *status_bat_iface;
-	struct alfred_server_status_op_mode *status_op_mode;
+	struct alfred_server_status_net_iface_v0 *status_net_iface;
+	struct alfred_server_status_bat_iface_v0 *status_bat_iface;
+	struct alfred_server_status_op_mode_v0 *status_op_mode;
 	struct alfred_server_status_rep_v0 *status_rep;
-	struct alfred_tlv *status_tlv;
 	struct interface *interface;
 	uint8_t buf[MAX_PAYLOAD];
-	int ret, len;
+	int ret = -1;
+	int len;
+
+	len = 0;
 
-	len = sizeof(*status_rep);
+	/* too large? - should never happen */
+	if (sizeof(*status_rep) + len > sizeof(buf)) {
+		fprintf(stderr, "ERROR: send buffer too small for server_status\n");
+		goto err;
+	}
 
 	status_rep = (struct alfred_server_status_rep_v0 *)buf;
 	status_rep->header.type = ALFRED_SERVER_STATUS;
 	status_rep->header.version = ALFRED_VERSION;
-	status_rep->header.length = len;
+	len += sizeof(*status_rep);
 
-	status_tlv = (struct alfred_tlv *)(buf + len);
-	status_tlv->type = ALFRED_SERVER_OP_MODE;
-	status_tlv->version = ALFRED_VERSION;
-	status_tlv->length = htons(sizeof(*status_op_mode));
-	len += sizeof(*status_tlv);
+	/* too large? - should never happen */
+	if (sizeof(*status_op_mode) + len > sizeof(buf)) {
+		fprintf(stderr, "ERROR: send buffer too small for server_status op_mode\n");
+		goto err;
+	}
 
 	status_op_mode = (struct alfred_server_status_op_mode *)(buf + len);
+	status_op_mode->header.type = ALFRED_SERVER_OP_MODE;
+	status_op_mode->header.version = ALFRED_VERSION;
+	status_op_mode->header.length = FIXED_TLV_LEN(*status_op_mode);
 
 	switch (globals->opmode) {
 	case OPMODE_SECONDARY:
@@ -408,13 +417,17 @@ static int unix_sock_server_status(struct globals *globals, int client_sock)
 	len += sizeof(*status_op_mode);
 
 	list_for_each_entry(interface, &globals->interfaces, list) {
-		status_tlv = (struct alfred_tlv *)(buf + len);
-		status_tlv->type = ALFRED_SERVER_NET_IFACE;
-		status_tlv->version = ALFRED_VERSION;
-		status_tlv->length = htons(sizeof(*status_net_iface));
-		len += sizeof(*status_tlv);
+		/* too large? - should never happen */
+		if (sizeof(*status_net_iface) + len > sizeof(buf)) {
+			fprintf(stderr, "ERROR: send buffer too small for server_status iface\n");
+			goto err;
+		}
 
 		status_net_iface = (struct alfred_server_status_net_iface *)(buf + len);
+		status_net_iface->header.type = ALFRED_SERVER_NET_IFACE;
+		status_net_iface->header.version = ALFRED_VERSION;
+		status_net_iface->header.length = FIXED_TLV_LEN(*status_net_iface);
+
 		strncpy(status_net_iface->net_iface, interface->interface,
 			sizeof(status_net_iface->net_iface));
 		status_net_iface->net_iface[sizeof(status_net_iface->net_iface) - 1] = '\0';
@@ -422,16 +435,21 @@ static int unix_sock_server_status(struct globals *globals, int client_sock)
 			status_net_iface->active = 1;
 		else
 			status_net_iface->active = 0;
+
 		len += sizeof(*status_net_iface);
 	}
 
-	status_tlv = (struct alfred_tlv *)(buf + len);
-	status_tlv->type = ALFRED_SERVER_BAT_IFACE;
-	status_tlv->version = ALFRED_VERSION;
-	status_tlv->length = htons(sizeof(*status_bat_iface));
-	len += sizeof(*status_tlv);
+	/* too large? - should never happen */
+	if (sizeof(*status_bat_iface) + len > sizeof(buf)) {
+		fprintf(stderr, "ERROR: send buffer too small for server_status op_mode\n");
+		goto err;
+	}
 
 	status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + len);
+	status_bat_iface->header.type = ALFRED_SERVER_BAT_IFACE;
+	status_bat_iface->header.version = ALFRED_VERSION;
+	status_bat_iface->header.length = FIXED_TLV_LEN(*status_bat_iface);
+
 	strncpy(status_bat_iface->bat_iface, globals->mesh_iface,
 		sizeof(status_bat_iface->bat_iface));
 	status_bat_iface->bat_iface[sizeof(status_bat_iface->bat_iface) - 1] = '\0';

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-02-20  9:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-09 16:43 [PATCH v3] alfred: introduce 'server status' IPC call Marek Lindner
2022-02-20  9:20 ` Sven Eckelmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).