From: Stefan Reinauer Date: Wed, 27 May 2026 16:06:10 +0000 (-0700) Subject: slirp: harden backend reinitialization X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=400b40c853f0151f87257f98a3f58c57b0bbec86;p=francis%2Fwinuae.git slirp: harden backend reinitialization Ariadne can close and reopen the selected Ethernet backend while guest software probes or retries card configuration. The SLIRP backend destroyed callback state before the receive thread was known to be stopped, and ignored initialization or thread start failures. Join the receive thread before teardown, keep callback state alive until shutdown completes, report SLIRP startup failures, and reset or reuse BOOTP leases across backend restarts. --- diff --git a/ethernet.cpp b/ethernet.cpp index 83ceda33..6231e6a9 100644 --- a/ethernet.cpp +++ b/ethernet.cpp @@ -122,7 +122,12 @@ int ethernet_open (struct netdriverdata *ndd, void *vsd, void *user, ethernet_go slirp_data = ed; uae_sem_init (&slirp_sem1, 0, 1); uae_sem_init (&slirp_sem2, 0, 1); - uae_slirp_init(); + if (uae_slirp_init() < 0) { + slirp_data = NULL; + uae_sem_destroy (&slirp_sem1); + uae_sem_destroy (&slirp_sem2); + return 0; + } for (int i = 0; i < MAX_SLIRP_REDIRS; i++) { struct slirp_redir *sr = &currprefs.slirp_redirs[i]; if (sr->proto) { @@ -156,7 +161,13 @@ int ethernet_open (struct netdriverdata *ndd, void *vsd, void *user, ethernet_go } } netmode = ndd->type; - uae_slirp_start (); + if (!uae_slirp_start ()) { + uae_slirp_cleanup (); + slirp_data = NULL; + uae_sem_destroy (&slirp_sem1); + uae_sem_destroy (&slirp_sem2); + return 0; + } } return 1; #endif @@ -184,9 +195,9 @@ void ethernet_close (struct netdriverdata *ndd, void *vsd) case UAENET_SLIRP: case UAENET_SLIRP_INBOUND: if (slirp_data) { - slirp_data = NULL; uae_slirp_end (); uae_slirp_cleanup (); + slirp_data = NULL; uae_sem_destroy (&slirp_sem1); uae_sem_destroy (&slirp_sem2); } diff --git a/slirp/bootp.cpp b/slirp/bootp.cpp index 0bcd6a7c..31cc48b8 100644 --- a/slirp/bootp.cpp +++ b/slirp/bootp.cpp @@ -40,6 +40,11 @@ BOOTPClient bootp_clients[NB_ADDR]; static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; +void bootp_reset(void) +{ + memset(bootp_clients, 0, sizeof bootp_clients); +} + static BOOTPClient *get_new_addr(struct in_addr *paddr) { BOOTPClient *bc; @@ -144,10 +149,15 @@ static void bootp_reply(struct bootp_t *bp) memset(rbp, 0, sizeof(struct bootp_t)); if (dhcp_msg_type == DHCPDISCOVER) { + bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); + if (bc) + goto have_addr; new_addr: bc = get_new_addr(&daddr.sin_addr); - if (!bc) + if (!bc) { + m_free(m); return; + } memcpy(bc->macaddr, client_ethaddr, 6); } else { bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); @@ -157,6 +167,7 @@ static void bootp_reply(struct bootp_t *bp) goto new_addr; } } +have_addr: saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); saddr.sin_port = htons(BOOTP_SERVER); diff --git a/slirp/bootp.h b/slirp/bootp.h index 86762d0a..c3b4df77 100644 --- a/slirp/bootp.h +++ b/slirp/bootp.h @@ -113,3 +113,4 @@ struct bootp_t { #include "unpacked.h" void bootp_input(struct mbuf *m); +void bootp_reset(void); diff --git a/slirp/slirp.cpp b/slirp/slirp.cpp index 0df263cd..67610b00 100644 --- a/slirp/slirp.cpp +++ b/slirp/slirp.cpp @@ -137,6 +137,7 @@ int slirp_init(void) link_up = 1; + bootp_reset(); if_init(); ip_init(); @@ -159,6 +160,7 @@ void slirp_cleanup(void) { ip_cleanup(); m_cleanup(); + bootp_reset(); link_up = 0; } diff --git a/slirp_uae.cpp b/slirp_uae.cpp index 8758532e..c1c4eab3 100644 --- a/slirp_uae.cpp +++ b/slirp_uae.cpp @@ -61,7 +61,7 @@ int uae_slirp_init(void) #ifdef WITH_QEMU_SLIRP if (impl == QEMU_IMPLEMENTATION) { - return uae_qemu_uae_init() == NULL; + return uae_qemu_uae_init() ? 0 : -1; } #endif #ifdef WITH_BUILTIN_SLIRP @@ -140,7 +140,6 @@ extern uae_sem_t slirp_sem2; static void slirp_receive_func(void *arg) { - slirp_thread_active = 1; while (slirp_thread_active == 1) { fd_set rfds, wfds, xfds; INT_PTR nfds;