]> Git Repo - qemu.git/blobdiff - slirp/slirp.c
target-arm: Add arm_boot_info secure_boot control
[qemu.git] / slirp / slirp.c
index 5d14e7f865cf9bb834faca75bc31812b03dd991b..35f819afb7befa900412e0c1134db6440d3dd8a7 100644 (file)
@@ -23,7 +23,7 @@
  */
 #include "qemu-common.h"
 #include "qemu/timer.h"
-#include "char/char.h"
+#include "sysemu/char.h"
 #include "slirp.h"
 #include "hw/hw.h"
 
@@ -37,14 +37,7 @@ static const uint8_t special_ethaddr[ETH_ALEN] = {
     0x52, 0x55, 0x00, 0x00, 0x00, 0x00
 };
 
-static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
-
-/* XXX: suppress those select globals */
-fd_set *global_readfds, *global_writefds, *global_xfds;
-
 u_int curtime;
-static u_int time_fasttimo, last_slowtimo;
-static int do_slowtimo;
 
 static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
     QTAILQ_HEAD_INITIALIZER(slirp_instances);
@@ -52,6 +45,11 @@ static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
 static struct in_addr dns_addr;
 static u_int dns_addr_time;
 
+#define TIMEOUT_FAST 2  /* milliseconds */
+#define TIMEOUT_SLOW 499  /* milliseconds */
+/* for the aging of certain requests like DNS */
+#define TIMEOUT_DEFAULT 1000  /* milliseconds */
+
 #ifdef _WIN32
 
 int get_dns_addr(struct in_addr *pdns_addr)
@@ -62,7 +60,7 @@ int get_dns_addr(struct in_addr *pdns_addr)
     IP_ADDR_STRING *pIPAddr;
     struct in_addr tmp_addr;
 
-    if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < 1000) {
+    if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < TIMEOUT_DEFAULT) {
         *pdns_addr = dns_addr;
         return 0;
     }
@@ -118,7 +116,7 @@ int get_dns_addr(struct in_addr *pdns_addr)
 
     if (dns_addr.s_addr != 0) {
         struct stat old_stat;
-        if ((curtime - dns_addr_time) < 1000) {
+        if ((curtime - dns_addr_time) < TIMEOUT_DEFAULT) {
             *pdns_addr = dns_addr;
             return 0;
         }
@@ -139,7 +137,7 @@ int get_dns_addr(struct in_addr *pdns_addr)
         return -1;
 
 #ifdef DEBUG
-    lprint("IP address of your DNS(s): ");
+    fprintf(stderr, "IP address of your DNS(s): ");
 #endif
     while (fgets(buff, 512, f) != NULL) {
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
@@ -153,17 +151,17 @@ int get_dns_addr(struct in_addr *pdns_addr)
             }
 #ifdef DEBUG
             else
-                lprint(", ");
+                fprintf(stderr, ", ");
 #endif
             if (++found > 3) {
 #ifdef DEBUG
-                lprint("(more)");
+                fprintf(stderr, "(more)");
 #endif
                 break;
             }
 #ifdef DEBUG
             else
-                lprint("%s", inet_ntoa(tmp_addr));
+                fprintf(stderr, "%s", inet_ntoa(tmp_addr));
 #endif
         }
     }
@@ -261,54 +259,68 @@ void slirp_cleanup(Slirp *slirp)
 
 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
-#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
 
-void slirp_update_timeout(uint32_t *timeout)
+static void slirp_update_timeout(uint32_t *timeout)
 {
-    if (!QTAILQ_EMPTY(&slirp_instances)) {
-        *timeout = MIN(1000, *timeout);
+    Slirp *slirp;
+    uint32_t t;
+
+    if (*timeout <= TIMEOUT_FAST) {
+        return;
+    }
+
+    t = MIN(1000, *timeout);
+
+    /* If we have tcp timeout with slirp, then we will fill @timeout with
+     * more precise value.
+     */
+    QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
+        if (slirp->time_fasttimo) {
+            *timeout = TIMEOUT_FAST;
+            return;
+        }
+        if (slirp->do_slowtimo) {
+            t = MIN(TIMEOUT_SLOW, t);
+        }
     }
+    *timeout = t;
 }
 
