]> Git Repo - qemu.git/blobdiff - slirp/slirp.c
slirp: replace compile time DO_KEEPALIVE
[qemu.git] / slirp / slirp.c
index 23864938f7adfe6e0e240a35d03752921226f29e..f11f9e9e51f699d134535acd8fce4bb9f7bfc454 100644 (file)
@@ -26,6 +26,7 @@
 #include "qemu/timer.h"
 #include "qemu/error-report.h"
 #include "chardev/char-fe.h"
+#include "migration/register.h"
 #include "slirp.h"
 #include "hw/hw.h"
 #include "qemu/cutils.h"
@@ -34,6 +35,9 @@
 #include <net/if.h>
 #endif
 
+/* Define to 1 if you want KEEPALIVE timers */
+bool slirp_do_keepalive;
+
 /* host loopback address */
 struct in_addr loopback_addr;
 /* host loopback network mask */
@@ -46,7 +50,7 @@ static const uint8_t special_ethaddr[ETH_ALEN] = {
 
 u_int curtime;
 
-static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
+static QTAILQ_HEAD(, Slirp) slirp_instances =
     QTAILQ_HEAD_INITIALIZER(slirp_instances);
 
 static struct in_addr dns_addr;
@@ -282,15 +286,19 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
                   bool in6_enabled,
                   struct in6_addr vprefix_addr6, uint8_t vprefix_len,
                   struct in6_addr vhost6, const char *vhostname,
+                  const char *tftp_server_name,
                   const char *tftp_path, const char *bootfile,
                   struct in_addr vdhcp_start, struct in_addr vnameserver,
                   struct in6_addr vnameserver6, const char **vdnssearch,
+                  const char *vdomainname,
+                  const SlirpCb *callbacks,
                   void *opaque)
 {
     Slirp *slirp = g_malloc0(sizeof(Slirp));
 
     slirp_init_once();
 
+    slirp->cb = callbacks;
     slirp->grand = g_rand_new();
     slirp->restricted = restricted;
 
@@ -316,9 +324,11 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
     }
     slirp->tftp_prefix = g_strdup(tftp_path);
     slirp->bootp_filename = g_strdup(bootfile);
+    slirp->vdomainname = g_strdup(vdomainname);
     slirp->vdhcp_startaddr = vdhcp_start;
     slirp->vnameserver_addr = vnameserver;
     slirp->vnameserver_addr6 = vnameserver6;
+    slirp->tftp_server_name = g_strdup(tftp_server_name);
 
     if (vdnssearch) {
         translate_dnssearch(slirp, vdnssearch);
@@ -335,6 +345,14 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
 
 void slirp_cleanup(Slirp *slirp)
 {
+    struct ex_list *e, *next;
+
+    for (e = slirp->exec_list; e; e = next) {
+        next = e->ex_next;
+        g_free(e->ex_exec);
+        g_free(e);
+    }
+
     QTAILQ_REMOVE(&slirp_instances, slirp, entry);
 
     unregister_savevm(NULL, "slirp", slirp);
@@ -348,6 +366,7 @@ void slirp_cleanup(Slirp *slirp)
     g_free(slirp->vdnssearch);
     g_free(slirp->tftp_prefix);
     g_free(slirp->bootp_filename);
+    g_free(slirp->vdomainname);
     g_free(slirp);
 }
 
@@ -675,55 +694,14 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
                         /* continue; */
                     } else {
                         ret = sowrite(so);
-                    }
-                    /*
-                     * XXXXX If we wrote something (a lot), there
-                     * could be a need for a window update.
-                     * In the worst case, the remote will send
-                     * a window probe to get things going again
-                     */
-                }
-
-                /*
-                 * Probe a still-connecting, non-blocking socket
-                 * to check if it's still alive
-                 */
-#ifdef PROBE_CONN
-                if (so->so_state & SS_ISFCONNECTING) {
-                    ret = qemu_recv(so->s, &ret, 0, 0);
-
-                    if (ret < 0) {
-                        /* XXX */
-                        if (errno == EAGAIN || errno == EWOULDBLOCK ||
-                            errno == EINPROGRESS || errno == ENOTCONN) {
-                            continue; /* Still connecting, continue */
-                        }
-
-                        /* else failed */
-                        so->so_state &= SS_PERSISTENT_MASK;
-                        so->so_state |= SS_NOFDREF;
-
-                        /* tcp_input will take care of it */
-                    } else {
-                        ret = send(so->s, &ret, 0, 0);
-                        if (ret < 0) {
-                            /* XXX */
-                            if (errno == EAGAIN || errno == EWOULDBLOCK ||
-                                errno == EINPROGRESS || errno == ENOTCONN) {
-                                continue;
-                            }
-                            /* else failed */
-                            so->so_state &= SS_PERSISTENT_MASK;
-                            so->so_state |= SS_NOFDREF;
-                        } else {
-                            so->so_state &= ~SS_ISFCONNECTING;
+                        if (ret > 0) {
+                            /* Call tcp_output in case we need to send a window
+                             * update to the guest, otherwise it will be stuck
+                             * until it sends a window probe. */
+                            tcp_output(sototcpcb(so));
                         }
-
                     }
-                    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
-                              so->so_ffamily);
-                } /* SS_ISFCONNECTING */
-#endif
+                }
             }
 
             /*
@@ -827,7 +805,7 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
             rah->ar_sip = ah->ar_tip;
             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
             rah->ar_tip = ah->ar_sip;
-            slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
+            slirp->cb->output(slirp->opaque, arp_reply, sizeof(arp_reply));
         }
         break;
     case ARPOP_REPLY:
@@ -927,7 +905,7 @@ static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
             /* target IP */
             rah->ar_tip = iph->ip_dst.s_addr;
             slirp->client_ipaddr = iph->ip_dst;
