[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