]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
slirp: harden backend reinitialization
authorStefan Reinauer <stefan.reinauer@coreboot.org>
Wed, 27 May 2026 16:06:10 +0000 (09:06 -0700)
committerStefan Reinauer <stefan.reinauer@coreboot.org>
Thu, 4 Jun 2026 04:29:27 +0000 (21:29 -0700)
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.

ethernet.cpp
slirp/bootp.cpp
slirp/bootp.h
slirp/slirp.cpp
slirp_uae.cpp

index 83ceda3300c7817cd9a02a595822d05b22c61ce6..6231e6a95750799327e46a00bf6a4d9d07e3f29e 100644 (file)
@@ -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);
                }
index 0bcd6a7ce44ceef5b5f103f84d11e2232a4d097e..31cc48b8a502a186ae48f7261bcc4f58f8b28920 100644 (file)
@@ -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);
index 86762d0ab094f410c2758484e97c1e503adf7e64..c3b4df77ff2ec622470ee67e3acfeb103e47878e 100644 (file)
@@ -113,3 +113,4 @@ struct bootp_t {
 #include "unpacked.h"
 
 void bootp_input(struct mbuf *m);
+void bootp_reset(void);
index 0df263cd80d33604e63aed7c1dee08abf629737b..67610b00a46707a4b329aaddd67a46e4215cb7c6 100644 (file)
@@ -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;
 }
 
index 8758532e6b8d319ed50295cbce386514e39e8df2..c1c4eab380dee0a42744f3c272e576dda1d7a2e8 100644 (file)
@@ -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;