-            slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
+            slirp->cb->output(slirp->opaque, arp_req, sizeof(arp_req));
             ifm->resolution_requested = true;
 
             /* Expire request and drop outgoing packet after 1 second */
@@ -1013,7 +991,7 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
                 eh->h_dest[0], eh->h_dest[1], eh->h_dest[2],
                 eh->h_dest[3], eh->h_dest[4], eh->h_dest[5]));
     memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
-    slirp_output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
+    slirp->cb->output(slirp->opaque, buf, ifm->m_len + ETH_HLEN);
     return 1;
 }
 
@@ -1060,7 +1038,7 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
     return 0;
 }
 
-int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
+int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline,
                    struct in_addr *guest_addr, int guest_port)
 {
     if (!guest_addr->s_addr) {
@@ -1073,19 +1051,31 @@ int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
         guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
         return -1;
     }
-    return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
+
+    return add_exec(&slirp->exec_list, chardev, cmdline, *guest_addr,
                     htons(guest_port));
 }
 
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
 {
-    if (so->s == -1 && so->extra) {
+    if (so->s == -1 && so->chardev) {
         /* XXX this blocks entire thread. Rewrite to use
          * qemu_chr_fe_write and background I/O callbacks */
-        qemu_chr_fe_write_all(so->extra, buf, len);
+        qemu_chr_fe_write_all(so->chardev, buf, len);
         return len;
     }
 
+    if (so->s == -1) {
+        /*
+         * This should in theory not happen but it is hard to be
+         * sure because some code paths will end up with so->s == -1
+         * on a failure but don't dispose of the struct socket.
+         * Check specifically, so we don't pass -1 to send().
+         */
+        errno = EBADF;
+        return -1;
+    }
+
     return send(so->s, buf, len, flags);
 }
 
@@ -1202,11 +1192,13 @@ struct sbuf_tmp {
     uint32_t roff, woff;
 };
 
-static void sbuf_tmp_pre_save(void *opaque)
+static int sbuf_tmp_pre_save(void *opaque)
 {
     struct sbuf_tmp *tmp = opaque;
     tmp->woff = tmp->parent->sb_wptr - tmp->parent->sb_data;
     tmp->roff = tmp->parent->sb_rptr - tmp->parent->sb_data;
+
+    return 0;
 }
 
 static int sbuf_tmp_post_load(void *opaque, int version)
@@ -1302,7 +1294,7 @@ typedef struct SS_FamilyTmpStruct {
 #define SS_FAMILY_MIG_IPV6  10  /* Linux */
 #define SS_FAMILY_MIG_OTHER 0xffff
 
-static void ss_family_pre_save(void *opaque)
+static int ss_family_pre_save(void *opaque)
 {
     SS_FamilyTmpStruct *tss = opaque;
 
@@ -1313,6 +1305,8 @@ static void ss_family_pre_save(void *opaque)
     } else if (tss->parent->ss.ss_family == AF_INET6) {
         tss->portable_family = SS_FAMILY_MIG_IPV6;
     }
+
+    return 0;
 }
 
 static int ss_family_post_load(void *opaque, int version_id)
@@ -1432,7 +1426,7 @@ static void slirp_state_save(QEMUFile *f, void *opaque)
     struct ex_list *ex_ptr;
 
     for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
-        if (ex_ptr->ex_pty == 3) {
+        if (ex_ptr->ex_chardev) {
             struct socket *so;
             so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
                                        ntohs(ex_ptr->ex_fport));
@@ -1457,9 +1451,6 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         int ret;
         struct socket *so = socreate(slirp);
 
-        if (!so)
-            return -ENOMEM;
-
         ret = vmstate_load_state(f, &vmstate_slirp_socket, so, version_id);
 
         if (ret < 0)
@@ -1470,7 +1461,7 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
             return -EINVAL;
         }
         for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
-            if (ex_ptr->ex_pty == 3 &&
+            if (ex_ptr->ex_chardev &&
                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
                 so->so_fport == ex_ptr->ex_fport) {
                 break;
@@ -1478,8 +1469,6 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         }
         if (!ex_ptr)
             return -EINVAL;
-
-        so->extra = (void *)ex_ptr->ex_exec;
     }
 
     return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);
This page took 0.033018 seconds and 4 git commands to generate.