diff mbox series

[3/4] alfred: introduce 'change batman-adv interface' IPC call

Message ID 20220102113136.470299-3-mareklindner@neomailbox.ch
State Accepted, archived
Delegated to: Simon Wunderlich
Headers show
Series [1/4] alfred: remove meaningless printf() call | expand

Commit Message

Marek Lindner Jan. 2, 2022, 11:31 a.m. UTC
The batman-adv interface used by alfred can be changed at
runtime by sending the CHANGE_BAT_IFACE command via unix
socket.

Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
---
 alfred.h     |  4 +++-
 client.c     | 37 +++++++++++++++++++++++++++++++++++++
 main.c       | 10 +++++++++-
 man/alfred.8 |  3 +++
 packet.h     | 14 ++++++++++++++
 unix_sock.c  | 27 ++++++++++++++++++++++++++-
 6 files changed, 92 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/alfred.h b/alfred.h
index 57d7daf..0fc6dc6 100644
--- a/alfred.h
+++ b/alfred.h
@@ -89,6 +89,7 @@  enum clientmode {
 	CLIENT_SET_DATA,
 	CLIENT_MODESWITCH,
 	CLIENT_CHANGE_INTERFACE,
+	CLIENT_CHANGE_BAT_IFACE,
 };
 
 struct interface {
@@ -110,7 +111,7 @@  struct globals {
 
 	char *change_interface;
 	struct server *best_server;	/* NULL if we are a server ourselves */
-	const char *mesh_iface;
+	char *mesh_iface;
 	enum opmode opmode;
 	enum clientmode clientmode;
 	int clientmode_arg;
@@ -150,6 +151,7 @@  int alfred_client_request_data(struct globals *globals);
 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);
 /* recv.c */
 int recv_alfred_packet(struct globals *globals, struct interface *interface,
 		       int recv_sock);
diff --git a/client.c b/client.c
index dc643f3..e1107bf 100644
--- a/client.c
+++ b/client.c
@@ -296,3 +296,40 @@  int alfred_client_change_interface(struct globals *globals)
 
 	return 0;
 }
+
+int alfred_client_change_bat_iface(struct globals *globals)
+{
+	unsigned char buf[MAX_PAYLOAD];
+	struct alfred_change_bat_iface_v0 *change_bat_iface;
+	int ret, len;
+	size_t interface_len;
+
+	if (unix_sock_open_client(globals))
+		return -1;
+
+	interface_len = strlen(globals->mesh_iface);
+	if (interface_len > sizeof(change_bat_iface->bat_iface)) {
+		fprintf(stderr, "%s: batman-adv interface name list too long, not changing\n",
+			__func__);
+		return 0;
+	}
+
+	change_bat_iface = (struct alfred_change_bat_iface_v0 *)buf;
+	len = sizeof(*change_bat_iface);
+
+	change_bat_iface->header.type = ALFRED_CHANGE_BAT_IFACE;
+	change_bat_iface->header.version = ALFRED_VERSION;
+	change_bat_iface->header.length = htons(len - sizeof(change_bat_iface->header));
+	strncpy(change_bat_iface->bat_iface, globals->mesh_iface,
+		sizeof(change_bat_iface->bat_iface));
+	change_bat_iface->bat_iface[sizeof(change_bat_iface->bat_iface) - 1] = '\0';
+
+	ret = write(globals->unix_sock, buf, len);
+	if (ret != len)
+		fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+			__func__, ret, len, strerror(errno));
+
+	unix_sock_close(globals);
+
+	return 0;
+}
diff --git a/main.c b/main.c
index ad317cf..2cb6d44 100644
--- a/main.c
+++ b/main.c
@@ -37,6 +37,7 @@  static void alfred_usage(void)
 	printf("  -M, --modeswitch primary            switch daemon to mode primary\n");
 	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("\n");
 	printf("server mode options:\n");
 	printf("  -i, --interface                     specify the interface (or comma separated list of interfaces) to listen on\n");
@@ -160,6 +161,7 @@  static struct globals *alfred_init(int argc, char *argv[])
 		{"req-version",		required_argument,	NULL,	'V'},
 		{"modeswitch",		required_argument,	NULL,	'M'},
 		{"change-interface",	required_argument,	NULL,	'I'},