-void slirp_select_fill(int *pnfds,
-                       fd_set *readfds, fd_set *writefds, fd_set *xfds)
+void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
 {
     Slirp *slirp;
     struct socket *so, *so_next;
-    int nfds;
 
     if (QTAILQ_EMPTY(&slirp_instances)) {
         return;
     }
 
-    /* fail safe */
-    global_readfds = NULL;
-    global_writefds = NULL;
-    global_xfds = NULL;
-
-    nfds = *pnfds;
     /*
      * First, TCP sockets
      */
-    do_slowtimo = 0;
 
     QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
         /*
          * *_slowtimo needs calling if there are IP fragments
          * in the fragment queue, or there are TCP connections active
          */
-        do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
+        slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
                 (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
 
         for (so = slirp->tcb.so_next; so != &slirp->tcb;
                 so = so_next) {
+            int events = 0;
+
             so_next = so->so_next;
 
+            so->pollfds_idx = -1;
+
             /*
              * See if we need a tcp_fasttimo
              */
-            if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) {
-                time_fasttimo = curtime; /* Flag when we want a fasttimo */
+            if (slirp->time_fasttimo == 0 &&
+                so->so_tcpcb->t_flags & TF_DELACK) {
+                slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
             }
 
             /*
@@ -323,8 +335,12 @@ void slirp_select_fill(int *pnfds,
              * Set for reading sockets which are accepting
              */
             if (so->so_state & SS_FACCEPTCONN) {
-                FD_SET(so->s, readfds);
-                UPD_NFDS(so->s);
+                GPollFD pfd = {
+                    .fd = so->s,
+                    .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
+                };
+                so->pollfds_idx = pollfds->len;
+                g_array_append_val(pollfds, pfd);
                 continue;
             }
 
@@ -332,8 +348,12 @@ void slirp_select_fill(int *pnfds,
              * Set for writing sockets which are connecting
              */
             if (so->so_state & SS_ISFCONNECTING) {
-                FD_SET(so->s, writefds);
-                UPD_NFDS(so->s);
+                GPollFD pfd = {
+                    .fd = so->s,
+                    .events = G_IO_OUT | G_IO_ERR,
+                };
+                so->pollfds_idx = pollfds->len;
+                g_array_append_val(pollfds, pfd);
                 continue;
             }
 
@@ -342,8 +362,7 @@ void slirp_select_fill(int *pnfds,
              * we have something to send
              */
             if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
-                FD_SET(so->s, writefds);
-                UPD_NFDS(so->s);
+                events |= G_IO_OUT | G_IO_ERR;
             }
 
             /*
@@ -352,9 +371,16 @@ void slirp_select_fill(int *pnfds,
              */
             if (CONN_CANFRCV(so) &&
                 (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
-                FD_SET(so->s, readfds);
-                FD_SET(so->s, xfds);
-                UPD_NFDS(so->s);
+                events |= G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI;
+            }
+
+            if (events) {
+                GPollFD pfd = {
+                    .fd = so->s,
+                    .events = events,
+                };
+                so->pollfds_idx = pollfds->len;
+                g_array_append_val(pollfds, pfd);
             }
         }
 
@@ -365,6 +391,8 @@ void slirp_select_fill(int *pnfds,
                 so = so_next) {
             so_next = so->so_next;
 
+            so->pollfds_idx = -1;
+
             /*
              * See if it's timed out
              */
@@ -373,7 +401,7 @@ void slirp_select_fill(int *pnfds,
                     udp_detach(so);
                     continue;
                 } else {
-                    do_slowtimo = 1; /* Let socket expire */
+                    slirp->do_slowtimo = true; /* Let socket expire */
                 }
             }
 
@@ -388,8 +416,12 @@ void slirp_select_fill(int *pnfds,
              * (XXX <= 4 ?)
              */
             if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
-                FD_SET(so->s, readfds);
-                UPD_NFDS(so->s);
+                GPollFD pfd = {
+                    .fd = so->s,
+                    .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
+                };
+                so->pollfds_idx = pollfds->len;
+                g_array_append_val(pollfds, pfd);
             }
         }
 
@@ -400,6 +432,8 @@ void slirp_select_fill(int *pnfds,
                 so = so_next) {
             so_next = so->so_next;
 
+            so->pollfds_idx = -1;
+
             /*
              * See if it's timed out
              */
@@ -408,22 +442,24 @@ void slirp_select_fill(int *pnfds,
                     icmp_detach(so);
                     continue;
                 } else {
-                    do_slowtimo = 1; /* Let socket expire */
+                    slirp->do_slowtimo = true; /* Let socket expire */
                 }
             }
 
             if (so->so_state & SS_ISFCONNECTED) {
-                FD_SET(so->s, readfds);
-                UPD_NFDS(so->s);
+                GPollFD pfd = {
+                    .fd = so->s,
+                    .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
+                };
+                so->pollfds_idx = pollfds->len;
+                g_array_append_val(pollfds, pfd);
             }
         }
     }
-
-    *pnfds = nfds;
+    slirp_update_timeout(timeout);
 }
 
