[PATCH 4/6] alfred: keep the running interfaces when reconfiguration fails

Sven Eckelmann <[email protected]> Fri, 31 Jul 2026 13:44:53 +0200
Newsgroups org.open-mesh.lists.batman
Message-ID <[email protected]>
netsock_set_interfaces() tore down the existing interface list with
netsock_close_all() before building the new one. When an allocation failed
while building the replacement it called netsock_close_all() again and
returned -ENOMEM, leaving the daemon with no interfaces at all.

Build the replacement into a temporary list first and only swap it in once
it is complete. On failure the temporary list is discarded and the running
interfaces are kept intact.

Signed-off-by: Sven Eckelmann <[email protected]>
---
 netsock.c   | 41 +++++++++++++++++++++++++++--------------
 unix_sock.c |  7 +++++--
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/netsock.c b/netsock.c
index 60b2285..3505041 100644
--- a/netsock.c
+++ b/netsock.c
@@ -100,12 +100,12 @@ struct interface *netsock_first_interface(struct globals *globals)
 	return NULL;
 }
 
-static struct interface *netsock_find_interface(struct globals *globals,
+static struct interface *netsock_find_interface(struct list_head *interfaces,
 						const char *name)
 {
 	struct interface *interface;
 
-	list_for_each_entry(interface, &globals->interfaces, list) {
+	list_for_each_entry(interface, interfaces, list) {
 		if (strcmp(name, interface->interface) == 0)
 			return interface;
 	}
@@ -115,30 +115,32 @@ static struct interface *netsock_find_interface(struct globals *globals,
 
 int netsock_set_interfaces(struct globals *globals, char *interfaces)
 {
+	struct list_head new_interfaces;
 	struct interface *interface;
+	struct interface *is;
 	char *saveptr;
 	char *input;
 	char *token;
 
-	netsock_close_all(globals);
+	INIT_LIST_HEAD(&new_interfaces);
 
 	/* interface 'none' disables all interface operations */
-	if (is_iface_disabled(interfaces))
+	if (is_iface_disabled(interfaces)) {
+		netsock_close_all(globals);
 		return 0;
+	}
 
 	input = interfaces;
 	while ((token = strtok_r(input, ",", &saveptr))) {
 		input = NULL;
 
-		interface = netsock_find_interface(globals, token);
+		interface = netsock_find_interface(&new_interfaces, token);
 		if (interface)
 			continue;
 
 		interface = malloc(sizeof(*interface));
-		if (!interface) {
-			netsock_close_all(globals);
-			return -ENOMEM;
-		}
+		if (!interface)
+			goto err;
 
 		memset(&interface->hwaddr, 0, sizeof(interface->hwaddr));
 		memset(&interface->address, 0, sizeof(interface->address));
@@ -151,8 +153,7 @@ int netsock_set_interfaces(struct globals *globals, char *interfaces)
 		interface->interface = strdup(token);
 		if (!interface->interface) {
 			free(interface);
-			netsock_close_all(globals);
-			return -ENOMEM;
+			goto err;
 		}
 
 		interface->server_hash = hash_new(64, server_compare,
@@ -160,14 +161,26 @@ int netsock_set_interfaces(struct globals *globals, char *interfaces)
 		if (!interface->server_hash) {
 			free(interface->interface);
 			free(interface);
-			netsock_close_all(globals);
-			return -ENOMEM;
+			goto err;
 		}
 
-		list_add_tail(&interface->list, &globals->interfaces);
+		list_add_tail(&interface->list, &new_interfaces);
 	}
 
+	netsock_close_all(globals);
+	list_splice_tail(&new_interfaces, &globals->interfaces);
+
 	return 0;
+
+err:
+	list_for_each_entry_safe(interface, is, &new_interfaces, list) {
+		list_del(&interface->list);
+		hash_delete(interface->server_hash, free);
+		free(interface->interface);
+		free(interface);
+	}
+
+	return -ENOMEM;
 }
 
 static int enable_raw_bind_capability(int enable)
diff --git a/unix_sock.c b/unix_sock.c
index 417b380..d0e82dc 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -388,11 +388,14 @@ unix_sock_change_iface(struct globals *globals,
 	if (!net_iface)
 		goto err;
 
+	if (netsock_set_interfaces(globals, change_iface->ifaces) < 0) {
+		free(net_iface);
+		goto err;
+	}
+
 	free(globals->net_iface);
 	globals->net_iface = net_iface;
 
-	netsock_set_interfaces(globals, change_iface->ifaces);
-
 	ret = 0;
 err:
 	close(client_sock);

-- 
2.47.3