+		{"change-bat-iface",	required_argument,	NULL,	'B'},
 		{"unix-path",		required_argument,	NULL,	'u'},
 		{"update-command",	required_argument,	NULL,	'c'},
 		{"version",		no_argument,		NULL,	'v'},
@@ -194,7 +196,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:u:dc:p:4:f", long_options,
+	while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:u:dc:p:4:f", long_options,
 				  &opt_ind)) != -1) {
 		switch (opt) {
 		case 'r':
@@ -252,6 +254,10 @@  static struct globals *alfred_init(int argc, char *argv[])
 			globals->clientmode = CLIENT_CHANGE_INTERFACE;
 			globals->change_interface = strdup(optarg);
 			break;
+		case 'B':
+			globals->clientmode = CLIENT_CHANGE_BAT_IFACE;
+			globals->mesh_iface = strdup(optarg);
+			break;
 		case 'u':
 			globals->unix_path = optarg;
 			break;
@@ -313,6 +319,8 @@  int main(int argc, char *argv[])
 		return alfred_client_modeswitch(globals);
 	case CLIENT_CHANGE_INTERFACE:
 		return alfred_client_change_interface(globals);
+	case CLIENT_CHANGE_BAT_IFACE:
+		return alfred_client_change_bat_iface(globals);
 	}
 
 	return 0;
diff --git a/man/alfred.8 b/man/alfred.8
index ff9b315..74814e0 100644
--- a/man/alfred.8
+++ b/man/alfred.8
@@ -91,6 +91,9 @@  to 0 ('\fB\-V\fP 0').
 .TP
 \fB\-I\fP, \fB\-\-change\-interface\fP \fIinterface\fP
 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
 .
 .SH SERVER OPTIONS
 .TP
diff --git a/packet.h b/packet.h
index 678f939..94c6a77 100644
--- a/packet.h
+++ b/packet.h
@@ -68,6 +68,7 @@  enum alfred_packet_type {
 	ALFRED_STATUS_ERROR = 4,
 	ALFRED_MODESWITCH = 5,
 	ALFRED_CHANGE_INTERFACE = 6,
+	ALFRED_CHANGE_BAT_IFACE = 7,
 };
 
 /* packets */
@@ -147,6 +148,19 @@  struct alfred_change_interface_v0 {
 	char ifaces[IFNAMSIZ * 16];
 } __packed;
 
+/**
+ * struct alfred_change_bat_iface_v0 - Request to change the
+ * batman-adv interface
+ * @header: TLV header describing the complete packet
+ * @bat_iface: interface to be changed to
+ *
+ * Sent to the daemon by client
+ */
+struct alfred_change_bat_iface_v0 {
+	struct alfred_tlv header;
+	char bat_iface[IFNAMSIZ];
+} __packed;
+
 /**
  * struct alfred_status_v0 - Status info of a transaction
  * @header: TLV header describing the complete packet
diff --git a/unix_sock.c b/unix_sock.c
index d9ad07b..bc39199 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -345,6 +345,27 @@  err:
 	return ret;
 }
 
+static int
+unix_sock_change_bat_iface(struct globals *globals,
+			   struct alfred_change_bat_iface_v0 *change_bat_iface,
+			   int client_sock)
+{
+	int len, ret = -1;
+
+	len = ntohs(change_bat_iface->header.length);
+
+	if (len < (int)(sizeof(*change_bat_iface) - sizeof(change_bat_iface->header)))
+		goto err;
+
+	free(globals->mesh_iface);
+	globals->mesh_iface = strdup(change_bat_iface->bat_iface);
+
+	ret = 0;
+err:
+	close(client_sock);
+	return ret;
+}
+
 int unix_sock_read(struct globals *globals)
 {
 	int client_sock;
@@ -402,7 +423,11 @@  int unix_sock_read(struct globals *globals)
 					     (struct alfred_change_interface_v0 *)packet,
 					     client_sock);
 		break;
-
+	case ALFRED_CHANGE_BAT_IFACE:
+		ret = unix_sock_change_bat_iface(globals,
+						 (struct alfred_change_bat_iface_v0 *)packet,
+						 client_sock);
+		break;
 	default:
 		/* unknown packet type */
 		ret = -1;