-void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
-                       int select_error)
+void slirp_pollfds_poll(GArray *pollfds, int select_error)
 {
     Slirp *slirp;
     struct socket *so, *so_next;
@@ -433,24 +469,22 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
         return;
     }
 
-    global_readfds = readfds;
-    global_writefds = writefds;
-    global_xfds = xfds;
-
-    curtime = qemu_get_clock_ms(rt_clock);
+    curtime = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
 
     QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
         /*
          * See if anything has timed out
          */
-        if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
+        if (slirp->time_fasttimo &&
+            ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) {
             tcp_fasttimo(slirp);
-            time_fasttimo = 0;
+            slirp->time_fasttimo = 0;
         }
-        if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
+        if (slirp->do_slowtimo &&
+            ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) {
             ip_slowtimo(slirp);
             tcp_slowtimo(slirp);
-            last_slowtimo = curtime;
+            slirp->last_slowtimo = curtime;
         }
 
         /*
@@ -462,12 +496,16 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
              */
             for (so = slirp->tcb.so_next; so != &slirp->tcb;
                     so = so_next) {
+                int revents;
+
                 so_next = so->so_next;
 
-                /*
-                 * FD_ISSET is meaningless on these sockets
-                 * (and they can crash the program)
-                 */
+                revents = 0;
+                if (so->pollfds_idx != -1) {
+                    revents = g_array_index(pollfds, GPollFD,
+                                            so->pollfds_idx).revents;
+                }
+
                 if (so->so_state & SS_NOFDREF || so->s == -1) {
                     continue;
                 }
@@ -475,15 +513,15 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                 /*
                  * Check for URG data
                  * This will soread as well, so no need to
-                 * test for readfds below if this succeeds
+                 * test for G_IO_IN below if this succeeds
                  */
-                if (FD_ISSET(so->s, xfds)) {
+                if (revents & G_IO_PRI) {
                     sorecvoob(so);
                 }
                 /*
                  * Check sockets for reading
                  */
-                else if (FD_ISSET(so->s, readfds)) {
+                else if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) {
                     /*
                      * Check for incoming connections
                      */
@@ -502,7 +540,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                 /*
                  * Check sockets for writing
                  */
-                if (FD_ISSET(so->s, writefds)) {
+                if (!(so->so_state & SS_NOFDREF) &&
+                        (revents & (G_IO_OUT | G_IO_ERR))) {
                     /*
                      * Check for non-blocking, still-connecting sockets
                      */
@@ -588,9 +627,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
              */
             for (so = slirp->udb.so_next; so != &slirp->udb;
                     so = so_next) {
+                int revents;
+
                 so_next = so->so_next;
 
-                if (so->s != -1 && FD_ISSET(so->s, readfds)) {
+                revents = 0;
+                if (so->pollfds_idx != -1) {
+                    revents = g_array_index(pollfds, GPollFD,
+                            so->pollfds_idx).revents;
+                }
+
+                if (so->s != -1 &&
+                    (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
                     sorecvfrom(so);
                 }
             }
@@ -600,9 +648,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
              */
             for (so = slirp->icmp.so_next; so != &slirp->icmp;
                     so = so_next) {
-                so_next = so->so_next;
+                    int revents;
+
+                    so_next = so->so_next;
+
+                    revents = 0;
+                    if (so->pollfds_idx != -1) {
+                        revents = g_array_index(pollfds, GPollFD,
+                                                so->pollfds_idx).revents;
+                    }
 
-                if (so->s != -1 && FD_ISSET(so->s, readfds)) {
+                    if (so->s != -1 &&
+                        (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) {
                     icmp_receive(so);
                 }
             }
@@ -610,15 +667,6 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 
         if_start(slirp);
     }
-
-    /* clear global file descriptor sets.
-     * these reside on the stack in vl.c
-     * so they're unusable if we're not in
-     * slirp_select_fill or slirp_select_poll.
-     */
-    global_readfds = NULL;
-    global_writefds = NULL;
-    global_xfds = NULL;
 }
 
 static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
@@ -728,6 +776,11 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
         return 1;
     }
 
+    if (iph->ip_dst.s_addr == 0) {
+        /* 0.0.0.0 can not be a destination address, something went wrong,
+         * avoid making it worse */
+        return 1;
+    }
     if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
         uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
         struct ethhdr *reh = (struct ethhdr *)arp_req;
@@ -762,7 +815,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
             ifm->arp_requested = true;
 
             /* Expire request and drop outgoing packet after 1 second */
-            ifm->expiration_date = qemu_get_clock_ns(rt_clock) + 1000000000ULL;
+            ifm->expiration_date = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 1000000000ULL;
         }
         return 0;
     } else {
This page took 0.040814 seconds and 4 git commands to generate.