qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded
@ 2009-06-24 12:42 Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 01/41] slirp: Drop redundant lines from udp_input Jan Kiszka
                   ` (41 more replies)
  0 siblings, 42 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

The foundation of this series are the patches from my previous posting
that didn't make it into upstream. But while reworking them, the series
grow far beyond the previous approach, adding lots of fixes and cleanups
to the slirp stack and its interfaces.

One major contribution is that the virtual IP addresses used inside
slirp VLANs are now (almost) freely configurable. This enables
sophisticated virtual network setups, specifically with guests that
depends on specific addresses.

In this second step, the series also comes with support for multiple
slirp instances per VM. Further contributions are
 - proper dynamic slirp cleanup during runtime
 - 'info usernet' command to dump slirp connection states
 - reworked monitor commands hostfwd_add/remove (formerly known as
   host_net_redir)
 - save/restore fixes for slirp
 - first larger code cleanup (more work required...)
 - various small fixes

The patches have been successfully tested against basic use cases:
connections to/from the guests, redirections, tftp, multi-instance,
save/restore. Moreover, they also passed successfull build tests
against mingw32.

Regarding the preferred flow: Mark, will you let this go through your
network tree first? Currently the series is based on upstream/master,
but I can rebase if required.

Find this series also at git://git.kiszka.org/qemu.git queues/net

Jan Kiszka (41):
      slirp: Drop redundant lines from udp_input
      slirp: Refactor tcp_ctl
      Revert "User networking: Show active connections"
      Introduce get_next_param_value
      slirp: Move smb, redir, tftp and bootp parameters and -net channel
      slirp: Rework internal configuration
      slirp: Rework external configuration interface
      slirp: Fix port comparision in slirp_remove_hostfwd
      slirp: Rework monitor commands for host forwarding
      slirp: Bind support for host forwarding rules
      slirp: Prepare for persistent socket state flags
      slirp: Explicitely mark host-forwarding sockets
      slirp: Do not allow to remove non-hostfwd sockets
      slirp: Mark sockets of incoming TCP connections
      slirp: Add info usernet for dumping connection states
      slirp: Drop dead code
      slirp: Drop statistic code
      slirp: Cleanup and basic reanimation of debug code
      slirp: Drop unused icmp_var.h
      slirp: tftp: Cleanup tftp_prefix check
      slirp: tftp: Clean up tftp_send_error
      slirp: tftp: Refactor tftp_handle_rrq
      slirp: tftp: Rework filename handling
      slirp: Factor out one-time initialization
      slirp: Make IP packet ID consistent
      slirp: Clean up updtime
      slirp: Kill slirp_is_inited
      slirp: Drop redundant checks from slirp_output
      slirp: Clean up timeout handling around slirp_select_fill/poll
      slirp: Drop link_up checks from if_output and slirp_socket_can_recv
      slirp: Factor out internal state structure
      slirp: Use internal state in interface
      slirp: Allocate/free stack instance dynamically
      slirp: Enable multiple instances
      slirp: Save/restore bootp client states
      slirp: Use shell to erase smb directory
      slirp: Improve error handling in slirp_smb
      slirp: Enable multi-instance support for the smb service
      net: Provide VLAN client lookup helper
      slirp: Make hostfwd_add/remove multi-instance-aware
      slirp: Basic VLAN client info_str

 Makefile           |    2 +-
 hw/xen_nic.c       |    2 +-
 monitor.c          |    4 +-
 net.c              |  745 ++++++++++++++++++++++++++++++++++++----------------
 net.h              |   14 +-
 qemu-monitor.hx    |   14 +-
 qemu-options.hx    |  226 +++++++++-------
 slirp/bootp.c      |   92 +++----
 slirp/bootp.h      |    7 +
 slirp/ctl.h        |    7 -
 slirp/debug.c      |  393 ---------------------------
 slirp/debug.h      |   17 +-
 slirp/icmp_var.h   |   67 -----
 slirp/if.c         |  135 ++--------
 slirp/if.h         |   40 +---
 slirp/ip.h         |   40 ---
 slirp/ip_icmp.c    |   42 +--
 slirp/ip_input.c   |  120 +++------
 slirp/ip_output.c  |   37 +---
 slirp/libslirp.h   |   72 +++---
 slirp/main.h       |   10 +-
 slirp/mbuf.c       |   39 +--
 slirp/mbuf.h       |   23 +--
 slirp/misc.c       |  625 ++++++-------------------------------------
 slirp/misc.h       |   16 +-
 slirp/sbuf.c       |    8 -
 slirp/slirp.c      |  500 +++++++++++++++++++----------------
 slirp/slirp.h      |   89 +++++--
 slirp/socket.c     |  128 +++------
 slirp/socket.h     |   15 +-
 slirp/tcp.h        |    7 -
 slirp/tcp_input.c  |  303 +++-------------------
 slirp/tcp_output.c |  115 +--------
 slirp/tcp_subr.c   |  559 ++++++---------------------------------
 slirp/tcp_timer.c  |   46 +---
 slirp/tcp_timer.h  |   10 +-
 slirp/tcp_var.h    |   71 +-----
 slirp/tftp.c       |  168 +++++-------
 slirp/tftp.h       |   10 +
 slirp/udp.c        |  114 ++++-----
 slirp/udp.h        |   28 +--
 sysemu.h           |    2 +
 vl.c               |   48 ++--
 43 files changed, 1624 insertions(+), 3386 deletions(-)
 delete mode 100644 slirp/ctl.h
 delete mode 100644 slirp/debug.c
 delete mode 100644 slirp/icmp_var.h

--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 01/41] slirp: Drop redundant lines from udp_input
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 08/41] slirp: Fix port comparision in slirp_remove_hostfwd Jan Kiszka
                   ` (40 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

The socket faddr/fport is already updated a few lines below, so these
are completely redundant.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/udp.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/slirp/udp.c b/slirp/udp.c
index 11e78cd..ba9d5c9 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -173,8 +173,6 @@ udp_input(register struct mbuf *m, int iphlen)
 		for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
 			if (tmp->so_lport == uh->uh_sport &&
 			    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
-				tmp->so_faddr.s_addr = ip->ip_dst.s_addr;
-				tmp->so_fport = uh->uh_dport;
 				so = tmp;
 				break;
 			}

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 02/41] slirp: Refactor tcp_ctl
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 01/41] slirp: Drop redundant lines from udp_input Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 08/41] slirp: Fix port comparision in slirp_remove_hostfwd Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 04/41] Introduce get_next_param_value Jan Kiszka
                   ` (38 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/tcp_subr.c |  109 +++++++++++++++---------------------------------------
 1 files changed, 30 insertions(+), 79 deletions(-)

diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 9d020a6..447a27c 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -1228,84 +1228,35 @@ do_prompt:
  * Return 0 if this connections is to be closed, 1 otherwise,
  * return 2 if this is a command-line connection
  */
-int
-tcp_ctl(struct socket *so)
+int tcp_ctl(struct socket *so)
 {
-	struct sbuf *sb = &so->so_snd;
-	int command;
- 	struct ex_list *ex_ptr;
-	int do_pty;
-        //	struct socket *tmpso;
-
-	DEBUG_CALL("tcp_ctl");
-	DEBUG_ARG("so = %lx", (long )so);
-
-#if 0
-	/*
-	 * Check if they're authorised
-	 */
-	if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) {
-		sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n");
-		sb->sb_wptr += sb->sb_cc;
-		return 0;
-	}
-#endif
-	command = (ntohl(so->so_faddr.s_addr) & 0xff);
-
-	switch(command) {
-	default: /* Check for exec's */
-
-		/*
-		 * Check if it's pty_exec
-		 */
-		for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
-			if (ex_ptr->ex_fport == so->so_fport &&
-			    command == ex_ptr->ex_addr) {
-				if (ex_ptr->ex_pty == 3) {
-					so->s = -1;
-					so->extra = (void *)ex_ptr->ex_exec;
-					return 1;
-				}
-				do_pty = ex_ptr->ex_pty;
-				goto do_exec;
-			}
-		}
-
-		/*
-		 * Nothing bound..
-		 */
-		/* tcp_fconnect(so); */
-
-		/* FALLTHROUGH */
-	case CTL_ALIAS:
-          sb->sb_cc = snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
-                               "Error: No application configured.\r\n");
-	  sb->sb_wptr += sb->sb_cc;
-	  return(0);
-
-	do_exec:
-		DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
-		return(fork_exec(so, ex_ptr->ex_exec, do_pty));
-
-#if 0
-	case CTL_CMD:
-	   for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
-	     if (tmpso->so_emu == EMU_CTL &&
-		 !(tmpso->so_tcpcb?
-		   (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK))
-		   :0)) {
-	       /* Ooops, control connection already active */
-	       sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n");
-	       sb->sb_wptr += sb->sb_cc;
-	       return 0;
-	     }
-	   }
-	   so->so_emu = EMU_CTL;
-	   ctl_password_ok = 0;
-	   sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> ");
-	   sb->sb_wptr += sb->sb_cc;
-	   do_echo=-1;
-	   return(2);
-#endif
-	}
+    int command = (ntohl(so->so_faddr.s_addr) & 0xff);
+    struct sbuf *sb = &so->so_snd;
+    struct ex_list *ex_ptr;
+    int do_pty;
+
+    DEBUG_CALL("tcp_ctl");
+    DEBUG_ARG("so = %lx", (long )so);
+
+    if (command != CTL_ALIAS) {
+        /* Check if it's pty_exec */
+        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+            if (ex_ptr->ex_fport == so->so_fport &&
+                command == ex_ptr->ex_addr) {
+                if (ex_ptr->ex_pty == 3) {
+                    so->s = -1;
+                    so->extra = (void *)ex_ptr->ex_exec;
+                    return 1;
+                }
+                do_pty = ex_ptr->ex_pty;
+                DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
+                return fork_exec(so, ex_ptr->ex_exec, do_pty);
+            }
+        }
+    }
+    sb->sb_cc =
+        snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
+                 "Error: No application configured.\r\n");
+    sb->sb_wptr += sb->sb_cc;
+    return 0;
 }

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 03/41] Revert "User networking: Show active connections"
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (3 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 04/41] Introduce get_next_param_value Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 10/41] slirp: Bind support for host forwarding rules Jan Kiszka
                   ` (36 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

This reverts commit 1c6ed9f3379faac83da0ed3e95cbd49003ac0dd1.

It's redundant to slirp statistics, which are going to be split up /
reworked later on.

Conflicts:

	monitor.c
	net.c

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |   44 --------------------------------------------
 qemu-monitor.hx  |    3 +--
 slirp/libslirp.h |    4 ----
 slirp/slirp.c    |   24 ------------------------
 4 files changed, 1 insertions(+), 74 deletions(-)

diff --git a/net.c b/net.c
index 55f70f2..87a6e76 100644
--- a/net.c
+++ b/net.c
@@ -756,45 +756,6 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name,
     return 0;
 }
 
-static void net_slirp_redir_print(void *opaque, int is_udp,
-                                  struct in_addr *laddr, u_int lport,
-                                  struct in_addr *faddr, u_int fport)
-{
-    Monitor *mon = (Monitor *)opaque;
-    uint32_t h_addr;
-    uint32_t g_addr;
-    char buf[16];
-
-    h_addr = ntohl(faddr->s_addr);
-    g_addr = ntohl(laddr->s_addr);
-
-    monitor_printf(mon, "  %s |", is_udp ? "udp" : "tcp" );
-    snprintf(buf, 15, "%d.%d.%d.%d", (h_addr >> 24) & 0xff,
-                                     (h_addr >> 16) & 0xff,
-                                     (h_addr >> 8) & 0xff,
-                                     (h_addr) & 0xff);
-    monitor_printf(mon, " %15s |", buf);
-    monitor_printf(mon, " %5d |", fport);
-
-    snprintf(buf, 15, "%d.%d.%d.%d", (g_addr >> 24) & 0xff,
-                                     (g_addr >> 16) & 0xff,
-                                     (g_addr >> 8) & 0xff,
-                                     (g_addr) & 0xff);
-    monitor_printf(mon, " %15s |", buf);
-    monitor_printf(mon, " %5d\n", lport);
-
-}
-
-static void net_slirp_redir_list(Monitor *mon)
-{
-    if (!mon)
-        return;
-
-    monitor_printf(mon, " Prot |    Host Addr    | HPort |    Guest Addr   | GPort\n");
-    monitor_printf(mon, "      |                 |       |                 |      \n");
-    slirp_redir_loop(net_slirp_redir_print, mon);
-}
-
 static void net_slirp_redir_rm(Monitor *mon, const char *port_str)
 {
     int host_port;
@@ -904,11 +865,6 @@ void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2
         return;
     }
 
-    if (!strcmp(redir_str, "list")) {
-        net_slirp_redir_list(mon);
-        return;
-    }
-
     slirp_redirection(mon, redir_str);
 }
 
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index fa48527..090255b 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -538,8 +538,7 @@ ETEXI
 #ifdef CONFIG_SLIRP
     { "host_net_redir", "ss?", net_slirp_redir,
       "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)\n"
-      "host_net_redir remove [tcp:|udp:]host-port -- remove redirection\n"
-      "host_net_redir list -- show all redirections" },
+      "host_net_redir remove [tcp:|udp:]host-port -- remove redirection" },
 #endif
 STEXI
 @item host_net_redir
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index d0df24b..c04f3a2 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -18,10 +18,6 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
 int slirp_can_output(void);
 void slirp_output(const uint8_t *pkt, int pkt_len);
 
-void slirp_redir_loop(void (*func)(void *opaque, int is_udp,
-                                  struct in_addr *laddr, u_int lport,              
-                                  struct in_addr *faddr, u_int fport),
-                     void *opaque);
 int slirp_redir_rm(int is_udp, int host_port);
 int slirp_redir(int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 30d4ee2..b3db742 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -734,30 +734,6 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
     }
 }
 
-static void _slirp_redir_loop(void (*func)(void *opaque, int is_udp,
-                                           struct in_addr *laddr, u_int lport,
-                                           struct in_addr *faddr, u_int fport),
-                              void *opaque, int is_udp)
-{
-    struct socket *head = (is_udp ? &udb : &tcb);
-    struct socket *so;
-
-    for (so = head->so_next; so != head; so = so->so_next) {
-        func(opaque, is_udp,
-             &so->so_laddr, ntohs(so->so_lport),
-             &so->so_faddr, ntohs(so->so_fport));
-    }
-}
-
-void slirp_redir_loop(void (*func)(void *opaque, int is_udp,
-                                  struct in_addr *laddr, u_int lport,
-                                  struct in_addr *faddr, u_int fport),
-                     void *opaque)
-{
-    _slirp_redir_loop(func, opaque, 0);
-    _slirp_redir_loop(func, opaque, 1);
-}
-
 /* Unlistens a redirection
  *
  * Return value: number of redirs removed */

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 08/41] slirp: Fix port comparision in slirp_remove_hostfwd
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 01/41] slirp: Drop redundant lines from udp_input Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 02/41] slirp: Refactor tcp_ctl Jan Kiszka
                   ` (39 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

For UDP host forwardings, fport is not stable, every outgoing packet of
the redirection can modify it. Use getsockname instead to look up the
port that is actually used on the host side.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/slirp.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/slirp/slirp.c b/slirp/slirp.c
index a918232..ad88121 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -761,12 +761,16 @@ int slirp_remove_hostfwd(int is_udp, int host_port)
 {
     struct socket *so;
     struct socket *head = (is_udp ? &udb : &tcb);
-    int fport = htons(host_port);
+    struct sockaddr_in addr;
+    int port = htons(host_port);
+    socklen_t addr_len;
     int n = 0;
 
  loop_again:
     for (so = head->so_next; so != head; so = so->so_next) {
-        if (so->so_fport == fport) {
+        addr_len = sizeof(addr);
+        if (getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
+            addr.sin_port == port) {
             close(so->s);
             sofree(so);
             n++;

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 09/41] slirp: Rework monitor commands for host forwarding
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (5 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 10/41] slirp: Bind support for host forwarding rules Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 05/41] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
                   ` (34 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Improve the monitor interface for adding and removing host forwarding
rules by splitting it up in two commands and rename them to hostfwd_add
and hostfwd_remove. Also split up the paths taken for legacy -redir
support and the monitor add command as the latter will be extended later
on.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c           |   37 ++++++++++++++++++++-----------------
 net.h           |    4 +++-
 qemu-monitor.hx |    8 +++++---
 vl.c            |    2 +-
 4 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/net.c b/net.c
index a12177d..75a7408 100644
--- a/net.c
+++ b/net.c
@@ -871,7 +871,7 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
     return 0;
 }
 
-static void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
+void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
 {
     int host_port;
     char buf[256] = "";
@@ -879,8 +879,10 @@ static void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
     int is_udp = 0;
     int n;
 
-    if (!mon)
+    if (!slirp_inited) {
+        monitor_printf(mon, "user mode network stack not in use\n");
         return;
+    }
 
     if (!port_str || !port_str[0])
         goto fail_syntax;
@@ -958,29 +960,30 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str)
     config_error(mon, "invalid host forwarding rule '%s'\n", redir_str);
 }
 
-void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2)
+void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str)
 {
-    struct slirp_config_str *config;
-
     if (!slirp_inited) {
-        if (mon) {
-            monitor_printf(mon, "user mode network stack not in use\n");
-        } else {
-            config = qemu_malloc(sizeof(*config));
-            pstrcpy(config->str, sizeof(config->str), redir_str);
-            config->flags = SLIRP_CFG_HOSTFWD;
-            config->next = slirp_configs;
-            slirp_configs = config;
-        }
+        monitor_printf(mon, "user mode network stack not in use\n");
         return;
     }
 
-    if (!strcmp(redir_str, "remove")) {
-        net_slirp_hostfwd_remove(mon, redir_opt2);
+    slirp_hostfwd(mon, redir_str);
+}
+
+void net_slirp_redir(const char *redir_str)
+{
+    struct slirp_config_str *config;
+
+    if (!slirp_inited) {
+        config = qemu_malloc(sizeof(*config));
+        pstrcpy(config->str, sizeof(config->str), redir_str);
+        config->flags = SLIRP_CFG_HOSTFWD;
+        config->next = slirp_configs;
+        slirp_configs = config;
         return;
     }
 
-    slirp_hostfwd(mon, redir_str);
+    slirp_hostfwd(NULL, redir_str);
 }
 
 #ifndef _WIN32
diff --git a/net.h b/net.h
index e705c87..884c354 100644
--- a/net.h
+++ b/net.h
@@ -128,7 +128,9 @@ int net_client_init(Monitor *mon, const char *device, const char *p);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
 void net_slirp_smb(const char *exported_dir);
-void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2);
+void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str);
+void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str);
+void net_slirp_redir(const char *redir_str);
 void net_cleanup(void);
 int slirp_is_inited(void);
 void net_client_check(void);
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 090255b..13c98bc 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -536,9 +536,11 @@ Remove host VLAN client.
 ETEXI
 
 #ifdef CONFIG_SLIRP
-    { "host_net_redir", "ss?", net_slirp_redir,
-      "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)\n"
-      "host_net_redir remove [tcp:|udp:]host-port -- remove redirection" },
+    { "hostfwd_add", "s", net_slirp_hostfwd_add,
+      "[tcp|udp]:hostport:[guestaddr]:guestport",
+      "redirect TCP or UDP connections from host to guest (requires -net user)" },
+    { "hostfwd_remove", "s", net_slirp_hostfwd_remove,
+      "[tcp|udp]:hostport", "remove host-to-guest TCP or UDP redirection" },
 #endif
 STEXI
 @item host_net_redir
diff --git a/vl.c b/vl.c
index ae260b1..c24655e 100644
--- a/vl.c
+++ b/vl.c
@@ -5319,7 +5319,7 @@ int main(int argc, char **argv, char **envp)
                 break;
 #endif
             case QEMU_OPTION_redir:
-                net_slirp_redir(NULL, optarg, NULL);
+                net_slirp_redir(optarg);
                 break;
 #endif
             case QEMU_OPTION_bt:

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 07/41] slirp: Rework external configuration interface
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (7 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 05/41] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 06/41] slirp: Rework internal configuration Jan Kiszka
                   ` (32 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

With the internal IP configuration made more flexible, we can now
enhance the user interface. This patch adds a number of new options to
"-net user": net (address and mask), host, dhcpstart, dns and smbserver.
It also renames "redir" to "hostfwd" and "channel" to "guestfwd" in
order to (hopefully) clarify their meanings. The format of guestfwd is
extended so that the user can define not only the port but also the
virtual server's IP address the forwarding starts from.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  316 +++++++++++++++++++++++++++++++++++++++++-------------
 qemu-options.hx  |   52 ++++++---
 slirp/libslirp.h |   24 ++--
 slirp/main.h     |    1 
 slirp/slirp.c    |   52 ++++-----
 5 files changed, 311 insertions(+), 134 deletions(-)

diff --git a/net.c b/net.c
index f7596d2..a12177d 100644
--- a/net.c
+++ b/net.c
@@ -669,12 +669,14 @@ static void config_error(Monitor *mon, const char *fmt, ...)
 
 /* slirp network adapter */
 
-#define SLIRP_CFG_REDIR 1
+#define SLIRP_CFG_HOSTFWD 1
+#define SLIRP_CFG_LEGACY  2
 
 struct slirp_config_str {
     struct slirp_config_str *next;
     int flags;
     char str[1024];
+    int legacy_format;
 };
 
 static int slirp_inited;
@@ -683,13 +685,14 @@ const char *legacy_tftp_prefix;
 const char *legacy_bootp_filename;
 static VLANClientState *slirp_vc;
 
-static void slirp_redirection(Monitor *mon, const char *redir_str);
-static void vmchannel_init(Monitor *mon, const char *config_str);
+static void slirp_hostfwd(Monitor *mon, const char *redir_str);
+static void slirp_guestfwd(Monitor *mon, const char *config_str,
+                           int legacy_format);
 
 #ifndef _WIN32
 static const char *legacy_smb_export;
 
-static void slirp_smb(const char *exported_dir);
+static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr);
 #endif
 
 int slirp_can_output(void)
@@ -731,31 +734,122 @@ static void net_slirp_cleanup(VLANClientState *vc)
 }
 
 static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
-                          const char *name, int restricted, const char *ip,
-                          const char *tftp_export, const char *bootfile,
-                          const char *smb_export)
+                          const char *name, int restricted,
+                          const char *vnetwork, const char *vhost,
+                          const char *vhostname, const char *tftp_export,
+                          const char *bootfile, const char *vdhcp_start,
+                          const char *vnameserver, const char *smb_export,
+                          const char *vsmbserver)
 {
     if (slirp_in_use) {
         /* slirp only supports a single instance so far */
         return -1;
     }
     if (!slirp_inited) {
+        /* default settings according to historic slirp */
+        struct in_addr net  = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
+        struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
+        struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
+        struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
+        struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
+#ifndef _WIN32
+        struct in_addr smbsrv = { .s_addr = 0 };
+#endif
+        char buf[20];
+        uint32_t addr;
+        int shift;
+        char *end;
+
         if (!tftp_export) {
             tftp_export = legacy_tftp_prefix;
         }
         if (!bootfile) {
             bootfile = legacy_bootp_filename;
         }
+
+        if (vnetwork) {
+            if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
+                if (!inet_aton(vnetwork, &net)) {
+                    return -1;
+                }
+                addr = ntohl(net.s_addr);
+                if (!(addr & 0x80000000)) {
+                    mask.s_addr = htonl(0xff000000); /* class A */
+                } else if ((addr & 0xfff00000) == 0xac100000) {
+                    mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
+                } else if ((addr & 0xc0000000) == 0x80000000) {
+                    mask.s_addr = htonl(0xffff0000); /* class B */
+                } else if ((addr & 0xffff0000) == 0xc0a80000) {
+                    mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
+                } else if ((addr & 0xffff0000) == 0xc6120000) {
+                    mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
+                } else if ((addr & 0xe0000000) == 0xe0000000) {
+                    mask.s_addr = htonl(0xffffff00); /* class C */
+                } else {
+                    mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
+                }
+            } else {
+                if (!inet_aton(buf, &net)) {
+                    return -1;
+                }
+                shift = strtol(vnetwork, &end, 10);
+                if (*end != '\0') {
+                    if (!inet_aton(vnetwork, &mask)) {
+                        return -1;
+                    }
+                } else if (shift < 4 || shift > 32) {
+                    return -1;
+                } else {
+                    mask.s_addr = htonl(0xffffffff << (32 - shift));
+                }
+            }
+            net.s_addr &= mask.s_addr;
+            host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
+            dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
+            dns.s_addr  = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
+        }
+
+        if (vhost && !inet_aton(vhost, &host)) {
+            return -1;
+        }
+        if ((host.s_addr & mask.s_addr) != net.s_addr) {
+            return -1;
+        }
+
+        if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
+            return -1;
+        }
+        if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
+            dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
+            return -1;
+        }
+
+        if (vnameserver && !inet_aton(vnameserver, &dns)) {
+            return -1;
+        }
+        if ((dns.s_addr & mask.s_addr) != net.s_addr ||
+            dns.s_addr == host.s_addr) {
+            return -1;
+        }
+
+#ifndef _WIN32
+        if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
+            return -1;
+        }
+#endif
+
+        slirp_init(restricted, net, mask, host, vhostname, tftp_export,
+                   bootfile, dhcp, dns);
         slirp_inited = 1;
-        slirp_init(restricted, ip, tftp_export, bootfile);
 
         while (slirp_configs) {
             struct slirp_config_str *config = slirp_configs;
 
-            if (config->flags & SLIRP_CFG_REDIR) {
-                slirp_redirection(mon, config->str);
+            if (config->flags & SLIRP_CFG_HOSTFWD) {
+                slirp_hostfwd(mon, config->str);
             } else {
-                vmchannel_init(mon, config->str);
+                slirp_guestfwd(mon, config->str,
+                               config->flags & SLIRP_CFG_LEGACY);
             }
             slirp_configs = config->next;
             qemu_free(config);
@@ -765,7 +859,7 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
             smb_export = legacy_smb_export;
         }
         if (smb_export) {
-            slirp_smb(smb_export);
+            slirp_smb(smb_export, smbsrv);
         }
 #endif
     }
@@ -777,7 +871,7 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
     return 0;
 }
 
-static void net_slirp_redir_rm(Monitor *mon, const char *port_str)
+static void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
 {
     int host_port;
     char buf[256] = "";
@@ -803,23 +897,24 @@ static void net_slirp_redir_rm(Monitor *mon, const char *port_str)
 
     host_port = atoi(p);
 
-    n = slirp_redir_rm(is_udp, host_port);
+    n = slirp_remove_hostfwd(is_udp, host_port);
 
-    monitor_printf(mon, "removed %d redirections to %s port %d\n", n,
-                        is_udp ? "udp" : "tcp", host_port);
+    monitor_printf(mon, "removed %d host forwarding rules for %s port %d\n",
+                   n, is_udp ? "udp" : "tcp", host_port);
     return;
 
  fail_syntax:
     monitor_printf(mon, "invalid format\n");
 }
 
-static void slirp_redirection(Monitor *mon, const char *redir_str)
+static void slirp_hostfwd(Monitor *mon, const char *redir_str)
 {
-    struct in_addr guest_addr;
+    struct in_addr guest_addr = { .s_addr = 0 };
     int host_port, guest_port;
     const char *p;
-    char buf[256], *r;
+    char buf[256];
     int is_udp;
+    char *end;
 
     p = redir_str;
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
@@ -836,33 +931,31 @@ static void slirp_redirection(Monitor *mon, const char *redir_str)
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
     }
-    host_port = strtol(buf, &r, 0);
-    if (r == buf) {
+    host_port = strtol(buf, &end, 0);
+    if (*end != '\0' || host_port < 1 || host_port > 65535) {
         goto fail_syntax;
     }
 
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
     }
-    if (buf[0] == '\0') {
-        pstrcpy(buf, sizeof(buf), "10.0.2.15");
-    }
-    if (!inet_aton(buf, &guest_addr)) {
+    if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
         goto fail_syntax;
     }
 
-    guest_port = strtol(p, &r, 0);
-    if (r == p) {
+    guest_port = strtol(p, &end, 0);
+    if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
         goto fail_syntax;
     }
 
-    if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
-        config_error(mon, "could not set up redirection '%s'\n", redir_str);
+    if (slirp_add_hostfwd(is_udp, host_port, guest_addr, guest_port) < 0) {
+        config_error(mon, "could not set up host forwarding rule '%s'\n",
+                     redir_str);
     }
     return;
 
  fail_syntax:
-    config_error(mon, "invalid redirection format '%s'\n", redir_str);
+    config_error(mon, "invalid host forwarding rule '%s'\n", redir_str);
 }
 
 void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2)
@@ -875,7 +968,7 @@ void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2
         } else {
             config = qemu_malloc(sizeof(*config));
             pstrcpy(config->str, sizeof(config->str), redir_str);
-            config->flags = SLIRP_CFG_REDIR;
+            config->flags = SLIRP_CFG_HOSTFWD;
             config->next = slirp_configs;
             slirp_configs = config;
         }
@@ -883,11 +976,11 @@ void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2
     }
 
     if (!strcmp(redir_str, "remove")) {
-        net_slirp_redir_rm(mon, redir_opt2);
+        net_slirp_hostfwd_remove(mon, redir_opt2);
         return;
     }
 
-    slirp_redirection(mon, redir_str);
+    slirp_hostfwd(mon, redir_str);
 }
 
 #ifndef _WIN32
@@ -925,7 +1018,7 @@ static void smb_exit(void)
     erase_dir(smb_dir);
 }
 
-static void slirp_smb(const char *exported_dir)
+static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr)
 {
     char smb_conf[1024];
     char smb_cmdline[1024];
@@ -971,19 +1064,24 @@ static void slirp_smb(const char *exported_dir)
     snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
              SMBD_COMMAND, smb_conf);
 
-    slirp_add_exec(0, smb_cmdline, 4, 139);
+    if (slirp_add_exec(0, smb_cmdline, vserver_addr, 139) < 0) {
+        fprintf(stderr, "conflicting/invalid smbserver address\n");
+        exit(1);
+    }
 }
 
 /* automatic user mode samba server configuration (legacy interface) */
 void net_slirp_smb(const char *exported_dir)
 {
+    struct in_addr vserver_addr = { .s_addr = 0 };
+
     if (legacy_smb_export) {
         fprintf(stderr, "-smb given twice\n");
         exit(1);
     }
     legacy_smb_export = exported_dir;
     if (slirp_inited) {
-        slirp_smb(exported_dir);
+        slirp_smb(exported_dir, vserver_addr);
     }
 }
 
@@ -994,51 +1092,85 @@ void do_info_slirp(Monitor *mon)
     slirp_stats();
 }
 
-struct VMChannel {
+struct GuestFwd {
     CharDriverState *hd;
+    struct in_addr server;
     int port;
 };
 
-static int vmchannel_can_read(void *opaque)
+static int guestfwd_can_read(void *opaque)
 {
-    struct VMChannel *vmc = (struct VMChannel*)opaque;
-    return slirp_socket_can_recv(4, vmc->port);
+    struct GuestFwd *fwd = opaque;
+    return slirp_socket_can_recv(fwd->server, fwd->port);
 }
 
-static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
+static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
 {
-    struct VMChannel *vmc = (struct VMChannel*)opaque;
-    slirp_socket_recv(4, vmc->port, buf, size);
+    struct GuestFwd *fwd = opaque;
+    slirp_socket_recv(fwd->server, fwd->port, buf, size);
 }
 
-static void vmchannel_init(Monitor *mon, const char *config_str)
+static void slirp_guestfwd(Monitor *mon, const char *config_str,
+                           int legacy_format)
 {
-    struct VMChannel *vmc;
-    char *devname;
-    char name[20];
+    struct in_addr server = { .s_addr = 0 };
+    struct GuestFwd *fwd;
+    const char *p;
+    char buf[128];
+    char *end;
     int port;
 
-    port = strtol(config_str, &devname, 10);
-    if (port < 1 || port > 65535 || *devname != ':') {
-        config_error(mon, "invalid vmchannel port number\n");
-        return;
+    p = config_str;
+    if (legacy_format) {
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+    } else {
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+        if (strcmp(buf, "tcp") && buf[0] != '\0') {
+            goto fail_syntax;
+        }
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+        if (buf[0] != '\0' && !inet_aton(buf, &server)) {
+            goto fail_syntax;
+        }
+        if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+            goto fail_syntax;
+        }
+    }
+    port = strtol(buf, &end, 10);
+    if (*end != '\0' || port < 1 || port > 65535) {
+        goto fail_syntax;
     }
-    devname++;
 
-    vmc = qemu_malloc(sizeof(struct VMChannel));
-    snprintf(name, sizeof(name), "vmchannel%d", port);
-    vmc->hd = qemu_chr_open(name, devname, NULL);
-    if (!vmc->hd) {
-        config_error(mon, "could not open vmchannel device '%s'\n", devname);
-        qemu_free(vmc);
+    fwd = qemu_malloc(sizeof(struct GuestFwd));
+    snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port);
+    fwd->hd = qemu_chr_open(buf, p, NULL);
+    if (!fwd->hd) {
+        config_error(mon, "could not open guest forwarding device '%s'\n",
+                     buf);
+        qemu_free(fwd);
         return;
     }
-    vmc->port = port;
+    fwd->server = server;
+    fwd->port = port;
 
-    slirp_add_exec(3, vmc->hd, 4, port);
-    qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
-                          NULL, vmc);
+    if (slirp_add_exec(3, fwd->hd, server, port) < 0) {
+        config_error(mon, "conflicting/invalid host:port in guest forwarding "
+                     "rule '%s'\n", config_str);
+        qemu_free(fwd);
+        return;
+    }
+    qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
+                          NULL, fwd);
     return;
+
+ fail_syntax:
+    config_error(mon, "invalid guest forwarding rule '%s'\n", config_str);
 }
 
 #endif /* CONFIG_SLIRP */
@@ -2236,15 +2368,21 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
         static const char * const slirp_params[] = {
-            "vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
-            "smb", "redir", "channel", NULL
+            "vlan", "name", "hostname", "restrict", "ip", "net", "host",
+            "tftp", "bootfile", "dhcpstart", "dns", "smb", "smbserver",
+            "hostfwd", "guestfwd", NULL
         };
         struct slirp_config_str *config;
+        int restricted = 0;
+        char *vnet = NULL;
+        char *vhost = NULL;
+        char *vhostname = NULL;
         char *tftp_export = NULL;
         char *bootfile = NULL;
+        char *vdhcp_start = NULL;
+        char *vnamesrv = NULL;
         char *smb_export = NULL;
-        int restricted = 0;
-        char *ip = NULL;
+        char *vsmbsrv = NULL;
         const char *q;
 
         if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
@@ -2252,14 +2390,29 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
             ret = -1;
             goto out;
         }
+        if (get_param_value(buf, sizeof(buf), "ip", p)) {
+            /* emulate legacy parameter */
+            vnet = qemu_malloc(strlen(buf) + strlen("/24") + 1);
+            strcpy(vnet, buf);
+            strcat(vnet, "/24");
+        }
+        if (get_param_value(buf, sizeof(buf), "net", p)) {
+            vnet = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "host", p)) {
+            vhost = qemu_strdup(buf);
+        }
         if (get_param_value(buf, sizeof(buf), "hostname", p)) {
-            pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
+            vhostname = qemu_strdup(buf);
         }
         if (get_param_value(buf, sizeof(buf), "restrict", p)) {
             restricted = (buf[0] == 'y') ? 1 : 0;
         }
-        if (get_param_value(buf, sizeof(buf), "ip", p)) {
-            ip = qemu_strdup(buf);
+        if (get_param_value(buf, sizeof(buf), "dhcpstart", p)) {
+            vdhcp_start = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "dns", p)) {
+            vnamesrv = qemu_strdup(buf);
         }
         if (get_param_value(buf, sizeof(buf), "tftp", p)) {
             tftp_export = qemu_strdup(buf);
@@ -2269,15 +2422,18 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         }
         if (get_param_value(buf, sizeof(buf), "smb", p)) {
             smb_export = qemu_strdup(buf);
+            if (get_param_value(buf, sizeof(buf), "smbserver", p)) {
+                vsmbsrv = qemu_strdup(buf);
+            }
         }
         q = p;
         while (1) {
             config = qemu_malloc(sizeof(*config));
             if (!get_next_param_value(config->str, sizeof(config->str),
-                                      "redir", &q)) {
+                                      "hostfwd", &q)) {
                 break;
             }
-            config->flags = SLIRP_CFG_REDIR;
+            config->flags = SLIRP_CFG_HOSTFWD;
             config->next = slirp_configs;
             slirp_configs = config;
             config = NULL;
@@ -2286,7 +2442,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         while (1) {
             config = qemu_malloc(sizeof(*config));
             if (!get_next_param_value(config->str, sizeof(config->str),
-                                      "channel", &q)) {
+                                      "guestfwd", &q)) {
                 break;
             }
             config->flags = 0;
@@ -2296,23 +2452,29 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         }
         qemu_free(config);
         vlan->nb_host_devs++;
-        ret = net_slirp_init(mon, vlan, device, name, restricted, ip,
-                             tftp_export, bootfile, smb_export);
-        qemu_free(ip);
+        ret = net_slirp_init(mon, vlan, device, name, restricted, vnet, vhost,
+                             vhostname, tftp_export, bootfile, vdhcp_start,
+                             vnamesrv, smb_export, vsmbsrv);
+        qemu_free(vnet);
+        qemu_free(vhost);
+        qemu_free(vhostname);
         qemu_free(tftp_export);
         qemu_free(bootfile);
+        qemu_free(vdhcp_start);
+        qemu_free(vnamesrv);
         qemu_free(smb_export);
+        qemu_free(vsmbsrv);
     } else if (!strcmp(device, "channel")) {
         if (!slirp_inited) {
             struct slirp_config_str *config;
 
             config = qemu_malloc(sizeof(*config));
             pstrcpy(config->str, sizeof(config->str), p);
-            config->flags = 0;
+            config->flags = SLIRP_CFG_LEGACY;
             config->next = slirp_configs;
             slirp_configs = config;
         } else {
-            vmchannel_init(mon, p);
+            slirp_guestfwd(mon, p, 1);
         }
         ret = 0;
     } else
diff --git a/qemu-options.hx b/qemu-options.hx
index b401464..efa4a50 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -749,10 +749,11 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str]\n"
     "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
-    "-net user[,vlan=n][,name=str][ip=netaddr][,restrict=y|n][,hostname=host]\n"
-    "         [,tftp=dir][,bootfile=f][,redir=rule][,channel=rule]"
+    "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n"
+    "         [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"
+    "         [,hostfwd=rule][,guestfwd=rule]"
 #ifndef _WIN32
-                                                                  "[,smb=dir]\n"
+                                             "[,smb=dir[,smbserver=addr]]\n"
 #endif
     "                connect the user mode network stack to VLAN 'n', configure its\n"
     "                DHCP server and enabled optional services\n"
@@ -817,8 +818,14 @@ Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default).
 @item name=@var{name}
 Assign symbolic name for use in monitor commands.
 
-@item ip=@var{netaddr}
-Set IP network address the guest will see (default: 10.0.2.x).
+@item net=@var{addr}[/@var{mask}]
+Set IP network address the guest will see. Optionally specify the netmask,
+either in the form a.b.c.d or as number of valid top-most bits. Default is
+10.0.2.0/8.
+
+@item host=@var{addr}
+Specify the guest-visible address of the host. Default is the 2nd IP in the
+guest network, i.e. x.x.x.2.
 
 @item restrict=y|yes|n|no
 If this options is enabled, the guest will be isolated, i.e. it will not be
@@ -828,12 +835,20 @@ to the outside. This option does not affect explicitly set forwarding rule.
 @item hostname=@var{name}
 Specifies the client hostname reported by the builtin DHCP server.
 
+@item dhcpstart=@var{addr}
+Specify the first of the 16 IPs the built-in DHCP server can assign. Default
+is the 16th to 31st IP in the guest network, i.e. x.x.x.16 to x.x.x.31.
+
+@item dns=@var{addr}
+Specify the guest-visible address of the virtual nameserver. The address must
+be different from the host address. Default is the 3rd IP in the guest network,
+i.e. x.x.x.3.
+
 @item tftp=@var{dir}
 When using the user mode network stack, activate a built-in TFTP
 server. The files in @var{dir} will be exposed as the root of a TFTP server.
 The TFTP client on the guest must be configured in binary mode (use the command
-@code{bin} of the Unix TFTP client). The host IP address on the guest is
-10.0.2.2 by default.
+@code{bin} of the Unix TFTP client).
 
 @item bootfile=@var{file}
 When using the user mode network stack, broadcast @var{file} as the BOOTP
@@ -845,10 +860,11 @@ Example (using pxelinux):
 qemu -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0
 @end example
 
-@item smb=@var{dir}
+@item smb=@var{dir}[,smbserver=@var{addr}]
 When using the user mode network stack, activate a built-in SMB
 server so that Windows OSes can access to the host files in @file{@var{dir}}
-transparently.
+transparently. The IP address of the SMB server can be set to @var{addr}. By
+default the 4th IP in the guest network is used, i.e. x.x.x.4.
 
 In the guest Windows OS, the line:
 @example
@@ -863,19 +879,19 @@ Note that a SAMBA server must be installed on the host OS in
 @file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
 Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
 
-@item redir=[tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
-Redirect incoming TCP or UDP connections to the host port @var{host-port} to
-the guest @var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
-is not specified, its value is 10.0.2.15 (default address given by the built-in
-DHCP server). If no connection type is specified, TCP is used. This option can
-be given multiple times.
+@item hostfwd=[tcp|udp]:@var{hostport}:[@var{guestaddr}]:@var{guestport}
+Redirect incoming TCP or UDP connections to the host port @var{hostport} to
+the guest IP address @var{guestaddr} on guest port @var{guestport}. If
+@var{guestaddr} is not specified, its value is x.x.x.15 (default first address
+given by the built-in DHCP server). If no connection type is specified, TCP is
+used. This option can be given multiple times.
 
 For example, to redirect host X11 connection from screen 1 to guest
 screen 0, use the following:
 
 @example
 # on the host
-qemu -net user,redir=tcp:6001::6000 [...]
+qemu -net user,hostfwd=tcp:6001::6000 [...]
 # this host xterm should open in the guest X11 server
 xterm -display :1
 @end example
@@ -885,14 +901,14 @@ the guest, use the following:
 
 @example
 # on the host
-qemu -net user,redir=tcp:5555::23 [...]
+qemu -net user,hostfwd=tcp:5555::23 [...]
 telnet localhost 5555
 @end example
 
 Then when you use on the host @code{telnet localhost 5555}, you
 connect to the guest telnet server.
 
-@item channel=@var{port}:@var{dev}
+@item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev}
 Forward guest TCP connections to port @var{port} on the host to character
 device @var{dev}. This option can be given multiple times.
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 7dee34b..e4c9c99 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,8 +5,11 @@
 extern "C" {
 #endif
 
-void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
-                const char *bootfile);
+void slirp_init(int restricted, struct in_addr vnetwork,
+                struct in_addr vnetmask, struct in_addr vhost,
+                const char *vhostname, const char *tftp_path,
+                const char *bootfile, struct in_addr vdhcp_start,
+                struct in_addr vnameserver);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -19,18 +22,17 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
 int slirp_can_output(void);
 void slirp_output(const uint8_t *pkt, int pkt_len);
 
-int slirp_redir_rm(int is_udp, int host_port);
-int slirp_redir(int is_udp, int host_port,
-                struct in_addr guest_addr, int guest_port);
-int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
-                   int guest_port);
+int slirp_add_hostfwd(int is_udp, int host_port,
+                      struct in_addr guest_addr, int guest_port);
+int slirp_remove_hostfwd(int is_udp, int host_port);
 
-extern char slirp_hostname[33];
+int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
+                   int guest_port);
 
 void slirp_stats(void);
-void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
-		int size);
-size_t slirp_socket_can_recv(int addr_low_byte, int guest_port);
+void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
+                       const uint8_t *buf, int size);
+size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port);
 
 #ifdef __cplusplus
 }
diff --git a/slirp/main.h b/slirp/main.h
index edbb9cb..891220a 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -47,6 +47,7 @@ extern int ppp_exit;
 extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
 extern int slirp_restrict;
+extern char slirp_hostname[33];
 extern char *tftp_prefix;
 extern char *bootp_filename;
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 8affd46..a918232 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -173,12 +173,14 @@ static void slirp_cleanup(void)
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
-void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
-                const char *bootfile)
+void slirp_init(int restricted, struct in_addr vnetwork,
+                struct in_addr vnetmask, struct in_addr vhost,
+                const char *vhostname, const char *tftp_path,
+                const char *bootfile, struct in_addr vdhcp_start,
+                struct in_addr vnameserver)
 {
     //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
 
-    struct in_addr special_addr = { .s_addr = htonl(0x0a000200) };
 #ifdef _WIN32
     WSADATA Data;
 
@@ -203,8 +205,11 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
         fprintf (stderr, "Warning: No DNS servers found\n");
     }
 
-    if (special_ip) {
-        inet_aton(special_ip, &special_addr);
+    vnetwork_addr = vnetwork;
+    vnetwork_mask = vnetmask;
+    vhost_addr = vhost;
+    if (vhostname) {
+        pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname);
     }
     qemu_free(tftp_prefix);
     tftp_prefix = NULL;
@@ -216,12 +221,9 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
     if (bootfile) {
         bootp_filename = qemu_strdup(bootfile);
     }
+    vdhcp_startaddr = vdhcp_start;
+    vnameserver_addr = vnameserver;
 
-    vnetwork_addr = special_addr;
-    vnetwork_mask.s_addr = htonl(0xffffff00);
-    vhost_addr.s_addr = special_addr.s_addr | htonl(2);
-    vdhcp_startaddr.s_addr = special_addr.s_addr | htonl(15);
-    vnameserver_addr.s_addr = special_addr.s_addr | htonl(3);
     getouraddr();
     register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
 }
@@ -755,7 +757,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
 /* Unlistens a redirection
  *
  * Return value: number of redirs removed */
-int slirp_redir_rm(int is_udp, int host_port)
+int slirp_remove_hostfwd(int is_udp, int host_port)
 {
     struct socket *so;
     struct socket *head = (is_udp ? &udb : &tcb);
@@ -775,8 +777,8 @@ int slirp_redir_rm(int is_udp, int host_port)
     return n;
 }
 
-int slirp_redir(int is_udp, int host_port,
-                struct in_addr guest_addr, int guest_port)
+int slirp_add_hostfwd(int is_udp, int host_port,
+                      struct in_addr guest_addr, int guest_port)
 {
     if (!guest_addr.s_addr) {
         guest_addr = vdhcp_startaddr;
@@ -793,13 +795,13 @@ int slirp_redir(int is_udp, int host_port,
     return 0;
 }
 
-int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
-                  int guest_port)
+int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
+                   int guest_port)
 {
-    struct in_addr guest_addr = {
-        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
-    };
-
+    if (!guest_addr.s_addr) {
+        guest_addr.s_addr =
+            vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr);
+    }
     if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
         guest_addr.s_addr == vhost_addr.s_addr ||
         guest_addr.s_addr == vnameserver_addr.s_addr) {
@@ -833,11 +835,8 @@ slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
     return NULL;
 }
 
-size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
+size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
 {
-    struct in_addr guest_addr = {
-        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
-    };
 	struct iovec iov[2];
 	struct socket *so;
 
@@ -855,13 +854,10 @@ size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
 	return sopreprbuf(so, iov, NULL);
 }
 
-void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
-        int size)
+void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
+                       const uint8_t *buf, int size)
 {
     int ret;
-    struct in_addr guest_addr = {
-        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
-    };
     struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
 
     if (!so)

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 10/41] slirp: Bind support for host forwarding rules
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (4 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 03/41] Revert "User networking: Show active connections" Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 09/41] slirp: Rework monitor commands for host forwarding Jan Kiszka
                   ` (35 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

From: Jan Kiszka <jan.kiszka@web.de>

Extend the hostfwd rule format so that the user can specify on which
host interface qemu should listen for incoming connections. If omitted,
binding will takes place against all interfaces.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |   50 ++++++++++++++++++++++++++++++++++++--------------
 net.h            |    2 +-
 qemu-monitor.hx  |    5 +++--
 qemu-options.hx  |   11 ++++++-----
 slirp/libslirp.h |    5 ++---
 slirp/slirp.c    |   11 ++++++-----
 slirp/socket.c   |   10 +++++-----
 slirp/socket.h   |    2 +-
 slirp/tcp_subr.c |   15 ++++++++-------
 slirp/udp.c      |    7 ++++---
 slirp/udp.h      |    2 +-
 11 files changed, 73 insertions(+), 47 deletions(-)

diff --git a/net.c b/net.c
index 75a7408..6753993 100644
--- a/net.c
+++ b/net.c
@@ -685,7 +685,8 @@ const char *legacy_tftp_prefix;
 const char *legacy_bootp_filename;
 static VLANClientState *slirp_vc;
 
-static void slirp_hostfwd(Monitor *mon, const char *redir_str);
+static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+                          int legacy_format);
 static void slirp_guestfwd(Monitor *mon, const char *config_str,
                            int legacy_format);
 
@@ -846,7 +847,8 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
             struct slirp_config_str *config = slirp_configs;
 
             if (config->flags & SLIRP_CFG_HOSTFWD) {
-                slirp_hostfwd(mon, config->str);
+                slirp_hostfwd(mon, config->str,
+                              config->flags & SLIRP_CFG_LEGACY);
             } else {
                 slirp_guestfwd(mon, config->str,
                                config->flags & SLIRP_CFG_LEGACY);
@@ -871,11 +873,12 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
     return 0;
 }
 
-void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
+void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
 {
+    struct in_addr host_addr = { .s_addr = INADDR_ANY };
     int host_port;
     char buf[256] = "";
-    const char *p = port_str;
+    const char *p = src_str;
     int is_udp = 0;
     int n;
 
@@ -884,7 +887,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
         return;
     }
 
-    if (!port_str || !port_str[0])
+    if (!src_str || !src_str[0])
         goto fail_syntax;
 
     get_str_sep(buf, sizeof(buf), &p, ':');
@@ -897,20 +900,29 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
         goto fail_syntax;
     }
 
+    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+        goto fail_syntax;
+    }
+    if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
+        goto fail_syntax;
+    }
+
     host_port = atoi(p);
 
-    n = slirp_remove_hostfwd(is_udp, host_port);
+    n = slirp_remove_hostfwd(is_udp, host_addr, host_port);
 
-    monitor_printf(mon, "removed %d host forwarding rules for %s port %d\n",
-                   n, is_udp ? "udp" : "tcp", host_port);
+    monitor_printf(mon, "removed %d host forwarding rules for %s\n", n,
+                   src_str);
     return;
 
  fail_syntax:
     monitor_printf(mon, "invalid format\n");
 }
 
-static void slirp_hostfwd(Monitor *mon, const char *redir_str)
+static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+                          int legacy_format)
 {
+    struct in_addr host_addr = { .s_addr = INADDR_ANY };
     struct in_addr guest_addr = { .s_addr = 0 };
     int host_port, guest_port;
     const char *p;
@@ -930,7 +942,16 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str)
         goto fail_syntax;
     }
 
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (!legacy_format) {
+        if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+            goto fail_syntax;
+        }
+        if (buf[0] != '\0' && !inet_aton(buf, &host_addr)) {
+            goto fail_syntax;
+        }
+    }
+
+    if (get_str_sep(buf, sizeof(buf), &p, legacy_format ? ':' : '-') < 0) {
         goto fail_syntax;
     }
     host_port = strtol(buf, &end, 0);
@@ -950,7 +971,8 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str)
         goto fail_syntax;
     }
 
-    if (slirp_add_hostfwd(is_udp, host_port, guest_addr, guest_port) < 0) {
+    if (slirp_add_hostfwd(is_udp, host_addr, host_port,
+                          guest_addr, guest_port) < 0) {
         config_error(mon, "could not set up host forwarding rule '%s'\n",
                      redir_str);
     }
@@ -967,7 +989,7 @@ void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str)
         return;
     }
 
-    slirp_hostfwd(mon, redir_str);
+    slirp_hostfwd(mon, redir_str, 0);
 }
 
 void net_slirp_redir(const char *redir_str)
@@ -977,13 +999,13 @@ void net_slirp_redir(const char *redir_str)
     if (!slirp_inited) {
         config = qemu_malloc(sizeof(*config));
         pstrcpy(config->str, sizeof(config->str), redir_str);
-        config->flags = SLIRP_CFG_HOSTFWD;
+        config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
         config->next = slirp_configs;
         slirp_configs = config;
         return;
     }
 
-    slirp_hostfwd(NULL, redir_str);
+    slirp_hostfwd(NULL, redir_str, 1);
 }
 
 #ifndef _WIN32
diff --git a/net.h b/net.h
index 884c354..6e91828 100644
--- a/net.h
+++ b/net.h
@@ -129,7 +129,7 @@ void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
 void net_slirp_smb(const char *exported_dir);
 void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str);
-void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str);
+void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str);
 void net_slirp_redir(const char *redir_str);
 void net_cleanup(void);
 int slirp_is_inited(void);
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 13c98bc..34f6992 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -537,10 +537,11 @@ ETEXI
 
 #ifdef CONFIG_SLIRP
     { "hostfwd_add", "s", net_slirp_hostfwd_add,
-      "[tcp|udp]:hostport:[guestaddr]:guestport",
+      "[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
       "redirect TCP or UDP connections from host to guest (requires -net user)" },
     { "hostfwd_remove", "s", net_slirp_hostfwd_remove,
-      "[tcp|udp]:hostport", "remove host-to-guest TCP or UDP redirection" },
+      "[tcp|udp]:[hostaddr]:hostport",
+      "remove host-to-guest TCP or UDP redirection" },
 #endif
 STEXI
 @item host_net_redir
diff --git a/qemu-options.hx b/qemu-options.hx
index efa4a50..517665b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -879,11 +879,12 @@ Note that a SAMBA server must be installed on the host OS in
 @file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
 Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
 
-@item hostfwd=[tcp|udp]:@var{hostport}:[@var{guestaddr}]:@var{guestport}
+@item hostfwd=[tcp|udp]:[@var{hostaddr}]:@var{hostport}-[@var{guestaddr}]:@var{guestport}
 Redirect incoming TCP or UDP connections to the host port @var{hostport} to
 the guest IP address @var{guestaddr} on guest port @var{guestport}. If
 @var{guestaddr} is not specified, its value is x.x.x.15 (default first address
-given by the built-in DHCP server). If no connection type is specified, TCP is
+given by the built-in DHCP server). By specifying @var{hostaddr}, the rule can
+be bound to a specific host interface. If no connection type is set, TCP is
 used. This option can be given multiple times.
 
 For example, to redirect host X11 connection from screen 1 to guest
@@ -891,7 +892,7 @@ screen 0, use the following:
 
 @example
 # on the host
-qemu -net user,hostfwd=tcp:6001::6000 [...]
+qemu -net user,hostfwd=tcp:127.0.0.1:6001-:6000 [...]
 # this host xterm should open in the guest X11 server
 xterm -display :1
 @end example
@@ -909,8 +910,8 @@ Then when you use on the host @code{telnet localhost 5555}, you
 connect to the guest telnet server.
 
 @item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev}
-Forward guest TCP connections to port @var{port} on the host to character
-device @var{dev}. This option can be given multiple times.
+Forward guest TCP connections to the IP address @var{server} on port @var{port}
+to the character device @var{dev}. This option can be given multiple times.
 
 @end table
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index e4c9c99..9be4425 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -22,10 +22,9 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
 int slirp_can_output(void);
 void slirp_output(const uint8_t *pkt, int pkt_len);
 
-int slirp_add_hostfwd(int is_udp, int host_port,
+int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
                       struct in_addr guest_addr, int guest_port);
-int slirp_remove_hostfwd(int is_udp, int host_port);
-
+int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port);
 int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
                    int guest_port);
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index ad88121..ab0a854 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -757,7 +757,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
 /* Unlistens a redirection
  *
  * Return value: number of redirs removed */
-int slirp_remove_hostfwd(int is_udp, int host_port)
+int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
 {
     struct socket *so;
     struct socket *head = (is_udp ? &udb : &tcb);
@@ -770,6 +770,7 @@ int slirp_remove_hostfwd(int is_udp, int host_port)
     for (so = head->so_next; so != head; so = so->so_next) {
         addr_len = sizeof(addr);
         if (getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
+            addr.sin_addr.s_addr == host_addr.s_addr &&
             addr.sin_port == port) {
             close(so->s);
             sofree(so);
@@ -781,19 +782,19 @@ int slirp_remove_hostfwd(int is_udp, int host_port)
     return n;
 }
 
-int slirp_add_hostfwd(int is_udp, int host_port,
+int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
                       struct in_addr guest_addr, int guest_port)
 {
     if (!guest_addr.s_addr) {
         guest_addr = vdhcp_startaddr;
     }
     if (is_udp) {
-        if (!udp_listen(htons(host_port), guest_addr.s_addr,
+        if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
                         htons(guest_port), 0))
             return -1;
     } else {
-        if (!solisten(htons(host_port), guest_addr.s_addr,
-                      htons(guest_port), 0))
+        if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
+                        htons(guest_port), 0))
             return -1;
     }
     return 0;
diff --git a/slirp/socket.c b/slirp/socket.c
index 9f13f03..936021e 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -586,17 +586,17 @@ sosendto(struct socket *so, struct mbuf *m)
 }
 
 /*
- * XXX This should really be tcp_listen
+ * Listen for incoming TCP connections
  */
 struct socket *
-solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
+tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
 	int s, opt = 1;
 	socklen_t addrlen = sizeof(addr);
 
-	DEBUG_CALL("solisten");
+	DEBUG_CALL("tcp_listen");
 	DEBUG_ARG("port = %d", port);
 	DEBUG_ARG("laddr = %x", laddr);
 	DEBUG_ARG("lport = %d", lport);
@@ -625,8 +625,8 @@ solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
 	so->so_laddr.s_addr = laddr; /* Ditto */
 
 	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = INADDR_ANY;
-	addr.sin_port = port;
+	addr.sin_addr.s_addr = haddr;
+	addr.sin_port = hport;
 
 	if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
 	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
diff --git a/slirp/socket.h b/slirp/socket.h
index f5adaba..ac36aaa 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -82,7 +82,7 @@ int sosendoob _P((struct socket *));
 int sowrite _P((struct socket *));
 void sorecvfrom _P((struct socket *));
 int sosendto _P((struct socket *, struct mbuf *));
-struct socket * solisten _P((u_int, u_int32_t, u_int, int));
+struct socket * tcp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
 void soisfconnecting _P((register struct socket *));
 void soisfconnected _P((register struct socket *));
 void soisfdisconnected _P((struct socket *));
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 858d1ae..6fa4223 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -970,7 +970,7 @@ do_prompt:
 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 			lport = htons((n5 << 8) | (n6));
 
-			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 			   return 1;
 
 			n6 = ntohs(so->so_fport);
@@ -1002,7 +1002,7 @@ do_prompt:
 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 			lport = htons((n5 << 8) | (n6));
 
-			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 			   return 1;
 
 			n6 = ntohs(so->so_fport);
@@ -1042,7 +1042,7 @@ do_prompt:
 			lport += m->m_data[i] - '0';
 		}
 		if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
-		    (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
+		    (so = tcp_listen(INADDR_ANY, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
                     m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
                                         ntohs(so->so_fport)) + 1;
 		return 1;
@@ -1057,7 +1057,7 @@ do_prompt:
 
 		/* The %256s is for the broken mIRC */
 		if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
-			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1066,7 +1066,7 @@ do_prompt:
                                              (unsigned long)ntohl(so->so_faddr.s_addr),
                                              ntohs(so->so_fport), 1);
 		} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
-			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1075,7 +1075,7 @@ do_prompt:
                                              (unsigned long)ntohl(so->so_faddr.s_addr),
                                              ntohs(so->so_fport), n1, 1);
 		} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
-			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1190,7 +1190,8 @@ do_prompt:
 
 				/* try to get udp port between 6970 - 7170 */
 				for (p = 6970; p < 7071; p++) {
-					if (udp_listen( htons(p),
+					if (udp_listen(INADDR_ANY,
+						       htons(p),
 						       so->so_laddr.s_addr,
 						       htons(lport),
 						       SS_FACCEPTONCE)) {
diff --git a/slirp/udp.c b/slirp/udp.c
index ff3a39f..d675ad3 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -627,7 +627,8 @@ struct cu_header {
 }
 
 struct socket *
-udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
+udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
+           int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
@@ -642,8 +643,8 @@ udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
 	insque(so,&udb);
 
 	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = INADDR_ANY;
-	addr.sin_port = port;
+	addr.sin_addr.s_addr = haddr;
+	addr.sin_port = hport;
 
 	if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
 		udp_detach(so);
diff --git a/slirp/udp.h b/slirp/udp.h
index 51a07a2..d4c2bea 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -101,7 +101,7 @@ void udp_input _P((register struct mbuf *, int));
 int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
 int udp_attach _P((struct socket *));
 void udp_detach _P((struct socket *));
-struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
+struct socket * udp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
 int udp_output2(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos);

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 05/41] slirp: Move smb, redir, tftp and bootp parameters and -net channel
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (6 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 09/41] slirp: Rework monitor commands for host forwarding Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 07/41] slirp: Rework external configuration interface Jan Kiszka
                   ` (33 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

So far a couple of slirp-related parameters were expressed via
stand-alone command line options. This it inconsistent and unintuitive.
Moreover, it prevents both dynamically reconfigured (host_net_add/
delete) and multi-instance slirp.

This patch refactors the configuration by turning -smb, -redir, -tftp
and -bootp as well as -net channel into options of "-net user". The old
stand-alone command line options are still processed, but no longer
advertised. This allows smooth migration of management applications to
to the new syntax and also the extension of that syntax later in this
series.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  175 +++++++++++++++++++++++++++++++++------------
 net.h            |    3 +
 qemu-options.hx  |  209 +++++++++++++++++++++++++++++-------------------------
 slirp/bootp.c    |    2 -
 slirp/libslirp.h |    5 +
 slirp/main.h     |    2 +
 slirp/slirp.c    |   14 +++-
 slirp/tftp.c     |    2 -
 vl.c             |    6 +-
 9 files changed, 265 insertions(+), 153 deletions(-)

diff --git a/net.c b/net.c
index 87a6e76..f7596d2 100644
--- a/net.c
+++ b/net.c
@@ -669,22 +669,28 @@ static void config_error(Monitor *mon, const char *fmt, ...)
 
 /* slirp network adapter */
 
+#define SLIRP_CFG_REDIR 1
+
 struct slirp_config_str {
     struct slirp_config_str *next;
-    const char *str;
+    int flags;
+    char str[1024];
 };
 
 static int slirp_inited;
-static struct slirp_config_str *slirp_redirs;
-#ifndef _WIN32
-static const char *slirp_smb_export;
-#endif
+static struct slirp_config_str *slirp_configs;
+const char *legacy_tftp_prefix;
+const char *legacy_bootp_filename;
 static VLANClientState *slirp_vc;
 
+static void slirp_redirection(Monitor *mon, const char *redir_str);
+static void vmchannel_init(Monitor *mon, const char *config_str);
+
 #ifndef _WIN32
+static const char *legacy_smb_export;
+
 static void slirp_smb(const char *exported_dir);
 #endif
-static void slirp_redirection(Monitor *mon, const char *redir_str);
 
 int slirp_can_output(void)
 {
@@ -724,27 +730,42 @@ static void net_slirp_cleanup(VLANClientState *vc)
     slirp_in_use = 0;
 }
 
-static int net_slirp_init(VLANState *vlan, const char *model, const char *name,
-                          int restricted, const char *ip)
+static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
+                          const char *name, int restricted, const char *ip,
+                          const char *tftp_export, const char *bootfile,
+                          const char *smb_export)
 {
     if (slirp_in_use) {
         /* slirp only supports a single instance so far */
         return -1;
     }
     if (!slirp_inited) {
+        if (!tftp_export) {
+            tftp_export = legacy_tftp_prefix;
+        }
+        if (!bootfile) {
+            bootfile = legacy_bootp_filename;
+        }
         slirp_inited = 1;
-        slirp_init(restricted, ip);
+        slirp_init(restricted, ip, tftp_export, bootfile);
 
-        while (slirp_redirs) {
-            struct slirp_config_str *config = slirp_redirs;
+        while (slirp_configs) {
+            struct slirp_config_str *config = slirp_configs;
 
-            slirp_redirection(NULL, config->str);
-            slirp_redirs = config->next;
+            if (config->flags & SLIRP_CFG_REDIR) {
+                slirp_redirection(mon, config->str);
+            } else {
+                vmchannel_init(mon, config->str);
+            }
+            slirp_configs = config->next;
             qemu_free(config);
         }
 #ifndef _WIN32
-        if (slirp_smb_export) {
-            slirp_smb(slirp_smb_export);
+        if (!smb_export) {
+            smb_export = legacy_smb_export;
+        }
+        if (smb_export) {
+            slirp_smb(smb_export);
         }
 #endif
     }
@@ -853,9 +874,10 @@ void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2
             monitor_printf(mon, "user mode network stack not in use\n");
         } else {
             config = qemu_malloc(sizeof(*config));
-            config->str = redir_str;
-            config->next = slirp_redirs;
-            slirp_redirs = config;
+            pstrcpy(config->str, sizeof(config->str), redir_str);
+            config->flags = SLIRP_CFG_REDIR;
+            config->next = slirp_configs;
+            slirp_configs = config;
         }
         return;
     }
@@ -952,14 +974,14 @@ static void slirp_smb(const char *exported_dir)
     slirp_add_exec(0, smb_cmdline, 4, 139);
 }
 
-/* automatic user mode samba server configuration */
+/* automatic user mode samba server configuration (legacy interface) */
 void net_slirp_smb(const char *exported_dir)
 {
-    if (slirp_smb_export) {
+    if (legacy_smb_export) {
         fprintf(stderr, "-smb given twice\n");
         exit(1);
     }
-    slirp_smb_export = exported_dir;
+    legacy_smb_export = exported_dir;
     if (slirp_inited) {
         slirp_smb(exported_dir);
     }
@@ -989,6 +1011,36 @@ static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
     slirp_socket_recv(4, vmc->port, buf, size);
 }
 
+static void vmchannel_init(Monitor *mon, const char *config_str)
+{
+    struct VMChannel *vmc;
+    char *devname;
+    char name[20];
+    int port;
+
+    port = strtol(config_str, &devname, 10);
+    if (port < 1 || port > 65535 || *devname != ':') {
+        config_error(mon, "invalid vmchannel port number\n");
+        return;
+    }
+    devname++;
+
+    vmc = qemu_malloc(sizeof(struct VMChannel));
+    snprintf(name, sizeof(name), "vmchannel%d", port);
+    vmc->hd = qemu_chr_open(name, devname, NULL);
+    if (!vmc->hd) {
+        config_error(mon, "could not open vmchannel device '%s'\n", devname);
+        qemu_free(vmc);
+        return;
+    }
+    vmc->port = port;
+
+    slirp_add_exec(3, vmc->hd, 4, port);
+    qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
+                          NULL, vmc);
+    return;
+}
+
 #endif /* CONFIG_SLIRP */
 
 #if !defined(_WIN32)
@@ -2184,10 +2236,16 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
         static const char * const slirp_params[] = {
-            "vlan", "name", "hostname", "restrict", "ip", NULL
+            "vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
+            "smb", "redir", "channel", NULL
         };
+        struct slirp_config_str *config;
+        char *tftp_export = NULL;
+        char *bootfile = NULL;
+        char *smb_export = NULL;
         int restricted = 0;
         char *ip = NULL;
+        const char *q;
 
         if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
             config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p);
@@ -2203,34 +2261,59 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "ip", p)) {
             ip = qemu_strdup(buf);
         }
+        if (get_param_value(buf, sizeof(buf), "tftp", p)) {
+            tftp_export = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "bootfile", p)) {
+            bootfile = qemu_strdup(buf);
+        }
+        if (get_param_value(buf, sizeof(buf), "smb", p)) {
+            smb_export = qemu_strdup(buf);
+        }
+        q = p;
+        while (1) {
+            config = qemu_malloc(sizeof(*config));
+            if (!get_next_param_value(config->str, sizeof(config->str),
+                                      "redir", &q)) {
+                break;
+            }
+            config->flags = SLIRP_CFG_REDIR;
+            config->next = slirp_configs;
+            slirp_configs = config;
+            config = NULL;
+        }
+        q = p;
+        while (1) {
+            config = qemu_malloc(sizeof(*config));
+            if (!get_next_param_value(config->str, sizeof(config->str),
+                                      "channel", &q)) {
+                break;
+            }
+            config->flags = 0;
+            config->next = slirp_configs;
+            slirp_configs = config;
+            config = NULL;
+        }
+        qemu_free(config);
         vlan->nb_host_devs++;
-        ret = net_slirp_init(vlan, device, name, restricted, ip);
+        ret = net_slirp_init(mon, vlan, device, name, restricted, ip,
+                             tftp_export, bootfile, smb_export);
         qemu_free(ip);
+        qemu_free(tftp_export);
+        qemu_free(bootfile);
+        qemu_free(smb_export);
     } else if (!strcmp(device, "channel")) {
-        long port;
-        char name[20], *devname;
-        struct VMChannel *vmc;
-
-        port = strtol(p, &devname, 10);
-        devname++;
-        if (port < 1 || port > 65535) {
-            config_error(mon, "vmchannel wrong port number\n");
-            ret = -1;
-            goto out;
-        }
-        vmc = malloc(sizeof(struct VMChannel));
-        snprintf(name, 20, "vmchannel%ld", port);
-        vmc->hd = qemu_chr_open(name, devname, NULL);
-        if (!vmc->hd) {
-            config_error(mon, "could not open vmchannel device '%s'\n",
-                         devname);
-            ret = -1;
-            goto out;
+        if (!slirp_inited) {
+            struct slirp_config_str *config;
+
+            config = qemu_malloc(sizeof(*config));
+            pstrcpy(config->str, sizeof(config->str), p);
+            config->flags = 0;
+            config->next = slirp_configs;
+            slirp_configs = config;
+        } else {
+            vmchannel_init(mon, p);
         }
-        vmc->port = port;
-        slirp_add_exec(3, vmc->hd, 4, port);
-        qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
-                NULL, vmc);
         ret = 0;
     } else
 #endif
diff --git a/net.h b/net.h
index a1c4d2c..e705c87 100644
--- a/net.h
+++ b/net.h
@@ -121,6 +121,9 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto,
 void net_checksum_calculate(uint8_t *data, int length);
 
 /* from net.c */
+extern const char *legacy_tftp_prefix;
+extern const char *legacy_bootp_filename;
+
 int net_client_init(Monitor *mon, const char *device, const char *p);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
diff --git a/qemu-options.hx b/qemu-options.hx
index 503da33..b401464 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -735,13 +735,27 @@ STEXI
 @table @option
 ETEXI
 
+HXCOMM Legacy slirp options (now moved to -net user):
+#ifdef CONFIG_SLIRP
+DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, "")
+DEF("bootp", HAS_ARG, QEMU_OPTION_bootp, "")
+DEF("redir", HAS_ARG, QEMU_OPTION_redir, "")
+#ifndef _WIN32
+DEF("smb", HAS_ARG, QEMU_OPTION_smb, "")
+#endif
+#endif
+
 DEF("net", HAS_ARG, QEMU_OPTION_net,
     "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str]\n"
     "                create a new Network Interface Card and connect it to VLAN 'n'\n"
 #ifdef CONFIG_SLIRP
-    "-net user[,vlan=n][,name=str][,hostname=host]\n"
-    "                connect the user mode network stack to VLAN 'n' and send\n"
-    "                hostname 'host' to DHCP clients\n"
+    "-net user[,vlan=n][,name=str][ip=netaddr][,restrict=y|n][,hostname=host]\n"
+    "         [,tftp=dir][,bootfile=f][,redir=rule][,channel=rule]"
+#ifndef _WIN32
+                                                                  "[,smb=dir]\n"
+#endif
+    "                connect the user mode network stack to VLAN 'n', configure its\n"
+    "                DHCP server and enabled optional services\n"
 #endif
 #ifdef _WIN32
     "-net tap[,vlan=n][,name=str],ifname=name\n"
@@ -792,13 +806,102 @@ Valid values for @var{type} are
 Not all devices are supported on all targets.  Use -net nic,model=?
 for a list of available devices for your target.
 
-@item -net user[,vlan=@var{n}][,hostname=@var{name}][,name=@var{name}]
+@item -net user[,@var{option}][,@var{option}][,...]
 Use the user mode network stack which requires no administrator
-privilege to run.  @option{hostname=name} can be used to specify the client
-hostname reported by the builtin DHCP server.
+privilege to run. Valid options are:
+
+@table @code
+@item vlan=@var{n}
+Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default).
+
+@item name=@var{name}
+Assign symbolic name for use in monitor commands.
+
+@item ip=@var{netaddr}
+Set IP network address the guest will see (default: 10.0.2.x).
+
+@item restrict=y|yes|n|no
+If this options is enabled, the guest will be isolated, i.e. it will not be
+able to contact the host and no guest IP packets will be routed over the host
+to the outside. This option does not affect explicitly set forwarding rule.
+
+@item hostname=@var{name}
+Specifies the client hostname reported by the builtin DHCP server.
+
+@item tftp=@var{dir}
+When using the user mode network stack, activate a built-in TFTP
+server. The files in @var{dir} will be exposed as the root of a TFTP server.
+The TFTP client on the guest must be configured in binary mode (use the command
+@code{bin} of the Unix TFTP client). The host IP address on the guest is
+10.0.2.2 by default.
+
+@item bootfile=@var{file}
+When using the user mode network stack, broadcast @var{file} as the BOOTP
+filename. In conjunction with @option{tftp}, this can be used to network boot
+a guest from a local directory.
+
+Example (using pxelinux):
+@example
+qemu -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0
+@end example
+
+@item smb=@var{dir}
+When using the user mode network stack, activate a built-in SMB
+server so that Windows OSes can access to the host files in @file{@var{dir}}
+transparently.
+
+In the guest Windows OS, the line:
+@example
+10.0.2.4 smbserver
+@end example
+must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me)
+or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
+
+Then @file{@var{dir}} can be accessed in @file{\\smbserver\qemu}.
+
+Note that a SAMBA server must be installed on the host OS in
+@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
+Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
+
+@item redir=[tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
+Redirect incoming TCP or UDP connections to the host port @var{host-port} to
+the guest @var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
+is not specified, its value is 10.0.2.15 (default address given by the built-in
+DHCP server). If no connection type is specified, TCP is used. This option can
+be given multiple times.
+
+For example, to redirect host X11 connection from screen 1 to guest
+screen 0, use the following:
+
+@example
+# on the host
+qemu -net user,redir=tcp:6001::6000 [...]
+# this host xterm should open in the guest X11 server
+xterm -display :1
+@end example
+
+To redirect telnet connections from host port 5555 to telnet port on
+the guest, use the following:
+
+@example
+# on the host
+qemu -net user,redir=tcp:5555::23 [...]
+telnet localhost 5555
+@end example
+
+Then when you use on the host @code{telnet localhost 5555}, you
+connect to the guest telnet server.
 
-@item -net channel,@var{port}:@var{dev}
-Forward @option{user} TCP connection to port @var{port} to character device @var{dev}
+@item channel=@var{port}:@var{dev}
+Forward guest TCP connections to port @var{port} on the host to character
+device @var{dev}. This option can be given multiple times.
+
+@end table
+
+Note: Legacy stand-alone options -tftp, -bootp, -smb and -redir are still
+processed and applied to -net user. Mixing them with the new configuration
+syntax gives undefined results. Their use for new applications is discouraged
+as they will be removed from future versions.
 
 @item -net tap[,vlan=@var{n}][,name=@var{name}][,fd=@var{h}][,ifname=@var{name}][,script=@var{file}][,downscript=@var{dfile}]
 Connect the host TAP network interface @var{name} to VLAN @var{n}, use
@@ -904,96 +1007,6 @@ libpcap, so it can be analyzed with tools such as tcpdump or Wireshark.
 Indicate that no network devices should be configured. It is used to
 override the default configuration (@option{-net nic -net user}) which
 is activated if no @option{-net} options are provided.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("tftp", HAS_ARG, QEMU_OPTION_tftp, \
-    "-tftp dir       allow tftp access to files in dir [-net user]\n")
-#endif
-STEXI
-@item -tftp @var{dir}
-When using the user mode network stack, activate a built-in TFTP
-server. The files in @var{dir} will be exposed as the root of a TFTP server.
-The TFTP client on the guest must be configured in binary mode (use the command
-@code{bin} of the Unix TFTP client). The host IP address on the guest is as
-usual 10.0.2.2.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("bootp", HAS_ARG, QEMU_OPTION_bootp, \
-    "-bootp file     advertise file in BOOTP replies\n")
-#endif
-STEXI
-@item -bootp @var{file}
-When using the user mode network stack, broadcast @var{file} as the BOOTP
-filename.  In conjunction with @option{-tftp}, this can be used to network boot
-a guest from a local directory.
-
-Example (using pxelinux):
-@example
-qemu -hda linux.img -boot n -tftp /path/to/tftp/files -bootp /pxelinux.0
-@end example
-ETEXI
-
-#ifndef _WIN32
-DEF("smb", HAS_ARG, QEMU_OPTION_smb, \
-           "-smb dir        allow SMB access to files in 'dir' [-net user]\n")
-#endif
-STEXI
-@item -smb @var{dir}
-When using the user mode network stack, activate a built-in SMB
-server so that Windows OSes can access to the host files in @file{@var{dir}}
-transparently.
-
-In the guest Windows OS, the line:
-@example
-10.0.2.4 smbserver
-@end example
-must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me)
-or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
-
-Then @file{@var{dir}} can be accessed in @file{\\smbserver\qemu}.
-
-Note that a SAMBA server must be installed on the host OS in
-@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd version
-2.2.7a from the Red Hat 9 and version 3.0.10-1.fc3 from Fedora Core 3.
-ETEXI
-
-#ifdef CONFIG_SLIRP
-DEF("redir", HAS_ARG, QEMU_OPTION_redir, \
-    "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" \
-    "                redirect TCP or UDP connections from host to guest [-net user]\n")
-#endif
-STEXI
-@item -redir [tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
-
-When using the user mode network stack, redirect incoming TCP or UDP
-connections to the host port @var{host-port} to the guest
-@var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
-is not specified, its value is 10.0.2.15 (default address given by the
-built-in DHCP server). If no connection type is specified, TCP is used.
-
-For example, to redirect host X11 connection from screen 1 to guest
-screen 0, use the following:
-
-@example
-# on the host
-qemu -redir tcp:6001::6000 [...]
-# this host xterm should open in the guest X11 server
-xterm -display :1
-@end example
-
-To redirect telnet connections from host port 5555 to telnet port on
-the guest, use the following:
-
-@example
-# on the host
-qemu -redir tcp:5555::23 [...]
-telnet localhost 5555
-@end example
-
-Then when you use on the host @code{telnet localhost 5555}, you
-connect to the guest telnet server.
 
 @end table
 ETEXI
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 4e0082d..a2fd734 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -38,7 +38,7 @@ typedef struct {
 
 static BOOTPClient bootp_clients[NB_ADDR];
 
-const char *bootp_filename;
+char *bootp_filename;
 
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index c04f3a2..7dee34b 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,7 +5,8 @@
 extern "C" {
 #endif
 
-void slirp_init(int restricted, const char *special_ip);
+void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
+                const char *bootfile);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -24,9 +25,7 @@ int slirp_redir(int is_udp, int host_port,
 int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
                    int guest_port);
 
-extern const char *tftp_prefix;
 extern char slirp_hostname[33];
-extern const char *bootp_filename;
 
 void slirp_stats(void);
 void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
diff --git a/slirp/main.h b/slirp/main.h
index ed51385..89e722f 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -46,6 +46,8 @@ extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
 extern const char *slirp_special_ip;
 extern int slirp_restrict;
+extern char *tftp_prefix;
+extern char *bootp_filename;
 
 #define PROTO_SLIP 0x1
 #ifdef USE_PPP
diff --git a/slirp/slirp.c b/slirp/slirp.c
index b3db742..b0a092c 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -171,7 +171,8 @@ static void slirp_cleanup(void)
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
-void slirp_init(int restricted, const char *special_ip)
+void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
+                const char *bootfile)
 {
     //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
 
@@ -203,6 +204,17 @@ void slirp_init(int restricted, const char *special_ip)
     if (special_ip)
         slirp_special_ip = special_ip;
 
+    qemu_free(tftp_prefix);
+    tftp_prefix = NULL;
+    if (tftp_path) {
+        tftp_prefix = qemu_strdup(tftp_path);
+    }
+    qemu_free(bootp_filename);
+    bootp_filename = NULL;
+    if (bootfile) {
+        bootp_filename = qemu_strdup(bootfile);
+    }
+
     inet_aton(slirp_special_ip, &special_addr);
     alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
     getouraddr();
diff --git a/slirp/tftp.c b/slirp/tftp.c
index 4ad5504..7cb095f 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -37,7 +37,7 @@ struct tftp_session {
 
 static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
 
-const char *tftp_prefix;
+char *tftp_prefix;
 
 static void tftp_session_update(struct tftp_session *spt)
 {
diff --git a/vl.c b/vl.c
index 77e4779..ae260b1 100644
--- a/vl.c
+++ b/vl.c
@@ -5308,14 +5308,14 @@ int main(int argc, char **argv, char **envp)
                 break;
 #ifdef CONFIG_SLIRP
             case QEMU_OPTION_tftp:
-		tftp_prefix = optarg;
+                legacy_tftp_prefix = optarg;
                 break;
             case QEMU_OPTION_bootp:
-                bootp_filename = optarg;
+                legacy_bootp_filename = optarg;
                 break;
 #ifndef _WIN32
             case QEMU_OPTION_smb:
-		net_slirp_smb(optarg);
+                net_slirp_smb(optarg);
                 break;
 #endif
             case QEMU_OPTION_redir:

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 04/41] Introduce get_next_param_value
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (2 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 02/41] slirp: Refactor tcp_ctl Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 03/41] Revert "User networking: Show active connections" Jan Kiszka
                   ` (37 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

In order to parse multiple instances of the same param=value pair,
introduce get_next_param_value which can pass back to string parsing
position after reading a parameter value.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 sysemu.h |    2 ++
 vl.c     |   17 +++++++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/sysemu.h b/sysemu.h
index d77de09..fafb231 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -273,6 +273,8 @@ void usb_info(Monitor *mon);
 
 int get_param_value(char *buf, int buf_size,
                     const char *tag, const char *str);
+int get_next_param_value(char *buf, int buf_size,
+                         const char *tag, const char **pstr);
 int check_params(char *buf, int buf_size,
                  const char * const *params, const char *str);
 
diff --git a/vl.c b/vl.c
index 60a00e1..77e4779 100644
--- a/vl.c
+++ b/vl.c
@@ -1812,20 +1812,23 @@ static int socket_init(void)
 }
 #endif
 
-int get_param_value(char *buf, int buf_size,
-                    const char *tag, const char *str)
+int get_next_param_value(char *buf, int buf_size,
+                         const char *tag, const char **pstr)
 {
     const char *p;
     char option[128];
 
-    p = str;
+    p = *pstr;
     for(;;) {
         p = get_opt_name(option, sizeof(option), p, '=');
         if (*p != '=')
             break;
         p++;
         if (!strcmp(tag, option)) {
-            (void)get_opt_value(buf, buf_size, p);
+            *pstr = get_opt_value(buf, buf_size, p);
+            if (**pstr == ',') {
+                (*pstr)++;
+            }
             return strlen(buf);
         } else {
             p = get_opt_value(NULL, 0, p);
@@ -1837,6 +1840,12 @@ int get_param_value(char *buf, int buf_size,
     return 0;
 }
 
+int get_param_value(char *buf, int buf_size,
+                    const char *tag, const char *str)
+{
+    return get_next_param_value(buf, buf_size, tag, &str);
+}
+
 int check_params(char *buf, int buf_size,
                  const char * const *params, const char *str)
 {

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 06/41] slirp: Rework internal configuration
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (8 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 07/41] slirp: Rework external configuration interface Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 16/41] slirp: Drop dead code Jan Kiszka
                   ` (31 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

The user mode IP stack is currently only minimally configurable /wrt to
its virtual IP addresses. This is unfortunate if some guest has a fixed
idea of which IP addresses to use.

Therefore this patch prepares the stack for fully configurable IP
addresses and masks. The user interface and default addresses remain
untouched in this step, they will be enhanced in the following patch.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/bootp.c     |   26 ++++------
 slirp/ctl.h       |    7 ---
 slirp/ip_icmp.c   |   15 ++----
 slirp/ip_input.c  |    9 ++-
 slirp/main.h      |    9 ++-
 slirp/misc.c      |    9 ++-
 slirp/misc.h      |    4 +
 slirp/slirp.c     |  142 +++++++++++++++++++++++++++++++----------------------
 slirp/slirp.h     |    1 
 slirp/socket.c    |   13 ++---
 slirp/tcp_input.c |   16 +++---
 slirp/tcp_subr.c  |   17 ++----
 slirp/udp.c       |   23 +++++----
 13 files changed, 149 insertions(+), 142 deletions(-)
 delete mode 100644 slirp/ctl.h

diff --git a/slirp/bootp.c b/slirp/bootp.c
index a2fd734..97c2811 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -27,8 +27,6 @@
 
 #define NB_ADDR 16
 
-#define START_ADDR 15
-
 #define LEASE_TIME (24 * 3600)
 
 typedef struct {
@@ -64,7 +62,7 @@ static BOOTPClient *get_new_addr(struct in_addr *paddr,
  found:
     bc = &bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+    paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i);
     return bc;
 }
 
@@ -72,12 +70,12 @@ static BOOTPClient *request_addr(const struct in_addr *paddr,
                                  const uint8_t *macaddr)
 {
     uint32_t req_addr = ntohl(paddr->s_addr);
-    uint32_t spec_addr = ntohl(special_addr.s_addr);
+    uint32_t dhcp_addr = ntohl(vdhcp_startaddr.s_addr);
     BOOTPClient *bc;
 
-    if (req_addr >= (spec_addr | START_ADDR) &&
-        req_addr < (spec_addr | (NB_ADDR + START_ADDR))) {
-        bc = &bootp_clients[(req_addr & 0xff) - START_ADDR];
+    if (req_addr >= dhcp_addr &&
+        req_addr < (dhcp_addr + NB_ADDR)) {
+        bc = &bootp_clients[req_addr - dhcp_addr];
         if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) {
             bc->allocated = 1;
             return bc;
@@ -99,7 +97,7 @@ static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
  found:
     bc = &bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+    paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i);
     return bc;
 }
 
@@ -156,7 +154,6 @@ static void bootp_reply(const struct bootp_t *bp)
     struct mbuf *m;
     struct bootp_t *rbp;
     struct sockaddr_in saddr, daddr;
-    struct in_addr dns_addr;
     const struct in_addr *preq_addr;
     int dhcp_msg_type, val;
     uint8_t *q;
@@ -218,7 +215,7 @@ static void bootp_reply(const struct bootp_t *bp)
         }
     }
 
-    saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
+    saddr.sin_addr = vhost_addr;
     saddr.sin_port = htons(BOOTP_SERVER);
 
     daddr.sin_port = htons(BOOTP_CLIENT);
@@ -262,10 +259,8 @@ static void bootp_reply(const struct bootp_t *bp)
 
         *q++ = RFC1533_NETMASK;
         *q++ = 4;
-        *q++ = 0xff;
-        *q++ = 0xff;
-        *q++ = 0xff;
-        *q++ = 0x00;
+        memcpy(q, &vnetwork_mask, 4);
+        q += 4;
 
         if (!slirp_restrict) {
             *q++ = RFC1533_GATEWAY;
@@ -275,8 +270,7 @@ static void bootp_reply(const struct bootp_t *bp)
 
             *q++ = RFC1533_DNS;
             *q++ = 4;
-            dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
-            memcpy(q, &dns_addr, 4);
+            memcpy(q, &vnameserver_addr, 4);
             q += 4;
         }
 
diff --git a/slirp/ctl.h b/slirp/ctl.h
deleted file mode 100644
index 4a8576d..0000000
--- a/slirp/ctl.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#define CTL_CMD		0
-#define CTL_EXEC	1
-#define CTL_ALIAS	2
-#define CTL_DNS		3
-
-#define CTL_SPECIAL	"10.0.2.0"
-#define CTL_LOCAL	"10.0.2.15"
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 61dcaf8..6e93ee3 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -110,7 +110,7 @@ icmp_input(struct mbuf *m, int hlen)
   case ICMP_ECHO:
     icp->icmp_type = ICMP_ECHOREPLY;
     ip->ip_len += hlen;	             /* since ip_input subtracts this */
-    if (ip->ip_dst.s_addr == alias_addr.s_addr) {
+    if (ip->ip_dst.s_addr == vhost_addr.s_addr) {
       icmp_reflect(m);
     } else {
       struct socket *so;
@@ -134,16 +134,13 @@ icmp_input(struct mbuf *m, int hlen)
 
       /* Send the packet */
       addr.sin_family = AF_INET;
-      if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+      if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
+          vnetwork_addr.s_addr) {
 	/* It's an alias */
-	switch(ntohl(so->so_faddr.s_addr) & 0xff) {
-	case CTL_DNS:
+	if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
 	  addr.sin_addr = dns_addr;
-	  break;
-	case CTL_ALIAS:
-	default:
+	} else {
 	  addr.sin_addr = loopback_addr;
-	  break;
 	}
       } else {
 	addr.sin_addr = so->so_faddr;
@@ -302,7 +299,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
   ip->ip_ttl = MAXTTL;
   ip->ip_p = IPPROTO_ICMP;
   ip->ip_dst = ip->ip_src;    /* ip adresses */
-  ip->ip_src = alias_addr;
+  ip->ip_src = vhost_addr;
 
   (void ) ip_output((struct socket *)NULL, m);
 
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index c37412e..7a3c88b 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -134,18 +134,19 @@ ip_input(struct mbuf *m)
 	}
 
     if (slirp_restrict) {
-        if (memcmp(&ip->ip_dst.s_addr, &special_addr, 3)) {
+        if ((ip->ip_dst.s_addr & vnetwork_mask.s_addr) ==
+            vnetwork_addr.s_addr) {
             if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)
                 goto bad;
         } else {
-            int host = ntohl(ip->ip_dst.s_addr) & 0xff;
             struct ex_list *ex_ptr;
 
-            if (host == 0xff)
+            if ((ip->ip_dst.s_addr & ~vnetwork_mask.s_addr) ==
+                ~vnetwork_mask.s_addr)
                 goto bad;
 
             for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
-                if (ex_ptr->ex_addr == host)
+                if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr)
                     break;
 
             if (!ex_ptr)
diff --git a/slirp/main.h b/slirp/main.h
index 89e722f..edbb9cb 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -32,9 +32,11 @@ extern char *slirp_tty;
 extern char *exec_shell;
 extern u_int curtime;
 extern fd_set *global_readfds, *global_writefds, *global_xfds;
-extern struct in_addr ctl_addr;
-extern struct in_addr special_addr;
-extern struct in_addr alias_addr;
+extern struct in_addr vnetwork_addr;
+extern struct in_addr vnetwork_mask;
+extern struct in_addr vhost_addr;
+extern struct in_addr vdhcp_startaddr;
+extern struct in_addr vnameserver_addr;
 extern struct in_addr our_addr;
 extern struct in_addr loopback_addr;
 extern struct in_addr dns_addr;
@@ -44,7 +46,6 @@ extern int towrite_max;
 extern int ppp_exit;
 extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
-extern const char *slirp_special_ip;
 extern int slirp_restrict;
 extern char *tftp_prefix;
 extern char *bootp_filename;
diff --git a/slirp/misc.c b/slirp/misc.c
index 1391d49..069d8b1 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -112,15 +112,16 @@ remque(void *a)
 /* #endif */
 
 
-int
-add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
+int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec,
+             struct in_addr addr, int port)
 {
 	struct ex_list *tmp_ptr;
 
 	/* First, check if the port is "bound" */
 	for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
-		if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
-		   return -1;
+		if (port == tmp_ptr->ex_fport &&
+		    addr.s_addr == tmp_ptr->ex_addr.s_addr)
+			return -1;
 	}
 
 	tmp_ptr = *ex_ptr;
diff --git a/slirp/misc.h b/slirp/misc.h
index ab8e3a7..29d5749 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -10,7 +10,7 @@
 
 struct ex_list {
 	int ex_pty;			/* Do we want a pty? */
-	int ex_addr;			/* The last byte of the address */
+	struct in_addr ex_addr;		/* Server address */
 	int ex_fport;                   /* Port to telnet to */
 	const char *ex_exec;            /* Command line of what to exec */
 	struct ex_list *ex_next;
@@ -74,7 +74,7 @@ void redir_x _P((u_int32_t, int, int, int));
 void getouraddr _P((void));
 void slirp_insque _P((void *, void *));
 void slirp_remque _P((void *));
-int add_exec _P((struct ex_list **, int, char *, int, int));
+int add_exec _P((struct ex_list **, int, char *, struct in_addr, int));
 int slirp_openpty _P((int *, int *));
 int fork_exec(struct socket *so, const char *ex, int do_pty);
 void snooze_hup _P((int));
diff --git a/slirp/slirp.c b/slirp/slirp.c
index b0a092c..8affd46 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -33,13 +33,16 @@ struct in_addr dns_addr;
 /* host loopback address */
 struct in_addr loopback_addr;
 
-/* address for slirp virtual addresses */
-struct in_addr special_addr;
-/* virtual address alias for host */
-struct in_addr alias_addr;
-
+/* virtual network configuration */
+struct in_addr vnetwork_addr;
+struct in_addr vnetwork_mask;
+struct in_addr vhost_addr;
+struct in_addr vdhcp_startaddr;
+struct in_addr vnameserver_addr;
+
+/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
 static const uint8_t special_ethaddr[6] = {
-    0x52, 0x54, 0x00, 0x12, 0x35, 0x00
+    0x52, 0x55, 0x00, 0x00, 0x00, 0x00
 };
 
 /* ARP cache for the guest IP addresses (XXX: allow many entries) */
@@ -48,7 +51,6 @@ static struct in_addr client_ipaddr;
 
 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
 
-const char *slirp_special_ip = CTL_SPECIAL;
 int slirp_restrict;
 static int do_slowtimo;
 int link_up;
@@ -176,12 +178,12 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
 {
     //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
 
+    struct in_addr special_addr = { .s_addr = htonl(0x0a000200) };
 #ifdef _WIN32
-    {
-        WSADATA Data;
-        WSAStartup(MAKEWORD(2,0), &Data);
-	atexit(slirp_cleanup);
-    }
+    WSADATA Data;
+
+    WSAStartup(MAKEWORD(2,0), &Data);
+    atexit(slirp_cleanup);
 #endif
 
     link_up = 1;
@@ -201,9 +203,9 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
         fprintf (stderr, "Warning: No DNS servers found\n");
     }
 
-    if (special_ip)
-        slirp_special_ip = special_ip;
-
+    if (special_ip) {
+        inet_aton(special_ip, &special_addr);
+    }
     qemu_free(tftp_prefix);
     tftp_prefix = NULL;
     if (tftp_path) {
@@ -215,8 +217,11 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
         bootp_filename = qemu_strdup(bootfile);
     }
 
-    inet_aton(slirp_special_ip, &special_addr);
-    alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
+    vnetwork_addr = special_addr;
+    vnetwork_mask.s_addr = htonl(0xffffff00);
+    vhost_addr.s_addr = special_addr.s_addr | htonl(2);
+    vdhcp_startaddr.s_addr = special_addr.s_addr | htonl(15);
+    vnameserver_addr.s_addr = special_addr.s_addr | htonl(3);
     getouraddr();
     register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
 }
@@ -601,10 +606,10 @@ struct arphdr
 	  *	 Ethernet looks like this : This bit is variable sized however...
 	  */
 	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/
-	unsigned char		ar_sip[4];		/* sender IP address		*/
+	uint32_t		ar_sip;			/* sender IP address		*/
 	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/
-	unsigned char		ar_tip[4];		/* target IP address		*/
-};
+	uint32_t		ar_tip	;		/* target IP address		*/
+} __attribute__((packed));
 
 static void arp_input(const uint8_t *pkt, int pkt_len)
 {
@@ -619,11 +624,12 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
     ar_op = ntohs(ah->ar_op);
     switch(ar_op) {
     case ARPOP_REQUEST:
-        if (!memcmp(ah->ar_tip, &special_addr, 3)) {
-            if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
+        if ((ah->ar_tip & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
+            if (ah->ar_tip == vnameserver_addr.s_addr ||
+                ah->ar_tip == vhost_addr.s_addr)
                 goto arp_ok;
             for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
-                if (ex_ptr->ex_addr == ah->ar_tip[3])
+                if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
                     goto arp_ok;
             }
             return;
@@ -633,8 +639,8 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
 
             /* ARP request for alias/dns mac address */
             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
-            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
-            reh->h_source[5] = ah->ar_tip[3];
+            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
+            memcpy(&reh->h_source[2], &ah->ar_tip, 4);
             reh->h_proto = htons(ETH_P_ARP);
 
             rah->ar_hrd = htons(1);
@@ -643,16 +649,16 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
             rah->ar_pln = 4;
             rah->ar_op = htons(ARPOP_REPLY);
             memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
-            memcpy(rah->ar_sip, ah->ar_tip, 4);
+            rah->ar_sip = ah->ar_tip;
             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
-            memcpy(rah->ar_tip, ah->ar_sip, 4);
+            rah->ar_tip = ah->ar_sip;
             slirp_output(arp_reply, sizeof(arp_reply));
         }
         break;
     case ARPOP_REPLY:
         /* reply to request of client mac address ? */
         if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
-            !memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) {
+            ah->ar_sip == client_ipaddr.s_addr) {
             memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
         }
         break;
@@ -716,8 +722,8 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
            in place of sending the packet and we hope that the sender
            will retry sending its packet. */
         memset(reh->h_dest, 0xff, ETH_ALEN);
-        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
-        reh->h_source[5] = CTL_ALIAS;
+        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
+        memcpy(&reh->h_source[2], &vhost_addr, 4);
         reh->h_proto = htons(ETH_P_ARP);
         rah->ar_hrd = htons(1);
         rah->ar_pro = htons(ETH_P_IP);
@@ -725,21 +731,21 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
         rah->ar_pln = 4;
         rah->ar_op = htons(ARPOP_REQUEST);
         /* source hw addr */
-        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
-        rah->ar_sha[5] = CTL_ALIAS;
+        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
+        memcpy(&rah->ar_sha[2], &vhost_addr, 4);
         /* source IP */
-        memcpy(rah->ar_sip, &alias_addr, 4);
+        rah->ar_sip = vhost_addr.s_addr;
         /* target hw addr (none) */
         memset(rah->ar_tha, 0, ETH_ALEN);
         /* target IP */
-        memcpy(rah->ar_tip, &iph->ip_dst, 4);
+        rah->ar_tip = iph->ip_dst.s_addr;
         client_ipaddr = iph->ip_dst;
         slirp_output(arp_req, sizeof(arp_req));
     } else {
         memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
-        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
+        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
         /* XXX: not correct */
-        eh->h_source[5] = CTL_ALIAS;
+        memcpy(&eh->h_source[2], &vhost_addr, 4);
         eh->h_proto = htons(ETH_P_IP);
         memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
         slirp_output(buf, ip_data_len + ETH_HLEN);
@@ -772,6 +778,9 @@ int slirp_redir_rm(int is_udp, int host_port)
 int slirp_redir(int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port)
 {
+    if (!guest_addr.s_addr) {
+        guest_addr = vdhcp_startaddr;
+    }
     if (is_udp) {
         if (!udp_listen(htons(host_port), guest_addr.s_addr,
                         htons(guest_port), 0))
@@ -787,8 +796,17 @@ int slirp_redir(int is_udp, int host_port,
 int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
                   int guest_port)
 {
-    return add_exec(&exec_list, do_pty, (char *)args,
-                    addr_low_byte, htons(guest_port));
+    struct in_addr guest_addr = {
+        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
+    };
+
+    if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
+        guest_addr.s_addr == vhost_addr.s_addr ||
+        guest_addr.s_addr == vnameserver_addr.s_addr) {
+        return -1;
+    }
+    return add_exec(&exec_list, do_pty, (char *)args, guest_addr,
+                    htons(guest_port));
 }
 
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
@@ -801,31 +819,32 @@ ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
 	return send(so->s, buf, len, flags);
 }
 
-static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
+static struct socket *
+slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
 {
-	struct socket *so;
-
-	for (so = tcb.so_next; so != &tcb; so = so->so_next) {
-		if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
-				special_addr.s_addr
-				&& (ntohl(so->so_faddr.s_addr) & 0xff) ==
-				addr_low_byte
-				&& htons(so->so_fport) == guest_port)
-			return so;
-	}
+    struct socket *so;
 
-	return NULL;
+    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+        if (so->so_faddr.s_addr == guest_addr.s_addr &&
+            htons(so->so_fport) == guest_port) {
+            return so;
+        }
+    }
+    return NULL;
 }
 
 size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
 {
+    struct in_addr guest_addr = {
+        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
+    };
 	struct iovec iov[2];
 	struct socket *so;
 
     if (!link_up)
         return 0;
 
-	so = slirp_find_ctl_socket(addr_low_byte, guest_port);
+	so = slirp_find_ctl_socket(guest_addr, guest_port);
 
 	if (!so || so->so_state & SS_NOFDREF)
 		return 0;
@@ -840,8 +859,11 @@ void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
         int size)
 {
     int ret;
-    struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
-   
+    struct in_addr guest_addr = {
+        .s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
+    };
+    struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
+
     if (!so)
         return;
 
@@ -1055,15 +1077,17 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         if (ret < 0)
             return ret;
 
-        if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr)
+        if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) !=
+            vnetwork_addr.s_addr) {
             return -EINVAL;
-
-        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+        }
+        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_pty == 3 &&
-                    (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr &&
-                    so->so_fport == ex_ptr->ex_fport)
+                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
+                so->so_fport == ex_ptr->ex_fport) {
                 break;
-
+            }
+        }
         if (!ex_ptr)
             return -EINVAL;
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 8309fe0..101d094 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -214,7 +214,6 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 #include "if.h"
 #include "main.h"
 #include "misc.h"
-#include "ctl.h"
 #ifdef USE_PPP
 #include "ppp/pppd.h"
 #include "ppp/ppp.h"
diff --git a/slirp/socket.c b/slirp/socket.c
index 82d026c..9f13f03 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -555,16 +555,13 @@ sosendto(struct socket *so, struct mbuf *m)
 	DEBUG_ARG("m = %lx", (long)m);
 
         addr.sin_family = AF_INET;
-	if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+	if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
+	    vnetwork_addr.s_addr) {
 	  /* It's an alias */
-	  switch(ntohl(so->so_faddr.s_addr) & 0xff) {
-	  case CTL_DNS:
+	  if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
 	    addr.sin_addr = dns_addr;
-	    break;
-	  case CTL_ALIAS:
-	  default:
+	  } else {
 	    addr.sin_addr = loopback_addr;
-	    break;
 	  }
 	} else
 	  addr.sin_addr = so->so_faddr;
@@ -652,7 +649,7 @@ solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
 	getsockname(s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
 	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = alias_addr;
+	   so->so_faddr = vhost_addr;
 	else
 	   so->so_faddr = addr.sin_addr;
 
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index effedfc..ab0840d 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -359,11 +359,12 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 
     if (slirp_restrict) {
-        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_fport == ti->ti_dport &&
-                    (ntohl(ti->ti_dst.s_addr) & 0xff) == ex_ptr->ex_addr)
+                ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
                 break;
-
+            }
+        }
         if (!ex_ptr)
             goto drop;
     }
@@ -639,9 +640,10 @@ findso:
 	   * If this is destined for the control address, then flag to
 	   * tcp_ctl once connected, otherwise connect
 	   */
-	  if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) {
-	    int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;
-	    if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) {
+	  if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
+	      vnetwork_addr.s_addr) {
+	    if (so->so_faddr.s_addr != vhost_addr.s_addr &&
+		so->so_faddr.s_addr != vnameserver_addr.s_addr) {
 #if 0
 	      if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) {
 		/* Command or exec adress */
@@ -652,7 +654,7 @@ findso:
 		/* May be an add exec */
 		for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
 		  if(ex_ptr->ex_fport == so->so_fport &&
-		     lastbyte == ex_ptr->ex_addr) {
+		     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
 		    so->so_state |= SS_CTL;
 		    break;
 		  }
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 447a27c..858d1ae 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -384,16 +384,12 @@ int tcp_fconnect(struct socket *so)
     setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
 
     addr.sin_family = AF_INET;
-    if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
+    if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
       /* It's an alias */
-      switch(ntohl(so->so_faddr.s_addr) & 0xff) {
-      case CTL_DNS:
+      if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
 	addr.sin_addr = dns_addr;
-	break;
-      case CTL_ALIAS:
-      default:
+      } else {
 	addr.sin_addr = loopback_addr;
-	break;
       }
     } else
       addr.sin_addr = so->so_faddr;
@@ -478,7 +474,7 @@ tcp_connect(struct socket *inso)
 	so->so_faddr = addr.sin_addr;
 	/* Translate connections from localhost to the real hostname */
 	if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = alias_addr;
+	   so->so_faddr = vhost_addr;
 
 	/* Close the accept() socket, set right state */
 	if (inso->so_state & SS_FACCEPTONCE) {
@@ -1230,7 +1226,6 @@ do_prompt:
  */
 int tcp_ctl(struct socket *so)
 {
-    int command = (ntohl(so->so_faddr.s_addr) & 0xff);
     struct sbuf *sb = &so->so_snd;
     struct ex_list *ex_ptr;
     int do_pty;
@@ -1238,11 +1233,11 @@ int tcp_ctl(struct socket *so)
     DEBUG_CALL("tcp_ctl");
     DEBUG_ARG("so = %lx", (long )so);
 
-    if (command != CTL_ALIAS) {
+    if (so->so_faddr.s_addr != vhost_addr.s_addr) {
         /* Check if it's pty_exec */
         for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_fport == so->so_fport &&
-                command == ex_ptr->ex_addr) {
+                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
                 if (ex_ptr->ex_pty == 3) {
                     so->s = -1;
                     so->extra = (void *)ex_ptr->ex_exec;
diff --git a/slirp/udp.c b/slirp/udp.c
index ba9d5c9..ff3a39f 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -312,12 +312,14 @@ int udp_output(struct socket *so, struct mbuf *m,
     struct sockaddr_in saddr, daddr;
 
     saddr = *addr;
-    if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
-        if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
-            saddr.sin_addr.s_addr = alias_addr.s_addr;
-        else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
-                 (ntohl(so->so_faddr.s_addr) & 0xff) != CTL_ALIAS)
-            saddr.sin_addr.s_addr = so->so_faddr.s_addr;
+    if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
+        if ((so->so_faddr.s_addr & ~vnetwork_mask.s_addr) ==
+            ~vnetwork_mask.s_addr) {
+            saddr.sin_addr = vhost_addr;
+        } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
+                   so->so_faddr.s_addr != vhost_addr.s_addr) {
+            saddr.sin_addr = so->so_faddr;
+        }
     }
     daddr.sin_addr = so->so_laddr;
     daddr.sin_port = so->so_lport;
@@ -652,11 +654,12 @@ udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
 
 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
-	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = alias_addr;
-	else
+	if (addr.sin_addr.s_addr == 0 ||
+	    addr.sin_addr.s_addr == loopback_addr.s_addr) {
+	   so->so_faddr = vhost_addr;
+	} else {
 	   so->so_faddr = addr.sin_addr;
-
+	}
 	so->so_lport = lport;
 	so->so_laddr.s_addr = laddr;
 	if (flags != SS_FACCEPTONCE)

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 11/41] slirp: Prepare for persistent socket state flags
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (17 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 20/41] slirp: tftp: Cleanup tftp_prefix check Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 17/41] slirp: Drop statistic code Jan Kiszka
                   ` (22 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

This prepares for adding flags to socket.so_state that must not be
removed during the lifetime of a socket.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/slirp.c     |    9 ++++++---
 slirp/socket.c    |   22 ++++++++++++++--------
 slirp/socket.h    |    2 ++
 slirp/tcp_input.c |    3 ++-
 slirp/udp.c       |    3 ++-
 5 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/slirp/slirp.c b/slirp/slirp.c
index ab0a854..08c10f2 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -495,7 +495,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
 				continue;
 
 			      /* else failed */
-			      so->so_state = SS_NOFDREF;
+			      so->so_state &= SS_PERSISTENT_MASK;
+			      so->so_state |= SS_NOFDREF;
 			    }
 			    /* else so->so_state &= ~SS_ISFCONNECTING; */
 
@@ -529,7 +530,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
 			      continue; /* Still connecting, continue */
 
 			    /* else failed */
-			    so->so_state = SS_NOFDREF;
+			    so->so_state &= SS_PERSISTENT_MASK;
+			    so->so_state |= SS_NOFDREF;
 
 			    /* tcp_input will take care of it */
 			  } else {
@@ -540,7 +542,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
 				  errno == EINPROGRESS || errno == ENOTCONN)
 				continue;
 			      /* else failed */
-			      so->so_state = SS_NOFDREF;
+			      so->so_state &= SS_PERSISTENT_MASK;
+			      so->so_state |= SS_NOFDREF;
 			    } else
 			      so->so_state &= ~SS_ISFCONNECTING;
 
diff --git a/slirp/socket.c b/slirp/socket.c
index 936021e..6b3da0a 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -581,7 +581,8 @@ sosendto(struct socket *so, struct mbuf *m)
 	 */
 	if (so->so_expire)
 		so->so_expire = curtime + SO_EXPIRE;
-	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
+	so->so_state &= SS_PERSISTENT_MASK;
+	so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */
 	return 0;
 }
 
@@ -620,7 +621,8 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags
 	if (flags & SS_FACCEPTONCE)
 	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
 
-	so->so_state = (SS_FACCEPTCONN|flags);
+	so->so_state &= SS_PERSISTENT_MASK;
+	so->so_state |= (SS_FACCEPTCONN | flags);
 	so->so_lport = lport; /* Kept in network format */
 	so->so_laddr.s_addr = laddr; /* Ditto */
 
@@ -715,10 +717,12 @@ sofcantrcvmore(struct socket *so)
 		}
 	}
 	so->so_state &= ~(SS_ISFCONNECTING);
-	if (so->so_state & SS_FCANTSENDMORE)
-	   so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */
-	else
+	if (so->so_state & SS_FCANTSENDMORE) {
+	   so->so_state &= SS_PERSISTENT_MASK;
+	   so->so_state |= SS_NOFDREF; /* Don't select it */
+	} else {
 	   so->so_state |= SS_FCANTRCVMORE;
+	}
 }
 
 static void
@@ -734,10 +738,12 @@ sofcantsendmore(struct socket *so)
             }
 	}
 	so->so_state &= ~(SS_ISFCONNECTING);
-	if (so->so_state & SS_FCANTRCVMORE)
-	   so->so_state = SS_NOFDREF; /* as above */
-	else
+	if (so->so_state & SS_FCANTRCVMORE) {
+	   so->so_state &= SS_PERSISTENT_MASK;
+	   so->so_state |= SS_NOFDREF; /* as above */
+	} else {
 	   so->so_state |= SS_FCANTSENDMORE;
+	}
 }
 
 void
diff --git a/slirp/socket.h b/slirp/socket.h
index ac36aaa..2cf476c 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -71,6 +71,8 @@ struct socket {
 #define SS_FACCEPTCONN		0x100	/* Socket is accepting connections from a host on the internet */
 #define SS_FACCEPTONCE		0x200	/* If set, the SS_FACCEPTCONN socket will die after one accept */
 
+#define SS_PERSISTENT_MASK	0xf000	/* Unremovable state bits */
+
 extern struct socket tcb;
 
 struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index ab0840d..8789303 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -1038,7 +1038,8 @@ trimthenstep6:
 		    soisfconnected(so);
 		    so->so_state &= ~SS_CTL;   /* success XXX */
 		  } else if (ret == 2) {
-		    so->so_state = SS_NOFDREF; /* CTL_CMD */
+		    so->so_state &= SS_PERSISTENT_MASK;
+		    so->so_state |= SS_NOFDREF; /* CTL_CMD */
 		  } else {
 		    needoutput = 1;
 		    tp->t_state = TCPS_FIN_WAIT_1;
diff --git a/slirp/udp.c b/slirp/udp.c
index d675ad3..3722845 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -666,7 +666,8 @@ udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
 	if (flags != SS_FACCEPTONCE)
 	   so->so_expire = 0;
 
-	so->so_state = SS_ISFCONNECTED;
+	so->so_state &= SS_PERSISTENT_MASK;
+	so->so_state |= SS_ISFCONNECTED;
 
 	return so;
 }

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 12/41] slirp: Explicitely mark host-forwarding sockets
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (10 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 16/41] slirp: Drop dead code Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 19/41] slirp: Drop unused icmp_var.h Jan Kiszka
                   ` (29 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Mark sockets that describe host forwardings. This is required for their
(and only their) proper deletion and for pretty-printing.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/slirp.c  |    4 ++--
 slirp/socket.h |    1 +
 slirp/udp.c    |    2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/slirp/slirp.c b/slirp/slirp.c
index 08c10f2..ad35c1f 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -793,11 +793,11 @@ int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
     }
     if (is_udp) {
         if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
-                        htons(guest_port), 0))
+                        htons(guest_port), SS_HOSTFWD))
             return -1;
     } else {
         if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
-                        htons(guest_port), 0))
+                        htons(guest_port), SS_HOSTFWD))
             return -1;
     }
     return 0;
diff --git a/slirp/socket.h b/slirp/socket.h
index 2cf476c..979b191 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -72,6 +72,7 @@ struct socket {
 #define SS_FACCEPTONCE		0x200	/* If set, the SS_FACCEPTCONN socket will die after one accept */
 
 #define SS_PERSISTENT_MASK	0xf000	/* Unremovable state bits */
+#define SS_HOSTFWD		0x1000	/* Socket describes host->guest forwarding */
 
 extern struct socket tcb;
 
diff --git a/slirp/udp.c b/slirp/udp.c
index 3722845..60fe754 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -667,7 +667,7 @@ udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
 	   so->so_expire = 0;
 
 	so->so_state &= SS_PERSISTENT_MASK;
-	so->so_state |= SS_ISFCONNECTED;
+	so->so_state |= SS_ISFCONNECTED | flags;
 
 	return so;
 }

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 13/41] slirp: Do not allow to remove non-hostfwd sockets
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (14 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 18/41] slirp: Cleanup and basic reanimation of debug code Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 14/41] slirp: Mark sockets of incoming TCP connections Jan Kiszka
                   ` (25 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Prevent that the users accidentally shoots down dynamic sockets. This
allows to remove looping for removals as there can now only be one
match.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c         |    8 ++++----
 slirp/slirp.c |   14 +++++---------
 2 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/net.c b/net.c
index 6753993..71aaa1e 100644
--- a/net.c
+++ b/net.c
@@ -880,7 +880,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
     char buf[256] = "";
     const char *p = src_str;
     int is_udp = 0;
-    int n;
+    int err;
 
     if (!slirp_inited) {
         monitor_printf(mon, "user mode network stack not in use\n");
@@ -909,10 +909,10 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
 
     host_port = atoi(p);
 
-    n = slirp_remove_hostfwd(is_udp, host_addr, host_port);
+    err = slirp_remove_hostfwd(is_udp, host_addr, host_port);
 
-    monitor_printf(mon, "removed %d host forwarding rules for %s\n", n,
-                   src_str);
+    monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
+                   err ? "removed" : "not found");
     return;
 
  fail_syntax:
diff --git a/slirp/slirp.c b/slirp/slirp.c
index ad35c1f..35de4e3 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -757,9 +757,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
     }
 }
 
-/* Unlistens a redirection
- *
- * Return value: number of redirs removed */
+/* Drop host forwarding rule, return 0 if found. */
 int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
 {
     struct socket *so;
@@ -767,22 +765,20 @@ int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
     struct sockaddr_in addr;
     int port = htons(host_port);
     socklen_t addr_len;
-    int n = 0;
 
- loop_again:
     for (so = head->so_next; so != head; so = so->so_next) {
         addr_len = sizeof(addr);
-        if (getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
+        if ((so->so_state & SS_HOSTFWD) &&
+            getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
             addr.sin_addr.s_addr == host_addr.s_addr &&
             addr.sin_port == port) {
             close(so->s);
             sofree(so);
-            n++;
-            goto loop_again;
+            return 0;
         }
     }
 
-    return n;
+    return -1;
 }
 
 int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 15/41] slirp: Add info usernet for dumping connection states
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (12 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 19/41] slirp: Drop unused icmp_var.h Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 18/41] slirp: Cleanup and basic reanimation of debug code Jan Kiszka
                   ` (27 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Break out sockstats from the slirp statistics and present them under the
new info category "usernet". This patch also improves the current output
/wrt proper reporting connection source and destination.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c          |    2 +
 net.c              |    6 ++++
 net.h              |    2 +
 qemu-monitor.hx    |    2 +
 slirp/debug.c      |   42 -------------------------
 slirp/libslirp.h   |    4 ++
 slirp/misc.c       |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/tcp.h        |    2 -
 slirp/tcp_output.c |   11 -------
 9 files changed, 102 insertions(+), 55 deletions(-)

diff --git a/monitor.c b/monitor.c
index 6b45f6c..47fc9de 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1735,6 +1735,8 @@ static const mon_cmd_t info_cmds[] = {
 #if defined(CONFIG_SLIRP)
     { "slirp", "", do_info_slirp,
       "", "show SLIRP statistics", },
+    { "usernet", "", do_info_usernet,
+      "", "show user network stack connection states", },
 #endif
     { "migrate", "", do_info_migrate, "", "show migration status" },
     { "balloon", "", do_info_balloon,
diff --git a/net.c b/net.c
index 71aaa1e..8bd3b25 100644
--- a/net.c
+++ b/net.c
@@ -1198,6 +1198,12 @@ static void slirp_guestfwd(Monitor *mon, const char *config_str,
     config_error(mon, "invalid guest forwarding rule '%s'\n", config_str);
 }
 
+void do_info_usernet(Monitor *mon)
+{
+    monitor_printf(mon, "VLAN %d (%s):\n", slirp_vc->vlan->id, slirp_vc->name);
+    slirp_connection_info(mon);
+}
+
 #endif /* CONFIG_SLIRP */
 
 #if !defined(_WIN32)
diff --git a/net.h b/net.h
index 6e91828..5a608e0 100644
--- a/net.h
+++ b/net.h
@@ -81,6 +81,8 @@ void qemu_handler_true(void *opaque);
 void do_info_network(Monitor *mon);
 int do_set_link(Monitor *mon, const char *name, const char *up_or_down);
 
+void do_info_usernet(Monitor *mon);
+
 /* NIC info */
 
 #define MAX_NICS 8
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 34f6992..359bdc6 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -87,6 +87,8 @@ show the current VM UUID
 show CPU statistics
 @item info slirp
 show SLIRP statistics (if available)
+@item info usernet
+show user network stack connection states
 @item info migrate
 show migration status
 @item info balloon
diff --git a/slirp/debug.c b/slirp/debug.c
index bfef580..ac856ca 100644
--- a/slirp/debug.c
+++ b/slirp/debug.c
@@ -291,47 +291,6 @@ mbufstats(void)
 	lprint("  %6d mbufs on used list\r\n",  i);
         lprint("  %6d mbufs queued as packets\r\n\r\n", if_queued);
 }
-
-static void
-sockstats(void)
-{
-	char buff[256];
-	int n;
-	struct socket *so;
-
-        lprint(" \r\n");
-
-	lprint(
-	   "Proto[state]     Sock     Local Address, Port  Remote Address, Port RecvQ SendQ\r\n");
-
-	for (so = tcb.so_next; so != &tcb; so = so->so_next) {
-
-		n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
-		while (n < 17)
-		   buff[n++] = ' ';
-		buff[17] = 0;
-		lprint("%s %3d   %15s %5d ",
-				buff, so->s,
-				inet_ntoa(so->so_laddr), ntohs(so->so_lport));
-		lprint("%15s %5d %5d %5d\r\n",
-				inet_ntoa(so->so_faddr), ntohs(so->so_fport),
-				so->so_rcv.sb_cc, so->so_snd.sb_cc);
-	}
-
-	for (so = udb.so_next; so != &udb; so = so->so_next) {
-
-		n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
-		while (n < 17)
-		   buff[n++] = ' ';
-		buff[17] = 0;
-		lprint("%s %3d  %15s %5d  ",
-				buff, so->s,
-				inet_ntoa(so->so_laddr), ntohs(so->so_lport));
-		lprint("%15s %5d %5d %5d\r\n",
-				inet_ntoa(so->so_faddr), ntohs(so->so_fport),
-				so->so_rcv.sb_cc, so->so_snd.sb_cc);
-	}
-}
 #endif
 
 #ifndef CONFIG_QEMU
@@ -386,7 +345,6 @@ slirp_stats(void)
     udpstats();
     icmpstats();
     mbufstats();
-    sockstats();
 #else
     lprint("SLIRP statistics code not compiled.\n");
 #endif
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 9be4425..5c7a8e9 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+#include <qemu-common.h>
+
 void slirp_init(int restricted, struct in_addr vnetwork,
                 struct in_addr vnetmask, struct in_addr vhost,
                 const char *vhostname, const char *tftp_path,
@@ -29,6 +31,8 @@ int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
                    int guest_port);
 
 void slirp_stats(void);
+void slirp_connection_info(Monitor *mon);
+
 void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
                        const uint8_t *buf, int size);
 size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port);
diff --git a/slirp/misc.c b/slirp/misc.c
index 069d8b1..8d03f79 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -6,6 +6,9 @@
  */
 
 #include <slirp.h>
+#include <libslirp.h>
+
+#include "monitor.h"
 
 u_int curtime, time_fasttimo, last_slowtimo;
 
@@ -906,3 +909,86 @@ rsh_exec(so,ns, user, host, args)
 	}
 }
 #endif
+
+void slirp_connection_info(Monitor *mon)
+{
+    const char * const tcpstates[] = {
+        [TCPS_CLOSED]       = "CLOSED",
+        [TCPS_LISTEN]       = "LISTEN",
+        [TCPS_SYN_SENT]     = "SYN_SENT",
+        [TCPS_SYN_RECEIVED] = "SYN_RCVD",
+        [TCPS_ESTABLISHED]  = "ESTABLISHED",
+        [TCPS_CLOSE_WAIT]   = "CLOSE_WAIT",
+        [TCPS_FIN_WAIT_1]   = "FIN_WAIT_1",
+        [TCPS_CLOSING]      = "CLOSING",
+        [TCPS_LAST_ACK]     = "LAST_ACK",
+        [TCPS_FIN_WAIT_2]   = "FIN_WAIT_2",
+        [TCPS_TIME_WAIT]    = "TIME_WAIT",
+    };
+    struct in_addr dst_addr;
+    struct sockaddr_in src;
+    socklen_t src_len;
+    uint16_t dst_port;
+    struct socket *so;
+    const char *state;
+    char buf[20];
+    int n;
+
+    monitor_printf(mon, "  Protocol[State]    FD  Source Address  Port   "
+                        "Dest. Address  Port RecvQ SendQ\n");
+
+    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+        if (so->so_state & SS_HOSTFWD) {
+            state = "HOST_FORWARD";
+        } else if (so->so_tcpcb) {
+            state = tcpstates[so->so_tcpcb->t_state];
+        } else {
+            state = "NONE";
+        }
+        if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) {
+            src_len = sizeof(src);
+            getsockname(so->s, (struct sockaddr *)&src, &src_len);
+            dst_addr = so->so_laddr;
+            dst_port = so->so_lport;
+        } else {
+            src.sin_addr = so->so_laddr;
+            src.sin_port = so->so_lport;
+            dst_addr = so->so_faddr;
+            dst_port = so->so_fport;
+        }
+        n = snprintf(buf, sizeof(buf), "  TCP[%s]", state);
+        memset(&buf[n], ' ', 19 - n);
+        buf[19] = 0;
+        monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s,
+                       src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
+                       ntohs(src.sin_port));
+        monitor_printf(mon, "%15s %5d %5d %5d\n",
+                       inet_ntoa(dst_addr), ntohs(dst_port),
+                       so->so_rcv.sb_cc, so->so_snd.sb_cc);
+    }
+
+    for (so = udb.so_next; so != &udb; so = so->so_next) {
+        if (so->so_state & SS_HOSTFWD) {
+            n = snprintf(buf, sizeof(buf), "  UDP[HOST_FORWARD]");
+            src_len = sizeof(src);
+            getsockname(so->s, (struct sockaddr *)&src, &src_len);
+            dst_addr = so->so_laddr;
+            dst_port = so->so_lport;
+        } else {
+            n = snprintf(buf, sizeof(buf), "  UDP[%d sec]",
+                         (so->so_expire - curtime) / 1000);
+            src.sin_addr = so->so_laddr;
+            src.sin_port = so->so_lport;
+            dst_addr = so->so_faddr;
+            dst_port = so->so_fport;
+        }
+        memset(&buf[n], ' ', 19 - n);
+        buf[19] = 0;
+        monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s,
+                       src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
+                       ntohs(src.sin_port));
+        monitor_printf(mon, "%15s %5d %5d %5d\n",
+                       inet_ntoa(dst_addr), ntohs(dst_port),
+                       so->so_rcv.sb_cc, so->so_snd.sb_cc);
+    }
+}
diff --git a/slirp/tcp.h b/slirp/tcp.h
index 4057032..3399857 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -166,6 +166,4 @@ struct tcphdr {
 
 extern tcp_seq tcp_iss;                /* tcp initial send seq # */
 
-extern const char * const tcpstates[];
-
 #endif
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 9ed50f5..5daf58e 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -40,17 +40,6 @@
 
 #include <slirp.h>
 
-/*
- * Since this is only used in "stats socket", we give meaning
- * names instead of the REAL names
- */
-const char * const tcpstates[] = {
-/*	"CLOSED",       "LISTEN",       "SYN_SENT",     "SYN_RCVD", */
-	"REDIRECT",	"LISTEN",	"SYN_SENT",     "SYN_RCVD",
-	"ESTABLISHED",  "CLOSE_WAIT",   "FIN_WAIT_1",   "CLOSING",
-	"LAST_ACK",     "FIN_WAIT_2",   "TIME_WAIT",
-};
-
 static const u_char  tcp_outflags[TCP_NSTATES] = {
 	TH_RST|TH_ACK, 0,      TH_SYN,        TH_SYN|TH_ACK,
 	TH_ACK,        TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 17/41] slirp: Drop statistic code
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (18 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 11/41] slirp: Prepare for persistent socket state flags Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 23/41] slirp: tftp: Rework filename handling Jan Kiszka
                   ` (21 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

As agreed on the mailing list, there is no interest in keeping the
usually disabled slirp statistics in the tree. So this patch removes
them.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c          |    2 -
 net.c              |    5 --
 qemu-monitor.hx    |    2 -
 slirp/debug.c      |  154 ----------------------------------------------------
 slirp/icmp_var.h   |   18 ------
 slirp/if.h         |   20 -------
 slirp/ip.h         |   37 ------------
 slirp/ip_icmp.c    |   14 -----
 slirp/ip_input.c   |   21 -------
 slirp/ip_output.c  |    7 --
 slirp/libslirp.h   |    1 
 slirp/mbuf.c       |    5 --
 slirp/mbuf.h       |   12 ----
 slirp/slirp.h      |    9 ---
 slirp/tcp_input.c  |   49 +----------------
 slirp/tcp_output.c |   23 --------
 slirp/tcp_subr.c   |    7 --
 slirp/tcp_timer.c  |   11 ----
 slirp/tcp_var.h    |   63 ---------------------
 slirp/udp.c        |   11 ----
 slirp/udp.h        |   20 -------
 21 files changed, 6 insertions(+), 485 deletions(-)

diff --git a/monitor.c b/monitor.c
index 47fc9de..7fdd3a0 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1733,8 +1733,6 @@ static const mon_cmd_t info_cmds[] = {
       "", "show CPU statistics", },
 #endif
 #if defined(CONFIG_SLIRP)
-    { "slirp", "", do_info_slirp,
-      "", "show SLIRP statistics", },
     { "usernet", "", do_info_usernet,
       "", "show user network stack connection states", },
 #endif
diff --git a/net.c b/net.c
index 8bd3b25..99726cd 100644
--- a/net.c
+++ b/net.c
@@ -1112,11 +1112,6 @@ void net_slirp_smb(const char *exported_dir)
 
 #endif /* !defined(_WIN32) */
 
-void do_info_slirp(Monitor *mon)
-{
-    slirp_stats();
-}
-
 struct GuestFwd {
     CharDriverState *hd;
     struct in_addr server;
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index 359bdc6..e320f9f 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -85,8 +85,6 @@ show the current VM name
 show the current VM UUID
 @item info cpustats
 show CPU statistics
-@item info slirp
-show SLIRP statistics (if available)
 @item info usernet
 show user network stack connection states
 @item info migrate
diff --git a/slirp/debug.c b/slirp/debug.c
index 6462c88..ad02df7 100644
--- a/slirp/debug.c
+++ b/slirp/debug.c
@@ -10,157 +10,3 @@
 
 FILE *dfd = NULL;
 int slirp_debug = 0;
-
-#ifdef LOG_ENABLED
-static void
-ipstats(void)
-{
-	lprint(" \r\n");
-
-	lprint("IP stats:\r\n");
-	lprint("  %6d total packets received (%d were unaligned)\r\n",
-			ipstat.ips_total, ipstat.ips_unaligned);
-	lprint("  %6d with incorrect version\r\n", ipstat.ips_badvers);
-	lprint("  %6d with bad header checksum\r\n", ipstat.ips_badsum);
-	lprint("  %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort);
-	lprint("  %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall);
-	lprint("  %6d with bad header length\r\n", ipstat.ips_badhlen);
-	lprint("  %6d with bad packet length\r\n", ipstat.ips_badlen);
-	lprint("  %6d fragments received\r\n", ipstat.ips_fragments);
-	lprint("  %6d fragments dropped\r\n", ipstat.ips_fragdropped);
-	lprint("  %6d fragments timed out\r\n", ipstat.ips_fragtimeout);
-	lprint("  %6d packets reassembled ok\r\n", ipstat.ips_reassembled);
-	lprint("  %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented);
-	lprint("  %6d total outgoing fragments\r\n", ipstat.ips_ofragments);
-	lprint("  %6d with bad protocol field\r\n", ipstat.ips_noproto);
-	lprint("  %6d total packets delivered\r\n", ipstat.ips_delivered);
-}
-
-static void
-tcpstats(void)
-{
-	lprint(" \r\n");
-
-	lprint("TCP stats:\r\n");
-
-	lprint("  %6d packets sent\r\n", tcpstat.tcps_sndtotal);
-	lprint("          %6d data packets (%d bytes)\r\n",
-			tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
-	lprint("          %6d data packets retransmitted (%d bytes)\r\n",
-			tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte);
-	lprint("          %6d ack-only packets (%d delayed)\r\n",
-			tcpstat.tcps_sndacks, tcpstat.tcps_delack);
-	lprint("          %6d URG only packets\r\n", tcpstat.tcps_sndurg);
-	lprint("          %6d window probe packets\r\n", tcpstat.tcps_sndprobe);
-	lprint("          %6d window update packets\r\n", tcpstat.tcps_sndwinup);
-	lprint("          %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl);
-	lprint("          %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin);
-
-	lprint("  %6d packets received\r\n", tcpstat.tcps_rcvtotal);
-	lprint("          %6d acks (for %d bytes)\r\n",
-			tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
-	lprint("          %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
-	lprint("          %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch);
-	lprint("          %6d packets received in sequence (%d bytes)\r\n",
-			tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
-        lprint("          %6d completely duplicate packets (%d bytes)\r\n",
-			tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
-
-	lprint("          %6d packets with some duplicate data (%d bytes duped)\r\n",
-			tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
-	lprint("          %6d out-of-order packets (%d bytes)\r\n",
-			tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte);
-	lprint("          %6d packets of data after window (%d bytes)\r\n",
-			tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin);
-	lprint("          %6d window probes\r\n", tcpstat.tcps_rcvwinprobe);
-	lprint("          %6d window update packets\r\n", tcpstat.tcps_rcvwinupd);
-	lprint("          %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose);
-	lprint("          %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum);
-	lprint("          %6d discarded for bad header offset fields\r\n",
-			tcpstat.tcps_rcvbadoff);
-
-	lprint("  %6d connection requests\r\n", tcpstat.tcps_connattempt);
-	lprint("  %6d connection accepts\r\n", tcpstat.tcps_accepts);
-	lprint("  %6d connections established (including accepts)\r\n", tcpstat.tcps_connects);
-	lprint("  %6d connections closed (including %d drop)\r\n",
-			tcpstat.tcps_closed, tcpstat.tcps_drops);
-	lprint("  %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops);
-	lprint("  %6d segments we tried to get rtt (%d succeeded)\r\n",
-			tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated);
-	lprint("  %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo);
-	lprint("          %6d connections dropped by rxmt timeout\r\n",
-			tcpstat.tcps_timeoutdrop);
-	lprint("  %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo);
-	lprint("  %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo);
-	lprint("          %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe);
-	lprint("          %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops);
-	lprint("  %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
-	lprint("  %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
-	lprint("  %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
-}
-
-static void
-udpstats(void)
-{
-        lprint(" \r\n");
-
-	lprint("UDP stats:\r\n");
-	lprint("  %6d datagrams received\r\n", udpstat.udps_ipackets);
-	lprint("  %6d with packets shorter than header\r\n", udpstat.udps_hdrops);
-	lprint("  %6d with bad checksums\r\n", udpstat.udps_badsum);
-	lprint("  %6d with data length larger than packet\r\n", udpstat.udps_badlen);
-	lprint("  %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss);
-	lprint("  %6d datagrams sent\r\n", udpstat.udps_opackets);
-}
-
-static void
-icmpstats(void)
-{
-	lprint(" \r\n");
-	lprint("ICMP stats:\r\n");
-	lprint("  %6d ICMP packets received\r\n", icmpstat.icps_received);
-	lprint("  %6d were too short\r\n", icmpstat.icps_tooshort);
-	lprint("  %6d with bad checksums\r\n", icmpstat.icps_checksum);
-	lprint("  %6d with type not supported\r\n", icmpstat.icps_notsupp);
-	lprint("  %6d with bad type feilds\r\n", icmpstat.icps_badtype);
-	lprint("  %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
-}
-
-static void
-mbufstats(void)
-{
-	struct mbuf *m;
-	int i;
-
-        lprint(" \r\n");
-
-	lprint("Mbuf stats:\r\n");
-
-	lprint("  %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
-
-	i = 0;
-	for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
-		i++;
-	lprint("  %6d mbufs on free list\r\n",  i);
-
-	i = 0;
-	for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
-		i++;
-	lprint("  %6d mbufs on used list\r\n",  i);
-        lprint("  %6d mbufs queued as packets\r\n\r\n", if_queued);
-}
-#endif
-
-void
-slirp_stats(void)
-{
-#ifdef LOG_ENABLED
-    ipstats();
-    tcpstats();
-    udpstats();
-    icmpstats();
-    mbufstats();
-#else
-    lprint("SLIRP statistics code not compiled.\n");
-#endif
-}
diff --git a/slirp/icmp_var.h b/slirp/icmp_var.h
index 99d4c9e..edbb922 100644
--- a/slirp/icmp_var.h
+++ b/slirp/icmp_var.h
@@ -34,20 +34,6 @@
 #define _NETINET_ICMP_VAR_H_
 
 /*
- * Variables related to this implementation
- * of the internet control message protocol.
- */
-struct icmpstat {
-/* statistics related to input messages processed */
-	u_long  icps_received;		/* #ICMP packets received */
-	u_long	icps_tooshort;		/* packet < ICMP_MINLEN */
-	u_long	icps_checksum;		/* bad checksum */
-	u_long	icps_notsupp;		/* #ICMP packets not supported */
-	u_long  icps_badtype;		/* #with bad type feild */
-	u_long	icps_reflect;		/* number of responses */
-};
-
-/*
  * Names for ICMP sysctl objects
  */
 #define	ICMPCTL_MASKREPL	1	/* allow replies to netmask requests */
@@ -60,8 +46,4 @@ struct icmpstat {
 	{ "stats", CTLTYPE_STRUCT }, \
 }
 
-#ifdef LOG_ENABLED
-extern struct icmpstat icmpstat;
-#endif
-
 #endif
diff --git a/slirp/if.h b/slirp/if.h
index d49bcd5..2fdc354 100644
--- a/slirp/if.h
+++ b/slirp/if.h
@@ -28,24 +28,4 @@ extern	struct mbuf *next_m;
 
 #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
 
-#ifdef LOG_ENABLED
-/* Interface statistics */
-struct slirp_ifstats {
-	u_int out_pkts;		/* Output packets */
-	u_int out_bytes;		/* Output bytes */
-	u_int out_errpkts;	/* Output Error Packets */
-	u_int out_errbytes;	/* Output Error Bytes */
-	u_int in_pkts;		/* Input packets */
-	u_int in_bytes;		/* Input bytes */
-	u_int in_errpkts;		/* Input Error Packets */
-	u_int in_errbytes;	/* Input Error Bytes */
-
-	u_int bytes_saved;	/* Number of bytes that compression "saved" */
-				/* ie: number of bytes that didn't need to be sent over the link
-				 * because of compression */
-
-	u_int in_mbad;		/* Bad incoming packets */
-};
-#endif
-
 #endif
diff --git a/slirp/ip.h b/slirp/ip.h
index 7a7a9b9..e0d7674 100644
--- a/slirp/ip.h
+++ b/slirp/ip.h
@@ -250,43 +250,6 @@ struct ipoption {
 	int8_t	ipopt_list[MAX_IPOPTLEN];	/* options proper */
 };
 
-#ifdef LOG_ENABLED
-/*
- * Structure attached to inpcb.ip_moptions and
- * passed to ip_output when IP multicast options are in use.
- */
-
-struct	ipstat {
-	u_long	ips_total;		/* total packets received */
-	u_long	ips_badsum;		/* checksum bad */
-	u_long	ips_tooshort;		/* packet too short */
-	u_long	ips_toosmall;		/* not enough data */
-	u_long	ips_badhlen;		/* ip header length < data size */
-	u_long	ips_badlen;		/* ip length < ip header length */
-	u_long	ips_fragments;		/* fragments received */
-	u_long	ips_fragdropped;	/* frags dropped (dups, out of space) */
-	u_long	ips_fragtimeout;	/* fragments timed out */
-	u_long	ips_forward;		/* packets forwarded */
-	u_long	ips_cantforward;	/* packets rcvd for unreachable dest */
-	u_long	ips_redirectsent;	/* packets forwarded on same net */
-	u_long	ips_noproto;		/* unknown or unsupported protocol */
-	u_long	ips_delivered;		/* datagrams delivered to upper level*/
-	u_long	ips_localout;		/* total ip packets generated here */
-	u_long	ips_odropped;		/* lost packets due to nobufs, etc. */
-	u_long	ips_reassembled;	/* total packets reassembled ok */
-	u_long	ips_fragmented;		/* datagrams successfully fragmented */
-	u_long	ips_ofragments;		/* output fragments created */
-	u_long	ips_cantfrag;		/* don't fragment flag was set, etc. */
-	u_long	ips_badoptions;		/* error in option processing */
-	u_long	ips_noroute;		/* packets discarded due to no route */
-	u_long	ips_badvers;		/* ip version != 4 */
-	u_long	ips_rawout;		/* total raw ip packets generated */
-	u_long	ips_unaligned;		/* times the ip packet was not aligned */
-};
-
-extern struct	ipstat	ipstat;
-#endif
-
 extern struct	ipq	ipq;			/* ip reass. queue */
 extern u_int16_t	ip_id;				/* ip packet ctr, for ids */
 
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index c47ab1f..66b4d23 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -33,10 +33,6 @@
 #include "slirp.h"
 #include "ip_icmp.h"
 
-#ifdef LOG_ENABLED
-struct icmpstat icmpstat;
-#endif
-
 /* The message sent when emulating PING */
 /* Be nice and tell them it's just a pseudo-ping packet */
 static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
@@ -78,14 +74,11 @@ icmp_input(struct mbuf *m, int hlen)
   DEBUG_ARG("m = %lx", (long )m);
   DEBUG_ARG("m_len = %d", m->m_len);
 
-  STAT(icmpstat.icps_received++);
-
   /*
    * Locate icmp structure in mbuf, and check
    * that its not corrupted and of at least minimum length.
    */
   if (icmplen < ICMP_MINLEN) {          /* min 8 bytes payload */
-    STAT(icmpstat.icps_tooshort++);
   freeit:
     m_freem(m);
     goto end_error;
@@ -95,7 +88,6 @@ icmp_input(struct mbuf *m, int hlen)
   m->m_data += hlen;
   icp = mtod(m, struct icmp *);
   if (cksum(m, icmplen)) {
-    STAT(icmpstat.icps_checksum++);
     goto freeit;
   }
   m->m_len += hlen;
@@ -159,12 +151,10 @@ icmp_input(struct mbuf *m, int hlen)
   case ICMP_TSTAMP:
   case ICMP_MASKREQ:
   case ICMP_REDIRECT:
-    STAT(icmpstat.icps_notsupp++);
     m_freem(m);
     break;
 
   default:
-    STAT(icmpstat.icps_badtype++);
     m_freem(m);
   } /* swith */
 
@@ -299,8 +289,6 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
 
   (void ) ip_output((struct socket *)NULL, m);
 
-  STAT(icmpstat.icps_reflect++);
-
 end_error:
   return;
 }
@@ -354,6 +342,4 @@ icmp_reflect(struct mbuf *m)
   }
 
   (void ) ip_output((struct socket *)NULL, m);
-
-  STAT(icmpstat.icps_reflect++);
 }
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 1fdd8d6..0356eb5 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -42,10 +42,6 @@
 #include <osdep.h>
 #include "ip_icmp.h"
 
-#ifdef LOG_ENABLED
-struct ipstat ipstat;
-#endif
-
 struct ipq ipq;
 
 static struct ip *ip_reass(register struct ip *ip,
@@ -82,24 +78,19 @@ ip_input(struct mbuf *m)
 	DEBUG_ARG("m = %lx", (long)m);
 	DEBUG_ARG("m_len = %d", m->m_len);
 
-	STAT(ipstat.ips_total++);
-
 	if (m->m_len < sizeof (struct ip)) {
-		STAT(ipstat.ips_toosmall++);
 		return;
 	}
 
 	ip = mtod(m, struct ip *);
 
 	if (ip->ip_v != IPVERSION) {
-		STAT(ipstat.ips_badvers++);
 		goto bad;
 	}
 
 	hlen = ip->ip_hl << 2;
 	if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
-	  STAT(ipstat.ips_badhlen++);                     /* or packet too short */
-	  goto bad;
+	  goto bad;                                  /* or packet too short */
 	}
 
         /* keep ip header intact for ICMP reply
@@ -107,7 +98,6 @@ ip_input(struct mbuf *m)
 	 * if (ip->ip_sum) {
 	 */
 	if(cksum(m,hlen)) {
-	  STAT(ipstat.ips_badsum++);
 	  goto bad;
 	}
 
@@ -116,7 +106,6 @@ ip_input(struct mbuf *m)
 	 */
 	NTOHS(ip->ip_len);
 	if (ip->ip_len < hlen) {
-		STAT(ipstat.ips_badlen++);
 		goto bad;
 	}
 	NTOHS(ip->ip_id);
@@ -129,7 +118,6 @@ ip_input(struct mbuf *m)
 	 * Drop packet if shorter than we expect.
 	 */
 	if (m->m_len < ip->ip_len) {
-		STAT(ipstat.ips_tooshort++);
 		goto bad;
 	}
 
@@ -210,11 +198,9 @@ ip_input(struct mbuf *m)
 		 * attempt reassembly; if it succeeds, proceed.
 		 */
 		if (ip->ip_tos & 1 || ip->ip_off) {
-			STAT(ipstat.ips_fragments++);
 			ip = ip_reass(ip, fp);
                         if (ip == NULL)
 				return;
-			STAT(ipstat.ips_reassembled++);
 			m = dtom(ip);
 		} else
 			if (fp)
@@ -226,7 +212,6 @@ ip_input(struct mbuf *m)
 	/*
 	 * Switch out to protocol's input routine.
 	 */
-	STAT(ipstat.ips_delivered++);
 	switch (ip->ip_p) {
 	 case IPPROTO_TCP:
 		tcp_input(m, hlen, (struct socket *)NULL);
@@ -238,7 +223,6 @@ ip_input(struct mbuf *m)
 		icmp_input(m, hlen);
 		break;
 	 default:
-		STAT(ipstat.ips_noproto++);
 		m_free(m);
 	}
 	return;
@@ -399,7 +383,6 @@ insert:
 	return ip;
 
 dropfrag:
-	STAT(ipstat.ips_fragdropped++);
 	m_freem(m);
         return NULL;
 }
@@ -468,7 +451,6 @@ ip_slowtimo(void)
         struct ipq *fp = container_of(l, struct ipq, ip_link);
         l = l->next;
 		if (--fp->ipq_ttl == 0) {
-			STAT(ipstat.ips_fragtimeout++);
 			ip_freef(fp);
 		}
 	}
@@ -671,7 +653,6 @@ typedef u_int32_t n_time;
 bad:
  	icmp_error(m, type, code, 0, 0);
 
-	STAT(ipstat.ips_badoptions++);
 	return (1);
 }
 
diff --git a/slirp/ip_output.c b/slirp/ip_output.c
index 94bb0f2..3031f4d 100644
--- a/slirp/ip_output.c
+++ b/slirp/ip_output.c
@@ -72,7 +72,6 @@ ip_output(struct socket *so, struct mbuf *m0)
 	ip->ip_off &= IP_DF;
 	ip->ip_id = htons(ip_id++);
 	ip->ip_hl = hlen >> 2;
-	STAT(ipstat.ips_localout++);
 
 	/*
 	 * If small enough for interface, can just send directly.
@@ -93,7 +92,6 @@ ip_output(struct socket *so, struct mbuf *m0)
 	 */
 	if (ip->ip_off & IP_DF) {
 		error = -1;
-		STAT(ipstat.ips_cantfrag++);
 		goto bad;
 	}
 
@@ -118,7 +116,6 @@ ip_output(struct socket *so, struct mbuf *m0)
 	  m = m_get();
           if (m == NULL) {
 	    error = -1;
-	    STAT(ipstat.ips_odropped++);
 	    goto sendorfree;
 	  }
 	  m->m_data += IF_MAXLINKHDR;
@@ -145,7 +142,6 @@ ip_output(struct socket *so, struct mbuf *m0)
 	  mhip->ip_sum = cksum(m, mhlen);
 	  *mnext = m;
 	  mnext = &m->m_nextpkt;
-	  STAT(ipstat.ips_ofragments++);
 	}
 	/*
 	 * Update first fragment by trimming what's been copied out
@@ -166,9 +162,6 @@ sendorfree:
 		else
 			m_freem(m);
 	}
-
-	if (error == 0)
-		STAT(ipstat.ips_fragmented++);
     }
 
 done:
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index c48837c..8117187 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -26,7 +26,6 @@ int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port);
 int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
                    int guest_port);
 
-void slirp_stats(void);
 void slirp_connection_info(Monitor *mon);
 
 void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index 7963d34..888de86 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -17,10 +17,9 @@
 
 #include <slirp.h>
 
-int mbuf_alloced = 0;
+static int mbuf_alloced;
 struct mbuf m_freelist, m_usedlist;
 #define MBUF_THRESH 30
-int mbuf_max = 0;
 
 /*
  * Find a nice value for msize
@@ -57,8 +56,6 @@ m_get(void)
 		mbuf_alloced++;
 		if (mbuf_alloced > MBUF_THRESH)
 			flags = M_DOFREE;
-		if (mbuf_alloced > mbuf_max)
-			mbuf_max = mbuf_alloced;
 	} else {
 		m = m_freelist.m_next;
 		remque(m);
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index e259441..c482753 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -114,19 +114,7 @@ struct mbuf {
 #define M_DOFREE		0x08	/* when m_free is called on the mbuf, free()
 					 * it rather than putting it on the free list */
 
-/*
- * Mbuf statistics. XXX
- */
-
-struct mbstat {
-	int mbs_alloced;		/* Number of mbufs allocated */
-
-};
-
-extern struct	mbstat mbstat;
-extern int mbuf_alloced;
 extern struct mbuf m_freelist, m_usedlist;
-extern int mbuf_max;
 
 void m_init _P((void));
 struct mbuf * m_get _P((void));
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 0c62fd7..c308582 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -3,15 +3,6 @@
 
 //#define DEBUG 1
 
-// Uncomment the following line to enable SLIRP statistics printing in Qemu
-//#define LOG_ENABLED
-
-#ifdef LOG_ENABLED
-#define STAT(expr) expr
-#else
-#define STAT(expr) do { } while(0)
-#endif
-
 #include "config-host.h"
 #include "slirp_config.h"
 
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 980ae06..b7a67e5 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -75,8 +75,6 @@ tcp_seq tcp_iss;                /* tcp initial send seq # */
                        tp->t_flags |= TF_DELACK; \
                (tp)->rcv_nxt += (ti)->ti_len; \
                flags = (ti)->ti_flags & TH_FIN; \
-               STAT(tcpstat.tcps_rcvpack++);         \
-               STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);   \
                if (so->so_emu) { \
 		       if (tcp_emu((so),(m))) sbappend((so), (m)); \
 	       } else \
@@ -94,8 +92,6 @@ tcp_seq tcp_iss;                /* tcp initial send seq # */
 		tp->t_flags |= TF_DELACK; \
 		(tp)->rcv_nxt += (ti)->ti_len; \
 		flags = (ti)->ti_flags & TH_FIN; \
-		STAT(tcpstat.tcps_rcvpack++);        \
-		STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);  \
 		if (so->so_emu) { \
 			if (tcp_emu((so),(m))) sbappend(so, (m)); \
 		} else \
@@ -145,8 +141,6 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
 		i = q->ti_seq + q->ti_len - ti->ti_seq;
 		if (i > 0) {
 			if (i >= ti->ti_len) {
-				STAT(tcpstat.tcps_rcvduppack++);
-				STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len);
 				m_freem(m);
 				/*
 				 * Try to present any queued data
@@ -162,8 +156,6 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
 		}
 		q = tcpiphdr_next(q);
 	}
-	STAT(tcpstat.tcps_rcvoopack++);
-	STAT(tcpstat.tcps_rcvoobyte += ti->ti_len);
 	ti->ti_mbuf = m;
 
 	/*
@@ -263,8 +255,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 		goto cont_conn;
 	}
 
-
-	STAT(tcpstat.tcps_rcvtotal++);
 	/*
 	 * Get IP and TCP header together in first mbuf.
 	 * Note: IP leaves IP header in first mbuf.
@@ -295,7 +285,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	ti->ti_len = htons((u_int16_t)tlen);
 	len = sizeof(struct ip ) + tlen;
 	if(cksum(m, len)) {
-	  STAT(tcpstat.tcps_rcvbadsum++);
 	  goto drop;
 	}
 
@@ -305,7 +294,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	 */
 	off = ti->ti_off << 2;
 	if (off < sizeof (struct tcphdr) || off > tlen) {
-	  STAT(tcpstat.tcps_rcvbadoff++);
 	  goto drop;
 	}
 	tlen -= off;
@@ -353,7 +341,6 @@ findso:
 			       ti->ti_dst, ti->ti_dport);
 		if (so)
 			tcp_last_so = so;
-		STAT(tcpstat.tcps_socachemiss++);
 	}
 
 	/*
@@ -460,13 +447,10 @@ findso:
 				/*
 				 * this is a pure ack for outstanding data.
 				 */
-				STAT(tcpstat.tcps_predack++);
 				if (tp->t_rtt &&
 				    SEQ_GT(ti->ti_ack, tp->t_rtseq))
 					tcp_xmit_timer(tp, tp->t_rtt);
 				acked = ti->ti_ack - tp->snd_una;
-				STAT(tcpstat.tcps_rcvackpack++);
-				STAT(tcpstat.tcps_rcvackbyte += acked);
 				sbdrop(&so->so_snd, acked);
 				tp->snd_una = ti->ti_ack;
 				m_freem(m);
@@ -503,10 +487,7 @@ findso:
 			 * with nothing on the reassembly queue and
 			 * we have enough buffer space to take it.
 			 */
-			STAT(tcpstat.tcps_preddat++);
 			tp->rcv_nxt += ti->ti_len;
-			STAT(tcpstat.tcps_rcvpack++);
-			STAT(tcpstat.tcps_rcvbyte += ti->ti_len);
 			/*
 			 * Add data to socket buffer.
 			 */
@@ -658,7 +639,6 @@ findso:
 	  tp->t_flags |= TF_ACKNOW;
 	  tp->t_state = TCPS_SYN_RECEIVED;
 	  tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
-	  STAT(tcpstat.tcps_accepts++);
 	  goto trimthenstep6;
 	} /* case TCPS_LISTEN */
 
@@ -699,7 +679,6 @@ findso:
 		tcp_rcvseqinit(tp);
 		tp->t_flags |= TF_ACKNOW;
 		if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
-			STAT(tcpstat.tcps_connects++);
 			soisfconnected(so);
 			tp->t_state = TCPS_ESTABLISHED;
 
@@ -726,8 +705,6 @@ trimthenstep6:
 			m_adj(m, -todrop);
 			ti->ti_len = tp->rcv_wnd;
 			tiflags &= ~TH_FIN;
-			STAT(tcpstat.tcps_rcvpackafterwin++);
-			STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
 		}
 		tp->snd_wl1 = ti->ti_seq - 1;
 		tp->rcv_up = ti->ti_seq;
@@ -768,11 +745,6 @@ trimthenstep6:
 			 */
 			tp->t_flags |= TF_ACKNOW;
 			todrop = ti->ti_len;
-			STAT(tcpstat.tcps_rcvduppack++);
-			STAT(tcpstat.tcps_rcvdupbyte += todrop);
-		} else {
-			STAT(tcpstat.tcps_rcvpartduppack++);
-			STAT(tcpstat.tcps_rcvpartdupbyte += todrop);
 		}
 		m_adj(m, todrop);
 		ti->ti_seq += todrop;
@@ -791,7 +763,6 @@ trimthenstep6:
 	if ((so->so_state & SS_NOFDREF) &&
 	    tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
 		tp = tcp_close(tp);
-		STAT(tcpstat.tcps_rcvafterclose++);
 		goto dropwithreset;
 	}
 
@@ -801,9 +772,7 @@ trimthenstep6:
 	 */
 	todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
 	if (todrop > 0) {
-		STAT(tcpstat.tcps_rcvpackafterwin++);
 		if (todrop >= ti->ti_len) {
-			STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len);
 			/*
 			 * If a new connection request is received
 			 * while in TIME_WAIT, drop the old connection
@@ -826,11 +795,10 @@ trimthenstep6:
 			 */
 			if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
 				tp->t_flags |= TF_ACKNOW;
-				STAT(tcpstat.tcps_rcvwinprobe++);
-			} else
+			} else {
 				goto dropafterack;
-		} else
-			STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
+			}
+		}
 		m_adj(m, -todrop);
 		ti->ti_len -= todrop;
 		tiflags &= ~(TH_PUSH|TH_FIN);
@@ -854,7 +822,6 @@ trimthenstep6:
 	case TCPS_FIN_WAIT_2:
 	case TCPS_CLOSE_WAIT:
 		tp->t_state = TCPS_CLOSED;
-		STAT(tcpstat.tcps_drops++);
 		tp = tcp_close(tp);
 		goto drop;
 
@@ -893,7 +860,6 @@ trimthenstep6:
 		if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
 		    SEQ_GT(ti->ti_ack, tp->snd_max))
 			goto dropwithreset;
-		STAT(tcpstat.tcps_connects++);
 		tp->t_state = TCPS_ESTABLISHED;
 		/*
 		 * The sent SYN is ack'ed with our sequence number +1
@@ -944,7 +910,6 @@ trimthenstep6:
 
 		if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
 			if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
-			  STAT(tcpstat.tcps_rcvdupack++);
 			  DEBUG_MISC((dfd," dup ack  m = %lx  so = %lx \n",
 				      (long )m, (long )so));
 				/*
@@ -1012,12 +977,9 @@ trimthenstep6:
 			tp->snd_cwnd = tp->snd_ssthresh;
 		tp->t_dupacks = 0;
 		if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
-			STAT(tcpstat.tcps_rcvacktoomuch++);
 			goto dropafterack;
 		}
 		acked = ti->ti_ack - tp->snd_una;
-		STAT(tcpstat.tcps_rcvackpack++);
-		STAT(tcpstat.tcps_rcvackbyte += acked);
 
 		/*
 		 * If transmit timer is running and timed sequence
@@ -1138,10 +1100,6 @@ step6:
 	    (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
 	    (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
 	    (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
-		/* keep track of pure window updates */
-		if (ti->ti_len == 0 &&
-		    tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
-			STAT(tcpstat.tcps_rcvwinupd++);
 		tp->snd_wnd = tiwin;
 		tp->snd_wl1 = ti->ti_seq;
 		tp->snd_wl2 = ti->ti_ack;
@@ -1425,7 +1383,6 @@ tcp_xmit_timer(register struct tcpcb *tp, int rtt)
 	DEBUG_ARG("tp = %lx", (long)tp);
 	DEBUG_ARG("rtt = %d", rtt);
 
-	STAT(tcpstat.tcps_rttupdated++);
 	if (tp->t_srtt != 0) {
 		/*
 		 * srtt is stored as fixed point with 3 bits after the
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index a11f3da..686e90d 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -247,8 +247,6 @@ again:
 	/*
 	 * No reason to send a segment, just return.
 	 */
-	STAT(tcpstat.tcps_didnuttin++);
-
 	return (0);
 
 send:
@@ -292,16 +290,6 @@ send:
 	 * the template for sends on this connection.
 	 */
 	if (len) {
-		if (tp->t_force && len == 1)
-			STAT(tcpstat.tcps_sndprobe++);
-		else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
-			STAT(tcpstat.tcps_sndrexmitpack++);
-			STAT(tcpstat.tcps_sndrexmitbyte += len);
-		} else {
-			STAT(tcpstat.tcps_sndpack++);
-			STAT(tcpstat.tcps_sndbyte += len);
-		}
-
 		m = m_get();
 		if (m == NULL) {
 			error = 1;
@@ -322,15 +310,6 @@ send:
 		if (off + len == so->so_snd.sb_cc)
 			flags |= TH_PUSH;
 	} else {
-		if (tp->t_flags & TF_ACKNOW)
-			STAT(tcpstat.tcps_sndacks++);
-		else if (flags & (TH_SYN|TH_FIN|TH_RST))
-			STAT(tcpstat.tcps_sndctrl++);
-		else if (SEQ_GT(tp->snd_up, tp->snd_una))
-			STAT(tcpstat.tcps_sndurg++);
-		else
-			STAT(tcpstat.tcps_sndwinup++);
-
 		m = m_get();
 		if (m == NULL) {
 			error = 1;
@@ -436,7 +415,6 @@ send:
 			if (tp->t_rtt == 0) {
 				tp->t_rtt = 1;
 				tp->t_rtseq = startseq;
-				STAT(tcpstat.tcps_segstimed++);
 			}
 		}
 
@@ -481,7 +459,6 @@ send:
 out:
 		return (error);
 	}
-	STAT(tcpstat.tcps_sndtotal++);
 
 	/*
 	 * Data sent (as far as we can tell).
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 892bd83..868382a 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -222,9 +222,7 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
 	if (TCPS_HAVERCVDSYN(tp->t_state)) {
 		tp->t_state = TCPS_CLOSED;
 		(void) tcp_output(tp);
-		STAT(tcpstat.tcps_drops++);
-	} else
-		STAT(tcpstat.tcps_conndrops++);
+	}
 	return (tcp_close(tp));
 }
 
@@ -261,7 +259,6 @@ tcp_close(struct tcpcb *tp)
 	sbfree(&so->so_rcv);
 	sbfree(&so->so_snd);
 	sofree(so);
-	STAT(tcpstat.tcps_closed++);
 	return ((struct tcpcb *)0);
 }
 
@@ -442,8 +439,6 @@ tcp_connect(struct socket *inso)
 
 	tcp_template(tp);
 
-	STAT(tcpstat.tcps_connattempt++);
-
 	tp->t_state = TCPS_SYN_SENT;
 	tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
 	tp->iss = tcp_iss;
diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c
index 9cacb0f..cd71572 100644
--- a/slirp/tcp_timer.c
+++ b/slirp/tcp_timer.c
@@ -32,10 +32,6 @@
 
 #include <slirp.h>
 
-#ifdef LOG_ENABLED
-struct   tcpstat tcpstat;        /* tcp statistics */
-#endif
-
 u_int32_t        tcp_now;                /* for RFC 1323 timestamps */
 
 static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
@@ -58,7 +54,6 @@ tcp_fasttimo(void)
 		    (tp->t_flags & TF_DELACK)) {
 			tp->t_flags &= ~TF_DELACK;
 			tp->t_flags |= TF_ACKNOW;
-			STAT(tcpstat.tcps_delack++);
 			(void) tcp_output(tp);
 		}
 }
@@ -180,7 +175,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 				 * We tried our best, now the connection must die!
 				 */
 				tp->t_rxtshift = TCP_MAXRXTSHIFT;
-				STAT(tcpstat.tcps_timeoutdrop++);
 				tp = tcp_drop(tp, tp->t_softerror);
 				/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
 				return (tp); /* XXX */
@@ -192,7 +186,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 			 */
 			tp->t_rxtshift = 6;
 		}
-		STAT(tcpstat.tcps_rexmttimeo++);
 		rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
 		TCPT_RANGESET(tp->t_rxtcur, rexmt,
 		    (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
@@ -254,7 +247,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 	 * Force a byte to be output, if possible.
 	 */
 	case TCPT_PERSIST:
-		STAT(tcpstat.tcps_persisttimeo++);
 		tcp_setpersist(tp);
 		tp->t_force = 1;
 		(void) tcp_output(tp);
@@ -266,7 +258,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 	 * or drop connection if idle for too long.
 	 */
 	case TCPT_KEEP:
-		STAT(tcpstat.tcps_keeptimeo++);
 		if (tp->t_state < TCPS_ESTABLISHED)
 			goto dropit;
 
@@ -285,7 +276,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 			 * by the protocol spec, this requires the
 			 * correspondent TCP to respond.
 			 */
-			STAT(tcpstat.tcps_keepprobe++);
 			tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
 			    tp->rcv_nxt, tp->snd_una - 1, 0);
 			tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
@@ -294,7 +284,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 		break;
 
 	dropit:
-		STAT(tcpstat.tcps_keepdrops++);
 		tp = tcp_drop(tp, 0);
 		break;
 	}
diff --git a/slirp/tcp_var.h b/slirp/tcp_var.h
index be5741f..db0a9c9 100644
--- a/slirp/tcp_var.h
+++ b/slirp/tcp_var.h
@@ -158,69 +158,6 @@ struct tcpcb {
 #define	TCP_REXMTVAL(tp) \
 	(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
 
-#ifdef LOG_ENABLED
-/*
- * TCP statistics.
- * Many of these should be kept per connection,
- * but that's inconvenient at the moment.
- */
-struct tcpstat {
-	u_long	tcps_connattempt;	/* connections initiated */
-	u_long	tcps_accepts;		/* connections accepted */
-	u_long	tcps_connects;		/* connections established */
-	u_long	tcps_drops;		/* connections dropped */
-	u_long	tcps_conndrops;		/* embryonic connections dropped */
-	u_long	tcps_closed;		/* conn. closed (includes drops) */
-	u_long	tcps_segstimed;		/* segs where we tried to get rtt */
-	u_long	tcps_rttupdated;	/* times we succeeded */
-	u_long	tcps_delack;		/* delayed acks sent */
-	u_long	tcps_timeoutdrop;	/* conn. dropped in rxmt timeout */
-	u_long	tcps_rexmttimeo;	/* retransmit timeouts */
-	u_long	tcps_persisttimeo;	/* persist timeouts */
-	u_long	tcps_keeptimeo;		/* keepalive timeouts */
-	u_long	tcps_keepprobe;		/* keepalive probes sent */
-	u_long	tcps_keepdrops;		/* connections dropped in keepalive */
-
-	u_long	tcps_sndtotal;		/* total packets sent */
-	u_long	tcps_sndpack;		/* data packets sent */
-	u_long	tcps_sndbyte;		/* data bytes sent */
-	u_long	tcps_sndrexmitpack;	/* data packets retransmitted */
-	u_long	tcps_sndrexmitbyte;	/* data bytes retransmitted */
-	u_long	tcps_sndacks;		/* ack-only packets sent */
-	u_long	tcps_sndprobe;		/* window probes sent */
-	u_long	tcps_sndurg;		/* packets sent with URG only */
-	u_long	tcps_sndwinup;		/* window update-only packets sent */
-	u_long	tcps_sndctrl;		/* control (SYN|FIN|RST) packets sent */
-
-	u_long	tcps_rcvtotal;		/* total packets received */
-	u_long	tcps_rcvpack;		/* packets received in sequence */
-	u_long	tcps_rcvbyte;		/* bytes received in sequence */
-	u_long	tcps_rcvbadsum;		/* packets received with ccksum errs */
-	u_long	tcps_rcvbadoff;		/* packets received with bad offset */
-	u_long	tcps_rcvduppack;	/* duplicate-only packets received */
-	u_long	tcps_rcvdupbyte;	/* duplicate-only bytes received */
-	u_long	tcps_rcvpartduppack;	/* packets with some duplicate data */
-	u_long	tcps_rcvpartdupbyte;	/* dup. bytes in part-dup. packets */
-	u_long	tcps_rcvoopack;		/* out-of-order packets received */
-	u_long	tcps_rcvoobyte;		/* out-of-order bytes received */
-	u_long	tcps_rcvpackafterwin;	/* packets with data after window */
-	u_long	tcps_rcvbyteafterwin;	/* bytes rcvd after window */
-	u_long	tcps_rcvafterclose;	/* packets rcvd after "close" */
-	u_long	tcps_rcvwinprobe;	/* rcvd window probe packets */
-	u_long	tcps_rcvdupack;		/* rcvd duplicate acks */
-	u_long	tcps_rcvacktoomuch;	/* rcvd acks for unsent data */
-	u_long	tcps_rcvackpack;	/* rcvd ack packets */
-	u_long	tcps_rcvackbyte;	/* bytes acked by rcvd acks */
-	u_long	tcps_rcvwinupd;		/* rcvd window update packets */
-	u_long	tcps_predack;		/* times hdr predict ok for acks */
-	u_long	tcps_preddat;		/* times hdr predict ok for data pkts */
-	u_long	tcps_socachemiss;	/* tcp_last_so misses */
-	u_long	tcps_didnuttin;		/* Times tcp_output didn't do anything XXX */
-};
-
-extern struct	tcpstat tcpstat;	/* tcp statistics */
-#endif
-
 extern u_int32_t	tcp_now;		/* for RFC 1323 timestamps */
 
 #endif
diff --git a/slirp/udp.c b/slirp/udp.c
index 3798e34..240e1bf 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -41,10 +41,6 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
-#ifdef LOG_ENABLED
-struct udpstat udpstat;
-#endif
-
 struct socket udb;
 
 static u_int8_t udp_tos(struct socket *so);
@@ -74,8 +70,6 @@ udp_input(register struct mbuf *m, int iphlen)
 	DEBUG_ARG("m = %lx", (long)m);
 	DEBUG_ARG("iphlen = %d", iphlen);
 
-	STAT(udpstat.udps_ipackets++);
-
 	/*
 	 * Strip IP options, if any; should skip this,
 	 * make available to user, and use on returned packets,
@@ -101,7 +95,6 @@ udp_input(register struct mbuf *m, int iphlen)
 
 	if (ip->ip_len != len) {
 		if (len > ip->ip_len) {
-			STAT(udpstat.udps_badlen++);
 			goto bad;
 		}
 		m_adj(m, len - ip->ip_len);
@@ -123,7 +116,6 @@ udp_input(register struct mbuf *m, int iphlen)
 	  ((struct ipovly *)ip)->ih_x1 = 0;
 	  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
 	  if(cksum(m, len + sizeof(struct ip))) {
-	    STAT(udpstat.udps_badsum++);
 	    goto bad;
 	  }
 	}
@@ -165,7 +157,6 @@ udp_input(register struct mbuf *m, int iphlen)
 		if (tmp == &udb) {
 		  so = NULL;
 		} else {
-		  STAT(udpstat.udpps_pcbcachemiss++);
 		  udp_last_so = so;
 		}
 	}
@@ -279,8 +270,6 @@ int udp_output2(struct socket *so, struct mbuf *m,
 	((struct ip *)ui)->ip_ttl = IPDEFTTL;
 	((struct ip *)ui)->ip_tos = iptos;
 
-	STAT(udpstat.udps_opackets++);
-
 	error = ip_output(so, m);
 
 	return (error);
diff --git a/slirp/udp.h b/slirp/udp.h
index d4c2bea..3eed14a 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -67,32 +67,12 @@ struct udpiphdr {
 #define ui_ulen         ui_u.uh_ulen
 #define ui_sum          ui_u.uh_sum
 
-#ifdef LOG_ENABLED
-struct udpstat {
-	                                /* input statistics: */
-	        u_long  udps_ipackets;          /* total input packets */
-	        u_long  udps_hdrops;            /* packet shorter than header */
-	        u_long  udps_badsum;            /* checksum error */
-	        u_long  udps_badlen;            /* data length larger than packet */
-	        u_long  udps_noport;            /* no socket on port */
-	        u_long  udps_noportbcast;       /* of above, arrived as broadcast */
-	        u_long  udps_fullsock;          /* not delivered, input socket full */
-	        u_long  udpps_pcbcachemiss;     /* input packets missing pcb cache */
-	                                /* output statistics: */
-	        u_long  udps_opackets;          /* total output packets */
-};
-#endif
-
 /*
  * Names for UDP sysctl objects
  */
 #define UDPCTL_CHECKSUM         1       /* checksum UDP packets */
 #define UDPCTL_MAXID            2
 
-#ifdef LOG_ENABLED
-extern struct udpstat udpstat;
-#endif
-
 extern struct socket udb;
 struct mbuf;
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 19/41] slirp: Drop unused icmp_var.h
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (11 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 12/41] slirp: Explicitely mark host-forwarding sockets Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 15/41] slirp: Add info usernet for dumping connection states Jan Kiszka
                   ` (28 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/icmp_var.h |   49 -------------------------------------------------
 slirp/slirp.h    |    1 -
 2 files changed, 0 insertions(+), 50 deletions(-)
 delete mode 100644 slirp/icmp_var.h

diff --git a/slirp/icmp_var.h b/slirp/icmp_var.h
deleted file mode 100644
index edbb922..0000000
--- a/slirp/icmp_var.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 1982, 1986, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)icmp_var.h	8.1 (Berkeley) 6/10/93
- * icmp_var.h,v 1.4 1995/02/16 00:27:40 wollman Exp
- */
-
-#ifndef _NETINET_ICMP_VAR_H_
-#define _NETINET_ICMP_VAR_H_
-
-/*
- * Names for ICMP sysctl objects
- */
-#define	ICMPCTL_MASKREPL	1	/* allow replies to netmask requests */
-#define	ICMPCTL_STATS		2	/* statistics (read-only) */
-#define ICMPCTL_MAXID		3
-
-#define ICMPCTL_NAMES { \
-	{ 0, 0 }, \
-	{ "maskrepl", CTLTYPE_INT }, \
-	{ "stats", CTLTYPE_STRUCT }, \
-}
-
-#endif
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 1bd7c89..063e5f6 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -191,7 +191,6 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 #include "tcp_var.h"
 #include "tcpip.h"
 #include "udp.h"
-#include "icmp_var.h"
 #include "mbuf.h"
 #include "sbuf.h"
 #include "socket.h"

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 20/41] slirp: tftp: Cleanup tftp_prefix check
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (16 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 14/41] slirp: Mark sockets of incoming TCP connections Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 11/41] slirp: Prepare for persistent socket state flags Jan Kiszka
                   ` (23 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Perform check for set prefix early (if it's not given, tftp is disabled)
and drop redundant second check.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/tftp.c |   15 +++++++--------
 1 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/slirp/tftp.c b/slirp/tftp.c
index 3358e2b..5d5614a 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -287,6 +287,12 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 
   spt = &tftp_sessions[s];
 
+  /* unspecifed prefix means service disabled */
+  if (!tftp_prefix) {
+      tftp_send_error(spt, 2, "Access violation", tp);
+      return;
+  }
+
   src = tp->x.tp_buf;
   dst = spt->filename;
   n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
@@ -333,13 +339,6 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
       return;
   }
 
-  /* only allow exported prefixes */
-
-  if (!tftp_prefix) {
-      tftp_send_error(spt, 2, "Access violation", tp);
-      return;
-  }
-
   /* check if the file exists */
 
   if (tftp_read_data(spt, 0, spt->filename, 0) < 0) {
@@ -370,7 +369,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 	  int tsize = atoi(value);
 	  struct stat stat_p;
 
-	  if (tsize == 0 && tftp_prefix) {
+	  if (tsize == 0) {
 	      char buffer[1024];
 	      int len;
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 16/41] slirp: Drop dead code
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (9 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 06/41] slirp: Rework internal configuration Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 12/41] slirp: Explicitely mark host-forwarding sockets Jan Kiszka
                   ` (30 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 73507 bytes --]

After all its years inside the qemu tree, there is no point in keeping
the dead code paths of slirp. This patch is a first round of removing
usually commented out code parts. More cleanups need to follow (and
maybe finally a proper reindention).

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/debug.c      |  185 ------------------
 slirp/debug.h      |    2 
 slirp/if.c         |   80 --------
 slirp/if.h         |   14 -
 slirp/ip_icmp.c    |    4 
 slirp/ip_input.c   |   17 --
 slirp/ip_output.c  |   23 --
 slirp/libslirp.h   |    8 -
 slirp/mbuf.c       |    6 -
 slirp/mbuf.h       |    2 
 slirp/misc.c       |  525 ----------------------------------------------------
 slirp/misc.h       |    8 -
 slirp/sbuf.c       |    8 -
 slirp/slirp.c      |   13 -
 slirp/slirp.h      |    7 -
 slirp/socket.c     |   53 -----
 slirp/socket.h     |    4 
 slirp/tcp.h        |    1 
 slirp/tcp_input.c  |  210 +--------------------
 slirp/tcp_output.c |   77 --------
 slirp/tcp_subr.c   |  366 ------------------------------------
 slirp/tcp_timer.c  |   17 --
 slirp/tcp_timer.h  |    6 -
 slirp/tcp_var.h    |    6 -
 slirp/tftp.c       |    2 
 slirp/udp.c        |   28 ---
 26 files changed, 22 insertions(+), 1650 deletions(-)

diff --git a/slirp/debug.c b/slirp/debug.c
index ac856ca..6462c88 100644
--- a/slirp/debug.c
+++ b/slirp/debug.c
@@ -9,127 +9,9 @@
 #include <slirp.h>
 
 FILE *dfd = NULL;
-#ifdef DEBUG
-int dostats = 1;
-#else
-int dostats = 0;
-#endif
 int slirp_debug = 0;
 
-/* Carry over one item from main.c so that the tty's restored.
- * Only done when the tty being used is /dev/tty --RedWolf */
-#ifndef CONFIG_QEMU
-extern struct termios slirp_tty_settings;
-extern int slirp_tty_restore;
-
-
-void
-debug_init(file, dbg)
-	char *file;
-	int dbg;
-{
-	/* Close the old debugging file */
-	if (dfd)
-	   fclose(dfd);
-
-	dfd = fopen(file,"w");
-	if (dfd != NULL) {
-#if 0
-		fprintf(dfd,"Slirp %s - Debugging Started.\n", SLIRP_VERSION);
-#endif
-		fprintf(dfd,"Debugging Started level %i.\r\n",dbg);
-		fflush(dfd);
-		slirp_debug = dbg;
-	} else {
-		lprint("Error: Debugging file \"%s\" could not be opened: %s\r\n",
-			file, strerror(errno));
-	}
-}
-
-/*
- * Dump a packet in the same format as tcpdump -x
- */
-#ifdef DEBUG
-void
-dump_packet(dat, n)
-	void *dat;
-	int n;
-{
-	u_char *pptr = (u_char *)dat;
-	int j,k;
-
-	n /= 16;
-	n++;
-	DEBUG_MISC((dfd, "PACKET DUMPED: \n"));
-	for(j = 0; j < n; j++) {
-		for(k = 0; k < 6; k++)
-			DEBUG_MISC((dfd, "%02x ", *pptr++));
-		DEBUG_MISC((dfd, "\n"));
-		fflush(dfd);
-	}
-}
-#endif
-#endif
-
 #ifdef LOG_ENABLED
-#if 0
-/*
- * Statistic routines
- *
- * These will print statistics to the screen, the debug file (dfd), or
- * a buffer, depending on "type", so that the stats can be sent over
- * the link as well.
- */
-
-static void
-ttystats(ttyp)
-	struct ttys *ttyp;
-{
-	struct slirp_ifstats *is = &ttyp->ifstats;
-	char buff[512];
-
-	lprint(" \r\n");
-
-	if (IF_COMP & IF_COMPRESS)
-	   strcpy(buff, "on");
-	else if (IF_COMP & IF_NOCOMPRESS)
-	   strcpy(buff, "off");
-	else
-	   strcpy(buff, "off (for now)");
-	lprint("Unit %d:\r\n", ttyp->unit);
-	lprint("  using %s encapsulation (VJ compression is %s)\r\n", (
-#ifdef USE_PPP
-	       ttyp->proto==PROTO_PPP?"PPP":
-#endif
-	       "SLIP"), buff);
-	lprint("  %d baudrate\r\n", ttyp->baud);
-	lprint("  interface is %s\r\n", ttyp->up?"up":"down");
-	lprint("  using fd %d, guardian pid is %d\r\n", ttyp->fd, ttyp->pid);
-#ifndef FULL_BOLT
-	lprint("  towrite is %d bytes\r\n", ttyp->towrite);
-#endif
-	if (ttyp->zeros)
-	   lprint("  %d zeros have been typed\r\n", ttyp->zeros);
-	else if (ttyp->ones)
-	   lprint("  %d ones have been typed\r\n", ttyp->ones);
-	lprint("Interface stats:\r\n");
-	lprint("  %6d output packets sent (%d bytes)\r\n", is->out_pkts, is->out_bytes);
-	lprint("  %6d output packets dropped (%d bytes)\r\n", is->out_errpkts, is->out_errbytes);
-	lprint("  %6d input packets received (%d bytes)\r\n", is->in_pkts, is->in_bytes);
-	lprint("  %6d input packets dropped (%d bytes)\r\n", is->in_errpkts, is->in_errbytes);
-	lprint("  %6d bad input packets\r\n", is->in_mbad);
-}
-
-static void
-allttystats(void)
-{
-	struct ttys *ttyp;
-
-	for (ttyp = ttys; ttyp; ttyp = ttyp->next)
-	   ttystats(ttyp);
-}
-#endif
-
 static void
 ipstats(void)
 {
@@ -154,25 +36,6 @@ ipstats(void)
 	lprint("  %6d total packets delivered\r\n", ipstat.ips_delivered);
 }
 
-#ifndef CONFIG_QEMU
-static void
-vjstats(void)
-{
-	lprint(" \r\n");
-
-	lprint("VJ compression stats:\r\n");
-
-	lprint("  %6d outbound packets (%d compressed)\r\n",
-	       comp_s.sls_packets, comp_s.sls_compressed);
-	lprint("  %6d searches for connection stats (%d misses)\r\n",
-	       comp_s.sls_searches, comp_s.sls_misses);
-	lprint("  %6d inbound uncompressed packets\r\n", comp_s.sls_uncompressedin);
-	lprint("  %6d inbound compressed packets\r\n", comp_s.sls_compressedin);
-	lprint("  %6d inbound unknown type packets\r\n", comp_s.sls_errorin);
-	lprint("  %6d inbound packets tossed due to error\r\n", comp_s.sls_tossed);
-}
-#endif
-
 static void
 tcpstats(void)
 {
@@ -234,11 +97,6 @@ tcpstats(void)
 	lprint("  %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
 	lprint("  %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
 	lprint("  %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
-
-
-/*	lprint("    Packets received too short:		%d\r\n", tcpstat.tcps_rcvshort); */
-/*	lprint("    Segments dropped due to PAWS:	%d\r\n", tcpstat.tcps_pawsdrop); */
-
 }
 
 static void
@@ -293,49 +151,6 @@ mbufstats(void)
 }
 #endif
 
-#ifndef CONFIG_QEMU
-void
-slirp_exit(exit_status)
-	int exit_status;
-{
-	struct ttys *ttyp;
-
-	DEBUG_CALL("slirp_exit");
-	DEBUG_ARG("exit_status = %d", exit_status);
-
-	if (dostats) {
-		lprint_print = (int (*) _P((void *, const char *, va_list)))vfprintf;
-		if (!dfd)
-		   debug_init("slirp_stats", 0xf);
-		lprint_arg = (char **)&dfd;
-
-		ipstats();
-		tcpstats();
-		udpstats();
-		icmpstats();
-		mbufstats();
-		sockstats();
-		allttystats();
-		vjstats();
-	}
-
-	for (ttyp = ttys; ttyp; ttyp = ttyp->next)
-	   tty_detached(ttyp, 1);
-
-	if (slirp_forked) {
-		/* Menendez time */
-		if (kill(getppid(), SIGQUIT) < 0)
-			lprint("Couldn't kill parent process %ld!\n",
-			    (long) getppid());
-    	}
-
-	/* Restore the terminal if we gotta */
-	if(slirp_tty_restore)
-	  tcsetattr(0,TCSANOW, &slirp_tty_settings);  /* NOW DAMMIT! */
-	exit(exit_status);
-}
-#endif
-
 void
 slirp_stats(void)
 {
diff --git a/slirp/debug.h b/slirp/debug.h
index c43eff7..963ffda 100644
--- a/slirp/debug.h
+++ b/slirp/debug.h
@@ -9,8 +9,6 @@
 #define PRN_SPRINTF	2
 
 extern FILE *dfd;
-extern FILE *lfd;
-extern int dostats;
 extern int slirp_debug;
 
 #define DBG_CALL 0x1
diff --git a/slirp/if.c b/slirp/if.c
index 17f8a73..1ef4bf9 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -36,89 +36,9 @@ if_init(void)
 {
 	if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
 	if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
-        //	sl_compress_init(&comp_s);
 	next_m = &if_batchq;
 }
 
-#if 0
-/*
- * This shouldn't be needed since the modem is blocking and
- * we don't expect any signals, but what the hell..
- */
-inline int
-writen(fd, bptr, n)
-	int fd;
-	char *bptr;
-	int n;
-{
-	int ret;
-	int total;
-
-	/* This should succeed most of the time */
-	ret = send(fd, bptr, n,0);
-	if (ret == n || ret <= 0)
-	   return ret;
-
-	/* Didn't write everything, go into the loop */
-	total = ret;
-	while (n > total) {
-		ret = send(fd, bptr+total, n-total,0);
-		if (ret <= 0)
-		   return ret;
-		total += ret;
-	}
-	return total;
-}
-
-/*
- * if_input - read() the tty, do "top level" processing (ie: check for any escapes),
- * and pass onto (*ttyp->if_input)
- *
- * XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
- */
-#define INBUFF_SIZE 2048 /* XXX */
-void
-if_input(ttyp)
-	struct ttys *ttyp;
-{
-	u_char if_inbuff[INBUFF_SIZE];
-	int if_n;
-
-	DEBUG_CALL("if_input");
-	DEBUG_ARG("ttyp = %lx", (long)ttyp);
-
-	if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0);
-
-	DEBUG_MISC((dfd, " read %d bytes\n", if_n));
-
-	if (if_n <= 0) {
-		if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
-			if (ttyp->up)
-			   link_up--;
-			tty_detached(ttyp, 0);
-		}
-		return;
-	}
-	if (if_n == 1) {
-		if (*if_inbuff == '0') {
-			ttyp->ones = 0;
-			if (++ttyp->zeros >= 5)
-			   slirp_exit(0);
-			return;
-		}
-		if (*if_inbuff == '1') {
-			ttyp->zeros = 0;
-			if (++ttyp->ones >= 5)
-			   tty_detached(ttyp, 0);
-			return;
-		}
-	}
-	ttyp->ones = ttyp->zeros = 0;
-
-	(*ttyp->if_input)(ttyp, if_inbuff, if_n);
-}
-#endif
-
 /*
  * if_output: Queue packet into an output queue.
  * There are 2 output queue's, if_fastq and if_batchq.
diff --git a/slirp/if.h b/slirp/if.h
index bed7152..d49bcd5 100644
--- a/slirp/if.h
+++ b/slirp/if.h
@@ -17,20 +17,8 @@
 #define IF_MRU 1500
 #define	IF_COMP IF_AUTOCOMP	/* Flags for compression */
 
-#if 0
-/*
- * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
- * and 8 bytes for PPP, but need to have it on an 8byte boundary
- */
-#ifdef USE_PPP
-#define IF_MAXLINKHDR 48
-#else
-#define IF_MAXLINKHDR 40
-#endif
-#else
-        /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
+/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
 #define IF_MAXLINKHDR (2 + 14 + 40)
-#endif
 
 extern int	if_queued;	/* Number of packets queued so far */
 
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 6e93ee3..c47ab1f 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -73,7 +73,6 @@ icmp_input(struct mbuf *m, int hlen)
   register struct icmp *icp;
   register struct ip *ip=mtod(m, struct ip *);
   int icmplen=ip->ip_len;
-  /* int code; */
 
   DEBUG_CALL("icmp_input");
   DEBUG_ARG("m = %lx", (long )m);
@@ -102,9 +101,6 @@ icmp_input(struct mbuf *m, int hlen)
   m->m_len += hlen;
   m->m_data -= hlen;
 
-  /*	icmpstat.icps_inhist[icp->icmp_type]++; */
-  /* code = icp->icmp_code; */
-
   DEBUG_ARG("icmp_type = %d", icp->icmp_type);
   switch (icp->icmp_type) {
   case ICMP_ECHO:
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 7a3c88b..1fdd8d6 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -165,16 +165,6 @@ ip_input(struct mbuf *m)
 	}
 
 	/*
-	 * Process options and, if not destined for us,
-	 * ship it on.  ip_dooptions returns 1 when an
-	 * error was detected (causing an icmp message
-	 * to be sent and the original packet to be freed).
-	 */
-/* We do no IP options */
-/*	if (hlen > sizeof (struct ip) && ip_dooptions(m))
- *		goto next;
- */
-	/*
 	 * If offset or IP_MF are set, must reassemble.
 	 * Otherwise, nothing need be done.
 	 * (We could look in the reassembly queue to see
@@ -396,9 +386,6 @@ insert:
 	  q = (struct ipasfrag *)(m->m_ext + delta);
 	}
 
-	/* DEBUG_ARG("ip = %lx", (long)ip);
-	 * ip=(struct ipasfrag *)m->m_data; */
-
     ip = fragtoip(q);
 	ip->ip_len = next;
 	ip->ip_tos &= ~1;
@@ -505,7 +492,6 @@ ip_dooptions(m)
 	register u_char *cp;
 	register struct ip_timestamp *ipt;
 	register struct in_ifaddr *ia;
-/*	int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */
 	int opt, optlen, cnt, off, code, type, forward = 0;
 	struct in_addr *sin, dst;
 typedef u_int32_t n_time;
@@ -683,9 +669,6 @@ typedef u_int32_t n_time;
 	}
 	return (0);
 bad:
-	/* ip->ip_len -= ip->ip_hl << 2;   XXX icmp_error adds in hdr length */
-
-/* Not yet */
  	icmp_error(m, type, code, 0, 0);
 
 	STAT(ipstat.ips_badoptions++);
diff --git a/slirp/ip_output.c b/slirp/ip_output.c
index 5bce520..94bb0f2 100644
--- a/slirp/ip_output.c
+++ b/slirp/ip_output.c
@@ -64,12 +64,6 @@ ip_output(struct socket *so, struct mbuf *m0)
 	DEBUG_ARG("so = %lx", (long)so);
 	DEBUG_ARG("m0 = %lx", (long)m0);
 
-	/* We do no options */
-/*	if (opt) {
- *		m = ip_insertoptions(m, opt, &len);
- *		hlen = len;
- *	}
- */
 	ip = mtod(m, struct ip *);
 	/*
 	 * Fill in IP header.
@@ -81,17 +75,6 @@ ip_output(struct socket *so, struct mbuf *m0)
 	STAT(ipstat.ips_localout++);
 
 	/*
-	 * Verify that we have any chance at all of being able to queue
-	 *      the packet or packet fragments
-	 */
-	/* XXX Hmmm... */
-/*	if (if_queued > IF_THRESH && towrite <= 0) {
- *		error = ENOBUFS;
- *		goto bad;
- *	}
- */
-
-	/*
 	 * If small enough for interface, can just send directly.
 	 */
 	if ((u_int16_t)ip->ip_len <= IF_MTU) {
@@ -142,12 +125,6 @@ ip_output(struct socket *so, struct mbuf *m0)
 	  mhip = mtod(m, struct ip *);
 	  *mhip = *ip;
 
-		/* No options */
-/*		if (hlen > sizeof (struct ip)) {
- *			mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
- *			mhip->ip_hl = mhlen >> 2;
- *		}
- */
 	  m->m_len = mhlen;
 	  mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
 	  if (ip->ip_off & IP_MF)
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 5c7a8e9..c48837c 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -1,10 +1,6 @@
 #ifndef _LIBSLIRP_H
 #define _LIBSLIRP_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #include <qemu-common.h>
 
 void slirp_init(int restricted, struct in_addr vnetwork,
@@ -37,8 +33,4 @@ void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
                        const uint8_t *buf, int size);
 size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index 1d30a63..7963d34 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -141,17 +141,11 @@ m_inc(struct mbuf *m, int size)
         if (m->m_flags & M_EXT) {
 	  datasize = m->m_data - m->m_ext;
 	  m->m_ext = (char *)realloc(m->m_ext,size);
-/*		if (m->m_ext == NULL)
- *			return (struct mbuf *)NULL;
- */
 	  m->m_data = m->m_ext + datasize;
         } else {
 	  char *dat;
 	  datasize = m->m_data - m->m_dat;
 	  dat = (char *)malloc(size);
-/*		if (dat == NULL)
- *			return (struct mbuf *)NULL;
- */
 	  memcpy(dat, m->m_dat, m->m_size);
 
 	  m->m_ext = dat;
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index 5527373..e259441 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -41,10 +41,8 @@
 /*
  * Macros for type conversion
  * mtod(m,t) -	convert mbuf pointer to data pointer of correct type
- * dtom(x) -	convert data pointer within mbuf to mbuf pointer (XXX)
  */
 #define mtod(m,t)	((t)(m)->m_data)
-/* #define	dtom(x)		((struct mbuf *)((int)(x) & ~(M_SIZE-1))) */
 
 /* XXX About mbufs for slirp:
  * Only one mbuf is ever used in a chain, for each "cell" of data.
diff --git a/slirp/misc.c b/slirp/misc.c
index 8d03f79..9587112 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -12,62 +12,6 @@
 
 u_int curtime, time_fasttimo, last_slowtimo;
 
-#if 0
-int x_port = -1;
-int x_display = 0;
-int x_screen = 0;
-
-int
-show_x(buff, inso)
-	char *buff;
-	struct socket *inso;
-{
-	if (x_port < 0) {
-		lprint("X Redir: X not being redirected.\r\n");
-	} else {
-		lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
-		      inet_ntoa(our_addr), x_port, x_screen);
-		lprint("X Redir: In csh/tcsh/etc. type:    setenv DISPLAY %s:%d.%d\r\n",
-		      inet_ntoa(our_addr), x_port, x_screen);
-		if (x_display)
-		   lprint("X Redir: Redirecting to display %d\r\n", x_display);
-	}
-
-	return CFG_OK;
-}
-
-
-/*
- * XXX Allow more than one X redirection?
- */
-void
-redir_x(inaddr, start_port, display, screen)
-	u_int32_t inaddr;
-	int start_port;
-	int display;
-	int screen;
-{
-	int i;
-
-	if (x_port >= 0) {
-		lprint("X Redir: X already being redirected.\r\n");
-		show_x(0, 0);
-	} else {
-		for (i = 6001 + (start_port-1); i <= 6100; i++) {
-			if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
-				/* Success */
-				x_port = i - 6000;
-				x_display = display;
-				x_screen = screen;
-				show_x(0, 0);
-				return;
-			}
-		}
-		lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
-	}
-}
-#endif
-
 /*
  * Get our IP address and put it in our_addr
  */
@@ -109,12 +53,8 @@ remque(void *a)
   ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
   ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
   element->qh_rlink = NULL;
-  /*  element->qh_link = NULL;  TCP FIN1 crashes if you do this.  Why ? */
 }
 
-/* #endif */
-
-
 int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec,
              struct in_addr addr, int port)
 {
@@ -170,73 +110,6 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 
 #else
 
-#ifndef CONFIG_QEMU
-int
-slirp_openpty(amaster, aslave)
-     int *amaster, *aslave;
-{
-	register int master, slave;
-
-#ifdef HAVE_GRANTPT
-	char *ptr;
-
-	if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
-	    grantpt(master) < 0 ||
-	    unlockpt(master) < 0 ||
-	    (ptr = ptsname(master)) == NULL)  {
-		close(master);
-		return -1;
-	}
-
-	if ((slave = open(ptr, O_RDWR)) < 0 ||
-	    ioctl(slave, I_PUSH, "ptem") < 0 ||
-	    ioctl(slave, I_PUSH, "ldterm") < 0 ||
-	    ioctl(slave, I_PUSH, "ttcompat") < 0) {
-		close(master);
-		close(slave);
-		return -1;
-	}
-
-	*amaster = master;
-	*aslave = slave;
-	return 0;
-
-#else
-
-	static char line[] = "/dev/ptyXX";
-	register const char *cp1, *cp2;
-
-	for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
-		line[8] = *cp1;
-		for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
-			line[9] = *cp2;
-			if ((master = open(line, O_RDWR, 0)) == -1) {
-				if (errno == ENOENT)
-				   return (-1);    /* out of ptys */
-			} else {
-				line[5] = 't';
-				/* These will fail */
-				(void) chown(line, getuid(), 0);
-				(void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
-#ifdef HAVE_REVOKE
-				(void) revoke(line);
-#endif
-				if ((slave = open(line, O_RDWR, 0)) != -1) {
-					*amaster = master;
-					*aslave = slave;
-					return 0;
-				}
-				(void) close(master);
-				line[5] = 'p';
-			}
-		}
-	}
-	errno = ENOENT; /* out of ptys */
-	return (-1);
-#endif
-}
-#endif
-
 /*
  * XXX This is ugly
  * We create and bind a socket, then fork off to another
@@ -257,9 +130,6 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 	int opt;
         int master = -1;
 	const char *argv[256];
-#if 0
-	char buff[256];
-#endif
 	/* don't want to clobber the original */
 	char *bptr;
 	const char *curarg;
@@ -271,14 +141,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
 	DEBUG_ARG("do_pty = %lx", (long)do_pty);
 
 	if (do_pty == 2) {
-#if 0
-		if (slirp_openpty(&master, &s) == -1) {
-			lprint("Error: openpty failed: %s\n", strerror(errno));
-			return 0;
-		}
-#else
                 return 0;
-#endif
 	} else {
 		addr.sin_family = AF_INET;
 		addr.sin_port = 0;
@@ -324,17 +187,6 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
                         } while (ret < 0 && errno == EINTR);
 		}
 
-#if 0
-		if (x_port >= 0) {
-#ifdef HAVE_SETENV
-			sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
-			setenv("DISPLAY", buff, 1);
-#else
-			sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
-			putenv(buff);
-#endif
-		}
-#endif
 		dup2(s, 0);
 		dup2(s, 1);
 		dup2(s, 2);
@@ -422,137 +274,6 @@ strdup(str)
 }
 #endif
 
-#if 0
-void
-snooze_hup(num)
-	int num;
-{
-	int s, ret;
-#ifndef NO_UNIX_SOCKETS
-	struct sockaddr_un sock_un;
-#endif
-	struct sockaddr_in sock_in;
-	char buff[256];
-
-	ret = -1;
-	if (slirp_socket_passwd) {
-		s = socket(AF_INET, SOCK_STREAM, 0);
-		if (s < 0)
-		   slirp_exit(1);
-		sock_in.sin_family = AF_INET;
-		sock_in.sin_addr.s_addr = slirp_socket_addr;
-		sock_in.sin_port = htons(slirp_socket_port);
-		if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
-		   slirp_exit(1); /* just exit...*/
-		sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
-		write(s, buff, strlen(buff)+1);
-	}
-#ifndef NO_UNIX_SOCKETS
-	  else {
-		s = socket(AF_UNIX, SOCK_STREAM, 0);
-		if (s < 0)
-		   slirp_exit(1);
-		sock_un.sun_family = AF_UNIX;
-		strcpy(sock_un.sun_path, socket_path);
-		if (connect(s, (struct sockaddr *)&sock_un,
-			      sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
-		   slirp_exit(1);
-		sprintf(buff, "kill none:%d", slirp_socket_unit);
-		write(s, buff, strlen(buff)+1);
-	}
-#endif
-	slirp_exit(0);
-}
-
-
-void
-snooze()
-{
-	sigset_t s;
-	int i;
-
-	/* Don't need our data anymore */
-	/* XXX This makes SunOS barf */
-/*	brk(0); */
-
-	/* Close all fd's */
-	for (i = 255; i >= 0; i--)
-	   close(i);
-
-	signal(SIGQUIT, slirp_exit);
-	signal(SIGHUP, snooze_hup);
-	sigemptyset(&s);
-
-	/* Wait for any signal */
-	sigsuspend(&s);
-
-	/* Just in case ... */
-	exit(255);
-}
-
-void
-relay(s)
-	int s;
-{
-	char buf[8192];
-	int n;
-	fd_set readfds;
-	struct ttys *ttyp;
-
-	/* Don't need our data anymore */
-	/* XXX This makes SunOS barf */
-/*	brk(0); */
-
-	signal(SIGQUIT, slirp_exit);
-	signal(SIGHUP, slirp_exit);
-        signal(SIGINT, slirp_exit);
-	signal(SIGTERM, slirp_exit);
-
-	/* Fudge to get term_raw and term_restore to work */
-	if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
-         lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
-         slirp_exit (1);
-    }
-	ttyp->fd = 0;
-	ttyp->flags |= TTY_CTTY;
-	term_raw(ttyp);
-
-	while (1) {
-		FD_ZERO(&readfds);
-
-		FD_SET(0, &readfds);
-		FD_SET(s, &readfds);
-
-		n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
-
-		if (n <= 0)
-		   slirp_exit(0);
-
-		if (FD_ISSET(0, &readfds)) {
-			n = read(0, buf, 8192);
-			if (n <= 0)
-			   slirp_exit(0);
-			n = writen(s, buf, n);
-			if (n <= 0)
-			   slirp_exit(0);
-		}
-
-		if (FD_ISSET(s, &readfds)) {
-			n = read(s, buf, 8192);
-			if (n <= 0)
-			   slirp_exit(0);
-			n = writen(0, buf, n);
-			if (n <= 0)
-			   slirp_exit(0);
-		}
-	}
-
-	/* Just in case.... */
-	exit(1);
-}
-#endif
-
-#ifdef CONFIG_QEMU
 #include "monitor.h"
 
 void lprint(const char *format, ...)
@@ -563,159 +284,6 @@ void lprint(const char *format, ...)
     monitor_vprintf(cur_mon, format, args);
     va_end(args);
 }
-#else
-int (*lprint_print) _P((void *, const char *, va_list));
-char *lprint_ptr, *lprint_ptr2, **lprint_arg;
-
-void
-#ifdef __STDC__
-lprint(const char *format, ...)
-#else
-lprint(va_alist) va_dcl
-#endif
-{
-	va_list args;
-
-#ifdef __STDC__
-        va_start(args, format);
-#else
-        char *format;
-        va_start(args);
-        format = va_arg(args, char *);
-#endif
-#if 0
-	/* If we're printing to an sbuf, make sure there's enough room */
-	/* XXX +100? */
-	if (lprint_sb) {
-		if ((lprint_ptr - lprint_sb->sb_wptr) >=
-		    (lprint_sb->sb_datalen - (strlen(format) + 100))) {
-			int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
-			int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
-			int deltap = lprint_ptr -         lprint_sb->sb_data;
-
-			lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
-							     lprint_sb->sb_datalen + TCP_SNDSPACE);
-
-			/* Adjust all values */
-			lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
-			lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
-			lprint_ptr =         lprint_sb->sb_data + deltap;
-
-			lprint_sb->sb_datalen += TCP_SNDSPACE;
-		}
-	}
-#endif
-	if (lprint_print)
-	   lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
-
-	/* Check if they want output to be logged to file as well */
-	if (lfd) {
-		/*
-		 * Remove \r's
-		 * otherwise you'll get ^M all over the file
-		 */
-		int len = strlen(format);
-		char *bptr1, *bptr2;
-
-		bptr1 = bptr2 = strdup(format);
-
-		while (len--) {
-			if (*bptr1 == '\r')
-			   memcpy(bptr1, bptr1+1, len+1);
-			else
-			   bptr1++;
-		}
-		vfprintf(lfd, bptr2, args);
-		free(bptr2);
-	}
-	va_end(args);
-}
-
-void
-add_emu(buff)
-	char *buff;
-{
-	u_int lport, fport;
-	u_int8_t tos = 0, emu = 0;
-	char buff1[256], buff2[256], buff4[128];
-	char *buff3 = buff4;
-	struct emu_t *emup;
-	struct socket *so;
-
-	if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
-		lprint("Error: Bad arguments\r\n");
-		return;
-	}
-
-	if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
-		lport = 0;
-		if (sscanf(buff1, "%d", &fport) != 1) {
-			lprint("Error: Bad first argument\r\n");
-			return;
-		}
-	}
-
-	if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
-		buff3 = 0;
-		if (sscanf(buff2, "%256s", buff1) != 1) {
-			lprint("Error: Bad second argument\r\n");
-			return;
-		}
-	}
-
-	if (buff3) {
-		if (strcmp(buff3, "lowdelay") == 0)
-		   tos = IPTOS_LOWDELAY;
-		else if (strcmp(buff3, "throughput") == 0)
-		   tos = IPTOS_THROUGHPUT;
-		else {
-			lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
-			return;
-		}
-	}
-
-	if (strcmp(buff1, "ftp") == 0)
-	   emu = EMU_FTP;
-	else if (strcmp(buff1, "irc") == 0)
-	   emu = EMU_IRC;
-	else if (strcmp(buff1, "none") == 0)
-	   emu = EMU_NONE; /* ie: no emulation */
-	else {
-		lprint("Error: Unknown service\r\n");
-		return;
-	}
-
-	/* First, check that it isn't already emulated */
-	for (emup = tcpemu; emup; emup = emup->next) {
-		if (emup->lport == lport && emup->fport == fport) {
-			lprint("Error: port already emulated\r\n");
-			return;
-		}
-	}
-
-	/* link it */
-	emup = (struct emu_t *)malloc(sizeof (struct emu_t));
-	emup->lport = (u_int16_t)lport;
-	emup->fport = (u_int16_t)fport;
-	emup->tos = tos;
-	emup->emu = emu;
-	emup->next = tcpemu;
-	tcpemu = emup;
-
-	/* And finally, mark all current sessions, if any, as being emulated */
-	for (so = tcb.so_next; so != &tcb; so = so->so_next) {
-		if ((lport && lport == ntohs(so->so_lport)) ||
-		    (fport && fport == ntohs(so->so_fport))) {
-			if (emu)
-			   so->so_emu = emu;
-			if (tos)
-			   so->so_iptos = tos;
-		}
-	}
-
-	lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
-}
-#endif
 
 #ifdef BAD_SPRINTF
 
@@ -817,99 +385,6 @@ fd_block(int fd)
 #endif
 }
 
-
-#if 0
-/*
- * invoke RSH
- */
-int
-rsh_exec(so,ns, user, host, args)
-	struct socket *so;
-	struct socket *ns;
-	char *user;
-	char *host;
-	char *args;
-{
-	int fd[2];
-	int fd0[2];
-	int s;
-	char buff[256];
-
-	DEBUG_CALL("rsh_exec");
-	DEBUG_ARG("so = %lx", (long)so);
-
-	if (pipe(fd)<0) {
-          lprint("Error: pipe failed: %s\n", strerror(errno));
-          return 0;
-	}
-/* #ifdef HAVE_SOCKETPAIR */
-#if 1
-        if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
-          close(fd[0]);
-          close(fd[1]);
-          lprint("Error: openpty failed: %s\n", strerror(errno));
-          return 0;
-        }
-#else
-        if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
-          close(fd[0]);
-          close(fd[1]);
-          lprint("Error: openpty failed: %s\n", strerror(errno));
-          return 0;
-        }
-#endif
-
-	switch(fork()) {
-	 case -1:
-           lprint("Error: fork failed: %s\n", strerror(errno));
-           close(fd[0]);
-           close(fd[1]);
-           close(fd0[0]);
-           close(fd0[1]);
-           return 0;
-
-	 case 0:
-           close(fd[0]);
-           close(fd0[0]);
-
-		/* Set the DISPLAY */
-           if (x_port >= 0) {
-#ifdef HAVE_SETENV
-             sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
-             setenv("DISPLAY", buff, 1);
-#else
-             sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
-             putenv(buff);
-#endif
-           }
-
-           dup2(fd0[1], 0);
-           dup2(fd0[1], 1);
-           dup2(fd[1], 2);
-           for (s = 3; s <= 255; s++)
-             close(s);
-
-           execlp("rsh","rsh","-l", user, host, args, NULL);
-
-           /* Ooops, failed, let's tell the user why */
-
-           sprintf(buff, "Error: execlp of %s failed: %s\n",
-                   "rsh", strerror(errno));
-           write(2, buff, strlen(buff)+1);
-           close(0); close(1); close(2); /* XXX */
-           exit(1);
-
-        default:
-          close(fd[1]);
-          close(fd0[1]);
-          ns->s=fd[0];
-          so->s=fd0[0];
-
-          return 1;
-	}
-}
-#endif
-
 void slirp_connection_info(Monitor *mon)
 {
     const char * const tcpstates[] = {
diff --git a/slirp/misc.h b/slirp/misc.h
index 29d5749..82dd596 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -19,10 +19,6 @@ struct ex_list {
 extern struct ex_list *exec_list;
 extern u_int time_fasttimo, last_slowtimo;
 
-extern int (*lprint_print) _P((void *, const char *, va_list));
-extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
-extern struct sbuf *lprint_sb;
-
 #ifndef HAVE_STRDUP
 char *strdup _P((const char *));
 #endif
@@ -63,10 +59,6 @@ struct emu_t {
 	struct emu_t *next;
 };
 
-#ifndef CONFIG_QEMU
-extern struct emu_t *tcpemu;
-#endif
-
 extern int x_port, x_server, x_display;
 
 int show_x _P((char *, struct socket *));
diff --git a/slirp/sbuf.c b/slirp/sbuf.c
index 5375414..5a1ccbf 100644
--- a/slirp/sbuf.c
+++ b/slirp/sbuf.c
@@ -9,14 +9,6 @@
 
 static void sbappendsb(struct sbuf *sb, struct mbuf *m);
 
-/* Done as a macro in socket.h */
-/* int
- * sbspace(struct sockbuff *sb)
- * {
- *	return SB_DATALEN - sb->sb_cc;
- * }
- */
-
 void
 sbfree(struct sbuf *sb)
 {
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 35de4e3..44a53cd 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -55,7 +55,6 @@ int slirp_restrict;
 static int do_slowtimo;
 int link_up;
 struct timeval tt;
-FILE *lfd;
 struct ex_list *exec_list;
 
 /* XXX: suppress those select globals */
@@ -96,16 +95,6 @@ static int get_dns_addr(struct in_addr *pdns_addr)
     pIPAddr = &(FixedInfo->DnsServerList);
     inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
     *pdns_addr = tmp_addr;
-#if 0
-    printf( "DNS Servers:\n" );
-    printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
-
-    pIPAddr = FixedInfo -> DnsServerList.Next;
-    while ( pIPAddr ) {
-            printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
-            pIPAddr = pIPAddr ->Next;
-    }
-#endif
     if (FixedInfo) {
         GlobalFree(FixedInfo);
         FixedInfo = NULL;
@@ -179,8 +168,6 @@ void slirp_init(int restricted, struct in_addr vnetwork,
                 const char *bootfile, struct in_addr vdhcp_start,
                 struct in_addr vnameserver)
 {
-    //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
-
 #ifdef _WIN32
     WSADATA Data;
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 101d094..0c62fd7 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -1,8 +1,6 @@
 #ifndef __COMMON_H__
 #define __COMMON_H__
 
-#define CONFIG_QEMU
-
 //#define DEBUG 1
 
 // Uncomment the following line to enable SLIRP statistics printing in Qemu
@@ -14,9 +12,6 @@
 #define STAT(expr) do { } while(0)
 #endif
 
-#ifndef CONFIG_QEMU
-#include "version.h"
-#endif
 #include "config-host.h"
 #include "slirp_config.h"
 
@@ -223,8 +218,6 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 #include "tftp.h"
 #include "libslirp.h"
 
-extern struct ttys *ttys_unit[MAX_INTERFACES];
-
 #ifndef NULL
 #define NULL (void *)0
 #endif
diff --git a/slirp/socket.c b/slirp/socket.c
index 6b3da0a..a911b29 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -15,14 +15,6 @@
 static void sofcantrcvmore(struct socket *so);
 static void sofcantsendmore(struct socket *so);
 
-#if 0
-static void
-so_init()
-{
-	/* Nothing yet */
-}
-#endif
-
 struct socket *
 solookup(struct socket *head, struct in_addr laddr, u_int lport,
          struct in_addr faddr, u_int fport)
@@ -526,12 +518,6 @@ sorecvfrom(struct socket *so)
 		so->so_expire = curtime + SO_EXPIRE;
 	    }
 
-	    /*		if (m->m_len == len) {
-	     *			m_inc(m, MINCSIZE);
-	     *			m->m_len = 0;
-	     *		}
-	     */
-
 	    /*
 	     * If this packet was destined for CTL_ADDR,
 	     * make it look like that's where it came from, done by udp_output
@@ -604,7 +590,6 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags
 	DEBUG_ARG("flags = %x", flags);
 
 	if ((so = socreate()) == NULL) {
-	  /* free(so);      Not sofree() ??? free(NULL) == NOP */
 	  return NULL;
 	}
 
@@ -659,33 +644,6 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags
 	return so;
 }
 
-#if 0
-/*
- * Data is available in so_rcv
- * Just write() the data to the socket
- * XXX not yet...
- */
-static void
-sorwakeup(so)
-	struct socket *so;
-{
-/*	sowrite(so); */
-/*	FD_CLR(so->s,&writefds); */
-}
-
-/*
- * Data has been freed in so_snd
- * We have room for a read() if we want to
- * For now, don't read, it'll be done in the main loop
- */
-static void
-sowwakeup(so)
-	struct socket *so;
-{
-	/* Nothing, yet */
-}
-#endif
-
 /*
  * Various session state calls
  * XXX Should be #define's
@@ -746,17 +704,6 @@ sofcantsendmore(struct socket *so)
 	}
 }
 
-void
-soisfdisconnected(struct socket *so)
-{
-/*	so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
-/*	close(so->s); */
-/*	so->so_state = SS_ISFDISCONNECTED; */
-	/*
-	 * XXX Do nothing ... ?
-	 */
-}
-
 /*
  * Set write drain mode
  * Set CANTSENDMORE once all data has been write()n
diff --git a/slirp/socket.h b/slirp/socket.h
index d241a48..4db2147 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -5,8 +5,6 @@
  * terms and conditions of the copyright.
  */
 
-/* MINE */
-
 #ifndef _SLIRP_SOCKET_H_
 #define _SLIRP_SOCKET_H_
 
@@ -64,7 +62,6 @@ struct socket {
 #define SS_ISFCONNECTED		0x004	/* Socket is connected to peer */
 #define SS_FCANTRCVMORE		0x008	/* Socket can't receive more from peer (for half-closes) */
 #define SS_FCANTSENDMORE	0x010	/* Socket can't send more to peer (for half-closes) */
-/* #define SS_ISFDISCONNECTED	0x020*/	/* Socket has disconnected from peer, in 2MSL state */
 #define SS_FWDRAIN		0x040	/* We received a FIN, drain data and set SS_FCANTSENDMORE */
 
 #define SS_CTL			0x080
@@ -89,7 +86,6 @@ int sosendto _P((struct socket *, struct mbuf *));
 struct socket * tcp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
 void soisfconnecting _P((register struct socket *));
 void soisfconnected _P((register struct socket *));
-void soisfdisconnected _P((struct socket *));
 void sofwdrain _P((struct socket *));
 struct iovec; /* For win32 */
 size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);
diff --git a/slirp/tcp.h b/slirp/tcp.h
index 3399857..4a18ed8 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -113,7 +113,6 @@ struct tcphdr {
 #undef TCP_NODELAY
 #define	TCP_NODELAY	0x01	/* don't delay send to coalesce packets */
 #undef TCP_MAXSEG
-/* #define	TCP_MAXSEG	0x02 */	/* set maximum segment size */
 
 /*
  * TCP FSM state definitions.
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 8789303..980ae06 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -81,7 +81,6 @@ tcp_seq tcp_iss;                /* tcp initial send seq # */
 		       if (tcp_emu((so),(m))) sbappend((so), (m)); \
 	       } else \
 	       	       sbappend((so), (m)); \
-/*               sorwakeup(so); */ \
 	} else {\
                (flags) = tcp_reass((tp), (ti), (m)); \
                tp->t_flags |= TF_ACKNOW; \
@@ -101,7 +100,6 @@ tcp_seq tcp_iss;                /* tcp initial send seq # */
 			if (tcp_emu((so),(m))) sbappend(so, (m)); \
 		} else \
 			sbappend((so), (m)); \
-/*		sorwakeup(so); */ \
 	} else { \
 		(flags) = tcp_reass((tp), (ti), (m)); \
 		tp->t_flags |= TF_ACKNOW; \
@@ -211,7 +209,6 @@ present:
 		remque(tcpiphdr2qlink(ti));
 		m = ti->ti_mbuf;
 		ti = tcpiphdr_next(ti);
-/*		if (so->so_state & SS_FCANTRCVMORE) */
 		if (so->so_state & SS_FCANTSENDMORE)
 			m_freem(m);
 		else {
@@ -221,7 +218,6 @@ present:
 				sbappend(so, m);
 		}
 	} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
-/*	sorwakeup(so); */
 	return (flags);
 }
 
@@ -241,11 +237,9 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	register int tiflags;
         struct socket *so = NULL;
 	int todrop, acked, ourfinisacked, needoutput = 0;
-/*	int dropsocket = 0; */
 	int iss = 0;
 	u_long tiwin;
 	int ret;
-/*	int ts_present = 0; */
     struct ex_list *ex_ptr;
 
 	DEBUG_CALL("tcp_input");
@@ -300,9 +294,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	ti->ti_x1 = 0;
 	ti->ti_len = htons((u_int16_t)tlen);
 	len = sizeof(struct ip ) + tlen;
-	/* keep checksum for ICMP reply
-	 * ti->ti_sum = cksum(m, len);
-	 * if (ti->ti_sum) { */
 	if(cksum(m, len)) {
 	  STAT(tcpstat.tcps_rcvbadsum++);
 	  goto drop;
@@ -322,25 +313,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	if (off > sizeof (struct tcphdr)) {
 	  optlen = off - sizeof (struct tcphdr);
 	  optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
-
-		/*
-		 * Do quick retrieval of timestamp options ("options
-		 * prediction?").  If timestamp is the only option and it's
-		 * formatted as recommended in RFC 1323 appendix A, we
-		 * quickly get the values now and not bother calling
-		 * tcp_dooptions(), etc.
-		 */
-/*		if ((optlen == TCPOLEN_TSTAMP_APPA ||
- *		     (optlen > TCPOLEN_TSTAMP_APPA &&
- *			optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) &&
- *		     *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) &&
- *		     (ti->ti_flags & TH_SYN) == 0) {
- *			ts_present = 1;
- *			ts_val = ntohl(*(u_int32_t *)(optp + 4));
- *			ts_ecr = ntohl(*(u_int32_t *)(optp + 8));
- *			optp = NULL;   / * we've parsed the options * /
- *		}
- */
 	}
 	tiflags = ti->ti_flags;
 
@@ -411,9 +383,6 @@ findso:
 	  sbreserve(&so->so_snd, TCP_SNDSPACE);
 	  sbreserve(&so->so_rcv, TCP_RCVSPACE);
 
-	  /*		tcp_last_so = so; */  /* XXX ? */
-	  /*		tp = sototcpcb(so);    */
-
 	  so->so_laddr = ti->ti_src;
 	  so->so_lport = ti->ti_sport;
 	  so->so_faddr = ti->ti_dst;
@@ -442,12 +411,7 @@ findso:
 	if (tp->t_state == TCPS_CLOSED)
 		goto drop;
 
-	/* Unscale the window into a 32-bit value. */
-/*	if ((tiflags & TH_SYN) == 0)
- *		tiwin = ti->ti_win << tp->snd_scale;
- *	else
- */
-		tiwin = ti->ti_win;
+	tiwin = ti->ti_win;
 
 	/*
 	 * Segment received on connection.
@@ -465,8 +429,6 @@ findso:
 	 */
 	if (optp && tp->t_state != TCPS_LISTEN)
 		tcp_dooptions(tp, (u_char *)optp, optlen, ti);
-/* , */
-/*			&ts_present, &ts_val, &ts_ecr); */
 
 	/*
 	 * Header prediction: check for the two common cases
@@ -488,20 +450,9 @@ findso:
 	 */
 	if (tp->t_state == TCPS_ESTABLISHED &&
 	    (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
-/*	    (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */
 	    ti->ti_seq == tp->rcv_nxt &&
 	    tiwin && tiwin == tp->snd_wnd &&
 	    tp->snd_nxt == tp->snd_max) {
-		/*
-		 * If last ACK falls within this segment's sequence numbers,
-		 *  record the timestamp.
-		 */
-/*		if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
- *		   SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) {
- *			tp->ts_recent_age = tcp_now;
- *			tp->ts_recent = ts_val;
- *		}
- */
 		if (ti->ti_len == 0) {
 			if (SEQ_GT(ti->ti_ack, tp->snd_una) &&
 			    SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
@@ -510,11 +461,8 @@ findso:
 				 * this is a pure ack for outstanding data.
 				 */
 				STAT(tcpstat.tcps_predack++);
-/*				if (ts_present)
- *					tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
- *				else
- */				     if (tp->t_rtt &&
-					    SEQ_GT(ti->ti_ack, tp->t_rtseq))
+				if (tp->t_rtt &&
+				    SEQ_GT(ti->ti_ack, tp->t_rtseq))
 					tcp_xmit_timer(tp, tp->t_rtt);
 				acked = ti->ti_ack - tp->snd_una;
 				STAT(tcpstat.tcps_rcvackpack++);
@@ -538,13 +486,6 @@ findso:
 					tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
 
 				/*
-				 * There's room in so_snd, sowwakup will read()
-				 * from the socket if we can
-				 */
-/*				if (so->so_snd.sb_flags & SB_NOTIFY)
- *					sowwakeup(so);
- */
-				/*
 				 * This is called because sowwakeup might have
 				 * put data into so_snd.  Since we don't so sowwakeup,
 				 * we don't need this.. XXX???
@@ -575,13 +516,6 @@ findso:
 				sbappend(so, m);
 
 			/*
-			 * XXX This is called when data arrives.  Later, check
-			 * if we can actually write() to the socket
-			 * XXX Need to check? It's be NON_BLOCKING
-			 */
-/*			sorwakeup(so); */
-
-			/*
 			 * If this is a short packet, then ACK now - with Nagel
 			 *	congestion avoidance sender won't send more until
 			 *	he gets an ACK.
@@ -644,13 +578,6 @@ findso:
 	      vnetwork_addr.s_addr) {
 	    if (so->so_faddr.s_addr != vhost_addr.s_addr &&
 		so->so_faddr.s_addr != vnameserver_addr.s_addr) {
-#if 0
-	      if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) {
-		/* Command or exec adress */
-		so->so_state |= SS_CTL;
-	      } else
-#endif
-              {
 		/* May be an add exec */
 		for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
 		  if(ex_ptr->ex_fport == so->so_fport &&
@@ -659,8 +586,9 @@ findso:
 		    break;
 		  }
 		}
-	      }
-	      if(so->so_state & SS_CTL) goto cont_input;
+		if (so->so_state & SS_CTL) {
+		    goto cont_input;
+		}
 	    }
 	    /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */
 	  }
@@ -718,8 +646,6 @@ findso:
 
 	  if (optp)
 	    tcp_dooptions(tp, (u_char *)optp, optlen, ti);
-	  /* , */
-	  /*				&ts_present, &ts_val, &ts_ecr); */
 
 	  if (iss)
 	    tp->iss = iss;
@@ -777,13 +703,6 @@ findso:
 			soisfconnected(so);
 			tp->t_state = TCPS_ESTABLISHED;
 
-			/* Do window scaling on this connection? */
-/*			if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
- *				(TF_RCVD_SCALE|TF_REQ_SCALE)) {
- * 				tp->snd_scale = tp->requested_s_scale;
- *				tp->rcv_scale = tp->request_r_scale;
- *			}
- */
 			(void) tcp_reass(tp, (struct tcpiphdr *)0,
 				(struct mbuf *)0);
 			/*
@@ -816,40 +735,10 @@ trimthenstep6:
 	} /* switch tp->t_state */
 	/*
 	 * States other than LISTEN or SYN_SENT.
-	 * First check timestamp, if present.
-	 * Then check that at least some bytes of segment are within
+	 * Check that at least some bytes of segment are within
 	 * receive window.  If segment begins before rcv_nxt,
 	 * drop leading data (and SYN); if nothing left, just ack.
-	 *
-	 * RFC 1323 PAWS: If we have a timestamp reply on this segment
-	 * and it's less than ts_recent, drop it.
 	 */
-/*	if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent &&
- *	    TSTMP_LT(ts_val, tp->ts_recent)) {
- *
- */		/* Check to see if ts_recent is over 24 days old.  */
-/*		if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
- */			/*
- *			 * Invalidate ts_recent.  If this segment updates
- *			 * ts_recent, the age will be reset later and ts_recent
- *			 * will get a valid value.  If it does not, setting
- *			 * ts_recent to zero will at least satisfy the
- *			 * requirement that zero be placed in the timestamp
- *			 * echo reply when ts_recent isn't valid.  The
- *			 * age isn't reset until we get a valid ts_recent
- *			 * because we don't want out-of-order segments to be
- *			 * dropped when ts_recent is old.
- *			 */
-/*			tp->ts_recent = 0;
- *		} else {
- *			tcpstat.tcps_rcvduppack++;
- *			tcpstat.tcps_rcvdupbyte += ti->ti_len;
- *			tcpstat.tcps_pawsdrop++;
- *			goto dropafterack;
- *		}
- *	}
- */
-
 	todrop = tp->rcv_nxt - ti->ti_seq;
 	if (todrop > 0) {
 		if (tiflags & TH_SYN) {
@@ -948,18 +837,6 @@ trimthenstep6:
 	}
 
 	/*
-	 * If last ACK falls within this segment's sequence numbers,
-	 * record its timestamp.
-	 */
-/*	if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
- *	    SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len +
- *		   ((tiflags & (TH_SYN|TH_FIN)) != 0))) {
- *		tp->ts_recent_age = tcp_now;
- *		tp->ts_recent = ts_val;
- *	}
- */
-
-	/*
 	 * If the RST bit is set examine the state:
 	 *    SYN_RECEIVED STATE:
 	 *	If passive open, return to LISTEN state.
@@ -972,15 +849,10 @@ trimthenstep6:
 	if (tiflags&TH_RST) switch (tp->t_state) {
 
 	case TCPS_SYN_RECEIVED:
-/*		so->so_error = ECONNREFUSED; */
-		goto close;
-
 	case TCPS_ESTABLISHED:
 	case TCPS_FIN_WAIT_1:
 	case TCPS_FIN_WAIT_2:
 	case TCPS_CLOSE_WAIT:
-/*		so->so_error = ECONNRESET; */
-	close:
 		tp->t_state = TCPS_CLOSED;
 		STAT(tcpstat.tcps_drops++);
 		tp = tcp_close(tp);
@@ -1048,13 +920,6 @@ trimthenstep6:
 		  soisfconnected(so);
 		}
 
-		/* Do window scaling? */
-/*		if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
- *			(TF_RCVD_SCALE|TF_REQ_SCALE)) {
- *			tp->snd_scale = tp->requested_s_scale;
- *			tp->rcv_scale = tp->request_r_scale;
- *		}
- */
 		(void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);
 		tp->snd_wl1 = ti->ti_seq - 1;
 		/* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
@@ -1155,19 +1020,13 @@ trimthenstep6:
 		STAT(tcpstat.tcps_rcvackbyte += acked);
 
 		/*
-		 * If we have a timestamp reply, update smoothed
-		 * round trip time.  If no timestamp is present but
-		 * transmit timer is running and timed sequence
+		 * If transmit timer is running and timed sequence
 		 * number was acked, update smoothed round trip time.
 		 * Since we now have an rtt measurement, cancel the
 		 * timer backoff (cf., Phil Karn's retransmit alg.).
 		 * Recompute the initial retransmit timer.
 		 */
-/*		if (ts_present)
- *			tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
- *		else
- */
-		     if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
+		if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
 			tcp_xmit_timer(tp,tp->t_rtt);
 
 		/*
@@ -1205,13 +1064,6 @@ trimthenstep6:
 			tp->snd_wnd -= acked;
 			ourfinisacked = 0;
 		}
-		/*
-		 * XXX sowwakup is called when data is acked and there's room for
-		 * for more data... it should read() the socket
-		 */
-/*		if (so->so_snd.sb_flags & SB_NOTIFY)
- *			sowwakeup(so);
- */
 		tp->snd_una = ti->ti_ack;
 		if (SEQ_LT(tp->snd_nxt, tp->snd_una))
 			tp->snd_nxt = tp->snd_una;
@@ -1233,7 +1085,6 @@ trimthenstep6:
 				 * we'll hang forever.
 				 */
 				if (so->so_state & SS_FCANTRCVMORE) {
-					soisfdisconnected(so);
 					tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;
 				}
 				tp->t_state = TCPS_FIN_WAIT_2;
@@ -1251,7 +1102,6 @@ trimthenstep6:
 				tp->t_state = TCPS_TIME_WAIT;
 				tcp_canceltimers(tp);
 				tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
-				soisfdisconnected(so);
 			}
 			break;
 
@@ -1384,7 +1234,6 @@ dodata:
 			 * will got to TCPS_LAST_ACK, and use tcp_output()
 			 * to send the FIN.
 			 */
-/*			sofcantrcvmore(so); */
 			sofwdrain(so);
 
 			tp->t_flags |= TF_ACKNOW;
@@ -1421,7 +1270,6 @@ dodata:
 			tp->t_state = TCPS_TIME_WAIT;
 			tcp_canceltimers(tp);
 			tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
-			soisfdisconnected(so);
 			break;
 
 		/*
@@ -1440,13 +1288,6 @@ dodata:
 	 *
 	 * See above.
 	 */
-/*	if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) {
- */
-/*	if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg &&
- *		(so->so_iptos & IPTOS_LOWDELAY) == 0) ||
- *	       ((so->so_iptos & IPTOS_LOWDELAY) &&
- *	       ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) {
- */
 	if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&
 	    ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
 		tp->t_flags |= TF_ACKNOW;
@@ -1493,10 +1334,6 @@ drop:
 	return;
 }
 
- /* , ts_present, ts_val, ts_ecr) */
-/*	int *ts_present;
- *	u_int32_t *ts_val, *ts_ecr;
- */
 static void
 tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
 {
@@ -1531,35 +1368,6 @@ tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
 			NTOHS(mss);
 			(void) tcp_mss(tp, mss);	/* sets t_maxseg */
 			break;
-
-/*		case TCPOPT_WINDOW:
- *			if (optlen != TCPOLEN_WINDOW)
- *				continue;
- *			if (!(ti->ti_flags & TH_SYN))
- *				continue;
- *			tp->t_flags |= TF_RCVD_SCALE;
- *			tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT);
- *			break;
- */
-/*		case TCPOPT_TIMESTAMP:
- *			if (optlen != TCPOLEN_TIMESTAMP)
- *				continue;
- *			*ts_present = 1;
- *			memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val));
- *			NTOHL(*ts_val);
- *			memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr));
- *			NTOHL(*ts_ecr);
- *
- */			/*
- *			 * A timestamp received in a SYN makes
- *			 * it ok to send timestamp requests and replies.
- *			 */
-/*			if (ti->ti_flags & TH_SYN) {
- *				tp->t_flags |= TF_RCVD_TSTMP;
- *				tp->ts_recent = *ts_val;
- *				tp->ts_recent_age = tcp_now;
- *			}
- */			break;
 		}
 	}
 }
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 5daf58e..a11f3da 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -272,39 +272,9 @@ send:
 			mss = htons((u_int16_t) tcp_mss(tp, 0));
 			memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
 			optlen = 4;
-
-/*			if ((tp->t_flags & TF_REQ_SCALE) &&
- *			    ((flags & TH_ACK) == 0 ||
- *			    (tp->t_flags & TF_RCVD_SCALE))) {
- *				*((u_int32_t *) (opt + optlen)) = htonl(
- *					TCPOPT_NOP << 24 |
- *					TCPOPT_WINDOW << 16 |
- *					TCPOLEN_WINDOW << 8 |
- *					tp->request_r_scale);
- *				optlen += 4;
- *			}
- */
 		}
  	}
 
- 	/*
-	 * Send a timestamp and echo-reply if this is a SYN and our side
-	 * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
-	 * and our peer have sent timestamps in our SYN's.
- 	 */
-/* 	if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
- *	     (flags & TH_RST) == 0 &&
- *	    ((flags & (TH_SYN|TH_ACK)) == TH_SYN ||
- *	     (tp->t_flags & TF_RCVD_TSTMP))) {
- *		u_int32_t *lp = (u_int32_t *)(opt + optlen);
- *
- *		/ * Form timestamp option as shown in appendix A of RFC 1323. *  /
- *		*lp++ = htonl(TCPOPT_TSTAMP_HDR);
- *		*lp++ = htonl(tcp_now);
- *		*lp   = htonl(tp->ts_recent);
- *		optlen += TCPOLEN_TSTAMP_APPA;
- *	}
- */
  	hdrlen += optlen;
 
 	/*
@@ -334,28 +304,15 @@ send:
 
 		m = m_get();
 		if (m == NULL) {
-/*			error = ENOBUFS; */
 			error = 1;
 			goto out;
 		}
 		m->m_data += IF_MAXLINKHDR;
 		m->m_len = hdrlen;
 
-		/*
-		 * This will always succeed, since we make sure our mbufs
-		 * are big enough to hold one MSS packet + header + ... etc.
-		 */
-/*		if (len <= MHLEN - hdrlen - max_linkhdr) { */
-
-			sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
-			m->m_len += len;
+		sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
+		m->m_len += len;
 
-/*		} else {
- *			m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
- *			if (m->m_next == 0)
- *				len = 0;
- *		}
- */
 		/*
 		 * If we're sending everything we've got, set PUSH.
 		 * (This will keep happy those implementations which only
@@ -376,7 +333,6 @@ send:
 
 		m = m_get();
 		if (m == NULL) {
-/*			error = ENOBUFS; */
 			error = 1;
 			goto out;
 		}
@@ -433,10 +389,6 @@ send:
 
 	if (SEQ_GT(tp->snd_up, tp->snd_una)) {
 		ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
-#ifdef notdef
-	if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
-		ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
-#endif
 		ti->ti_flags |= TH_URG;
 	} else
 		/*
@@ -523,32 +475,10 @@ send:
 	((struct ip *)ti)->ip_ttl = IPDEFTTL;
 	((struct ip *)ti)->ip_tos = so->so_iptos;
 
-/* #if BSD >= 43 */
-	/* Don't do IP options... */
-/*	error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
- *	    so->so_options & SO_DONTROUTE, 0);
- */
 	error = ip_output(so, m);
-
-/* #else
- *	error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
- *	    so->so_options & SO_DONTROUTE);
- * #endif
- */
     }
 	if (error) {
 out:
-/*		if (error == ENOBUFS) {
- *			tcp_quench(tp->t_inpcb, 0);
- *			return (0);
- *		}
- */
-/*		if ((error == EHOSTUNREACH || error == ENETDOWN)
- *		    && TCPS_HAVERCVDSYN(tp->t_state)) {
- *			tp->t_softerror = error;
- *			return (0);
- *		}
- */
 		return (error);
 	}
 	STAT(tcpstat.tcps_sndtotal++);
@@ -574,9 +504,6 @@ tcp_setpersist(struct tcpcb *tp)
 {
     int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
 
-/*	if (tp->t_timer[TCPT_REXMT])
- *		panic("tcp_output REXMT");
- */
 	/*
 	 * Start/restart persistence timer.
 	 */
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 219f1dd..892bd83 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -60,7 +60,6 @@ tcp_init(void)
  * in a skeletal tcp/ip header, minimizing the amount of work
  * necessary when the connection is used.
  */
-/* struct tcpiphdr * */
 void
 tcp_template(struct tcpcb *tp)
 {
@@ -119,11 +118,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
         if (m == NULL) {
 		if ((m = m_get()) == NULL)
 			return;
-#ifdef TCP_COMPAT_42
-		tlen = 1;
-#else
 		tlen = 0;
-#endif
 		m->m_data += IF_MAXLINKHDR;
 		*mtod(m, struct tcpiphdr *) = *ti;
 		ti = mtod(m, struct tcpiphdr *);
@@ -220,12 +215,6 @@ tcp_newtcpcb(struct socket *so)
  */
 struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
 {
-/* tcp_drop(tp, errno)
-	register struct tcpcb *tp;
-	int errno;
-{
-*/
-
 	DEBUG_CALL("tcp_drop");
 	DEBUG_ARG("tp = %lx", (long)tp);
 	DEBUG_ARG("errno = %d", errno);
@@ -236,10 +225,6 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
 		STAT(tcpstat.tcps_drops++);
 	} else
 		STAT(tcpstat.tcps_conndrops++);
-/*	if (errno == ETIMEDOUT && tp->t_softerror)
- *		errno = tp->t_softerror;
- */
-/*	so->so_error = errno; */
 	return (tcp_close(tp));
 }
 
@@ -267,14 +252,8 @@ tcp_close(struct tcpcb *tp)
 		remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
 		m_freem(m);
 	}
-	/* It's static */
-/*	if (tp->t_template)
- *		(void) m_free(dtom(tp->t_template));
- */
-/*	free(tp, M_PCB);  */
 	free(tp);
         so->so_tcpcb = NULL;
-	soisfdisconnected(so);
 	/* clobber input socket cache if we're closing the cached connection */
 	if (so == tcp_last_so)
 		tcp_last_so = &tcb;
@@ -286,30 +265,6 @@ tcp_close(struct tcpcb *tp)
 	return ((struct tcpcb *)0);
 }
 
-#ifdef notdef
-void
-tcp_drain()
-{
-	/* XXX */
-}
-
-/*
- * When a source quench is received, close congestion window
- * to one segment.  We will gradually open it again as we proceed.
- */
-void
-tcp_quench(i, errno)
-
-	int errno;
-{
-	struct tcpcb *tp = intotcpcb(inp);
-
-	if (tp)
-		tp->snd_cwnd = tp->t_maxseg;
-}
-
-#endif /* notdef */
-
 /*
  * TCP protocol interface to socket abstraction.
  */
@@ -349,9 +304,6 @@ tcp_sockclosed(struct tcpcb *tp)
 		tp->t_state = TCPS_LAST_ACK;
 		break;
 	}
-/*	soisfdisconnecting(tp->t_socket); */
-	if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
-		soisfdisconnected(tp->t_socket);
 	if (tp)
 		tcp_output(tp);
 }
@@ -490,13 +442,6 @@ tcp_connect(struct socket *inso)
 
 	tcp_template(tp);
 
-	/* Compute window scaling to request.  */
-/*	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
- *		(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
- *		tp->request_r_scale++;
- */
-
-/*	soisconnecting(so); */ /* NOFDREF used instead */
 	STAT(tcpstat.tcps_connattempt++);
 
 	tp->t_state = TCPS_SYN_SENT;
@@ -540,10 +485,7 @@ static const struct tos_t tcptos[] = {
 	  {0, 0, 0, 0}
 };
 
-#ifdef CONFIG_QEMU
-static
-#endif
-struct emu_t *tcpemu = NULL;
+static struct emu_t *tcpemu = NULL;
 
 /*
  * Return TOS according to the above table
@@ -575,10 +517,6 @@ tcp_tos(struct socket *so)
 	return 0;
 }
 
-#if 0
-int do_echo = -1;
-#endif
-
 /*
  * Emulate programs that try and connect to us
  * This includes ftp (the data connection is
@@ -661,302 +599,6 @@ tcp_emu(struct socket *so, struct mbuf *m)
 			return 0;
 		}
 
-#if 0
-	 case EMU_RLOGIN:
-		/*
-		 * Rlogin emulation
-		 * First we accumulate all the initial option negotiation,
-		 * then fork_exec() rlogin according to the  options
-		 */
-		{
-			int i, i2, n;
-			char *ptr;
-			char args[100];
-			char term[100];
-			struct sbuf *so_snd = &so->so_snd;
-			struct sbuf *so_rcv = &so->so_rcv;
-
-			/* First check if they have a priveladged port, or too much data has arrived */
-			if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
-			    (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
-				memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
-				so_snd->sb_wptr += 18;
-				so_snd->sb_cc += 18;
-				tcp_sockclosed(sototcpcb(so));
-				m_free(m);
-				return 0;
-			}
-
-			/* Append the current data */
-			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
-			so_rcv->sb_wptr += m->m_len;
-			so_rcv->sb_rptr += m->m_len;
-			m_free(m);
-
-			/*
-			 * Check if we have all the initial options,
-			 * and build argument list to rlogin while we're here
-			 */
-			n = 0;
-			ptr = so_rcv->sb_data;
-			args[0] = 0;
-			term[0] = 0;
-			while (ptr < so_rcv->sb_wptr) {
-				if (*ptr++ == 0) {
-					n++;
-					if (n == 2) {
-						sprintf(args, "rlogin -l %s %s",
-							ptr, inet_ntoa(so->so_faddr));
-					} else if (n == 3) {
-						i2 = so_rcv->sb_wptr - ptr;
-						for (i = 0; i < i2; i++) {
-							if (ptr[i] == '/') {
-								ptr[i] = 0;
-#ifdef HAVE_SETENV
-								sprintf(term, "%s", ptr);
-#else
-								sprintf(term, "TERM=%s", ptr);
-#endif
-								ptr[i] = '/';
-								break;
-							}
-						}
-					}
-				}
-			}
-
-			if (n != 4)
-			   return 0;
-
-			/* We have it, set our term variable and fork_exec() */
-#ifdef HAVE_SETENV
-			setenv("TERM", term, 1);
-#else
-			putenv(term);
-#endif
-			fork_exec(so, args, 2);
-			term[0] = 0;
-			so->so_emu = 0;
-
-			/* And finally, send the client a 0 character */
-			so_snd->sb_wptr[0] = 0;
-			so_snd->sb_wptr++;
-			so_snd->sb_cc++;
-
-			return 0;
-		}
-
-	 case EMU_RSH:
-		/*
-		 * rsh emulation
-		 * First we accumulate all the initial option negotiation,
-		 * then rsh_exec() rsh according to the  options
-		 */
-		{
-			int  n;
-			char *ptr;
-			char *user;
-			char *args;
-			struct sbuf *so_snd = &so->so_snd;
-			struct sbuf *so_rcv = &so->so_rcv;
-
-			/* First check if they have a priveladged port, or too much data has arrived */
-			if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
-			    (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
-				memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
-				so_snd->sb_wptr += 18;
-				so_snd->sb_cc += 18;
-				tcp_sockclosed(sototcpcb(so));
-				m_free(m);
-				return 0;
-			}
-
-			/* Append the current data */
-			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
-			so_rcv->sb_wptr += m->m_len;
-			so_rcv->sb_rptr += m->m_len;
-			m_free(m);
-
-			/*
-			 * Check if we have all the initial options,
-			 * and build argument list to rlogin while we're here
-			 */
-			n = 0;
-			ptr = so_rcv->sb_data;
-			user="";
-			args="";
-			if (so->extra==NULL) {
-				struct socket *ns;
-				struct tcpcb* tp;
-				int port=atoi(ptr);
-				if (port <= 0) return 0;
-                if (port > 1023 || port < 512) {
-                  memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
-                  so_snd->sb_wptr += 18;
-                  so_snd->sb_cc += 18;
-                  tcp_sockclosed(sototcpcb(so));
-                  return 0;
-                }
-				if ((ns=socreate()) == NULL)
-                  return 0;
-				if (tcp_attach(ns)<0) {
-                  free(ns);
-                  return 0;
-				}
-
-				ns->so_laddr=so->so_laddr;
-				ns->so_lport=htons(port);
-
-				(void) tcp_mss(sototcpcb(ns), 0);
-
-				ns->so_faddr=so->so_faddr;
-				ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */
-
-				if (ns->so_faddr.s_addr == 0 ||
-					ns->so_faddr.s_addr == loopback_addr.s_addr)
-                  ns->so_faddr = alias_addr;
-
-				ns->so_iptos = tcp_tos(ns);
-				tp = sototcpcb(ns);
-
-				tcp_template(tp);
-
-				/* Compute window scaling to request.  */
-				/*	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
-				 *		(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
-				 *		tp->request_r_scale++;
-				 */
-
-                /*soisfconnecting(ns);*/
-
-				STAT(tcpstat.tcps_connattempt++);
-
-				tp->t_state = TCPS_SYN_SENT;
-				tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
-				tp->iss = tcp_iss;
-				tcp_iss += TCP_ISSINCR/2;
-				tcp_sendseqinit(tp);
-				tcp_output(tp);
-				so->extra=ns;
-			}
-			while (ptr < so_rcv->sb_wptr) {
-              if (*ptr++ == 0) {
-                n++;
-                if (n == 2) {
-                  user=ptr;
-                } else if (n == 3) {
-                  args=ptr;
-                }
-              }
-			}
-
-			if (n != 4)
-              return 0;
-
-			rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args);
-			so->so_emu = 0;
-			so->extra=NULL;
-
-			/* And finally, send the client a 0 character */
-			so_snd->sb_wptr[0] = 0;
-			so_snd->sb_wptr++;
-			so_snd->sb_cc++;
-
-			return 0;
-		}
-
-	 case EMU_CTL:
-		{
-			int num;
-			struct sbuf *so_snd = &so->so_snd;
-			struct sbuf *so_rcv = &so->so_rcv;
-
-			/*
-			 * If there is binary data here, we save it in so->so_m
-			 */
-			if (!so->so_m) {
-			  int rxlen;
-			  char *rxdata;
-			  rxdata=mtod(m, char *);
-			  for (rxlen=m->m_len; rxlen; rxlen--) {
-			    if (*rxdata++ & 0x80) {
-			      so->so_m = m;
-			      return 0;
-			    }
-			  }
-			} /* if(so->so_m==NULL) */
-
-			/*
-			 * Append the line
-			 */
-			sbappendsb(so_rcv, m);
-
-			/* To avoid going over the edge of the buffer, we reset it */
-			if (so_snd->sb_cc == 0)
-			   so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data;
-
-			/*
-			 * A bit of a hack:
-			 * If the first packet we get here is 1 byte long, then it
-			 * was done in telnet character mode, therefore we must echo
-			 * the characters as they come.  Otherwise, we echo nothing,
-			 * because in linemode, the line is already echoed
-			 * XXX two or more control connections won't work
-			 */
-			if (do_echo == -1) {
-				if (m->m_len == 1) do_echo = 1;
-				else do_echo = 0;
-			}
-			if (do_echo) {
-			  sbappendsb(so_snd, m);
-			  m_free(m);
-			  tcp_output(sototcpcb(so)); /* XXX */
-			} else
-			  m_free(m);
-
-			num = 0;
-			while (num < so->so_rcv.sb_cc) {
-				if (*(so->so_rcv.sb_rptr + num) == '\n' ||
-				    *(so->so_rcv.sb_rptr + num) == '\r') {
-					int n;
-
-					*(so_rcv->sb_rptr + num) = 0;
-					if (ctl_password && !ctl_password_ok) {
-						/* Need a password */
-						if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) {
-							if (strcmp(buff, ctl_password) == 0) {
-								ctl_password_ok = 1;
-								n = sprintf(so_snd->sb_wptr,
-									    "Password OK.\r\n");
-								goto do_prompt;
-							}
-						}
-						n = sprintf(so_snd->sb_wptr,
-					 "Error: Password required, log on with \"pass PASSWORD\"\r\n");
-						goto do_prompt;
-					}
-					cfg_quitting = 0;
-					n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF);
-					if (!cfg_quitting) {
-						/* Register the printed data */
-do_prompt:
-						so_snd->sb_cc += n;
-						so_snd->sb_wptr += n;
-						/* Add prompt */
-						n = sprintf(so_snd->sb_wptr, "Slirp> ");
-						so_snd->sb_cc += n;
-						so_snd->sb_wptr += n;
-					}
-					/* Drop so_rcv data */
-					so_rcv->sb_cc = 0;
-					so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data;
-					tcp_output(sototcpcb(so)); /* Send the reply */
-				}
-				num++;
-			}
-			return 0;
-		}
-#endif
         case EMU_FTP: /* ftp */
                 *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */
 		if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
@@ -1100,7 +742,7 @@ do_prompt:
 		 * A typical packet for player version 1.0 (release version):
 		 *
 		 * 0000:50 4E 41 00 05
-		 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P
+		 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 ........g.l.c..P
 		 * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
 		 * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
 		 * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
@@ -1112,8 +754,8 @@ do_prompt:
 		 *
 		 * A typical packet for player version 2.0 (beta):
 		 *
-		 * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á.
-		 * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0
+		 * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA.............
+		 * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux.c..Win2.0.0
 		 * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
 		 * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
 		 * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c
index 9215eb2..9cacb0f 100644
--- a/slirp/tcp_timer.c
+++ b/slirp/tcp_timer.c
@@ -102,10 +102,6 @@ tpgone:
 		;
 	}
 	tcp_iss += TCP_ISSINCR/PR_SLOWHZ;		/* increment iss */
-#ifdef TCP_COMPAT_42
-	if ((int)tcp_iss < 0)
-		tcp_iss = 0;				/* XXX */
-#endif
 	tcp_now++;					/* for timestamps */
 }
 
@@ -210,7 +206,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 		 * retransmit times until then.
 		 */
 		if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
-/*			in_losing(tp->t_inpcb); */
 			tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
 			tp->t_srtt = 0;
 		}
@@ -275,7 +270,6 @@ tcp_timers(register struct tcpcb *tp, int timer)
 		if (tp->t_state < TCPS_ESTABLISHED)
 			goto dropit;
 
-/*		if (tp->t_socket->so_options & SO_KEEPALIVE && */
 		if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
 		    	if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
 				goto dropit;
@@ -292,17 +286,8 @@ tcp_timers(register struct tcpcb *tp, int timer)
 			 * correspondent TCP to respond.
 			 */
 			STAT(tcpstat.tcps_keepprobe++);
-#ifdef TCP_COMPAT_42
-			/*
-			 * The keepalive packet must have nonzero length
-			 * to get a 4.2 host to respond.
-			 */
-			tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
-			    tp->rcv_nxt - 1, tp->snd_una - 1, 0);
-#else
 			tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
 			    tp->rcv_nxt, tp->snd_una - 1, 0);
-#endif
 			tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 		} else
 			tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
@@ -310,7 +295,7 @@ tcp_timers(register struct tcpcb *tp, int timer)
 
 	dropit:
 		STAT(tcpstat.tcps_keepdrops++);
-		tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
+		tp = tcp_drop(tp, 0);
 		break;
 	}
 
diff --git a/slirp/tcp_timer.h b/slirp/tcp_timer.h
index 791ee49..f648ed0 100644
--- a/slirp/tcp_timer.h
+++ b/slirp/tcp_timer.h
@@ -98,7 +98,6 @@
 #define	TCPTV_KEEPCNT	8			/* max probes before drop */
 
 #define	TCPTV_MIN	(  1*PR_SLOWHZ)		/* minimum allowable value */
-/* #define	TCPTV_REXMTMAX	( 64*PR_SLOWHZ)	*/	/* max allowable REXMT value */
 #define TCPTV_REXMTMAX  ( 12*PR_SLOWHZ)		/* max allowable REXMT value */
 
 #define	TCP_LINGERTIME	120			/* linger at most 2 minutes */
@@ -106,11 +105,6 @@
 #define TCP_MAXRXTSHIFT 12                      /* maximum retransmits */
 
 
-#ifdef	TCPTIMERS
-char *tcptimers[] =
-    { "REXMT", "PERSIST", "KEEP", "2MSL" };
-#endif
-
 /*
  * Force a time value to be in a certain range.
  */
diff --git a/slirp/tcp_var.h b/slirp/tcp_var.h
index d4af1c8..be5741f 100644
--- a/slirp/tcp_var.h
+++ b/slirp/tcp_var.h
@@ -61,9 +61,7 @@ struct tcpcb {
 #define	TF_RCVD_TSTMP	0x0100		/* a timestamp was received in SYN */
 #define	TF_SACK_PERMIT	0x0200		/* other side said I could SACK */
 
-	/* Make it static  for now */
-/*	struct	tcpiphdr *t_template;	/ * skeletal packet for transmit */
-	struct	tcpiphdr t_template;
+	struct	tcpiphdr t_template;    /* static skeletal packet for xmit */
 
 	struct	socket *t_socket;		/* back pointer to socket */
 /*
@@ -199,7 +197,6 @@ struct tcpstat {
 	u_long	tcps_rcvbyte;		/* bytes received in sequence */
 	u_long	tcps_rcvbadsum;		/* packets received with ccksum errs */
 	u_long	tcps_rcvbadoff;		/* packets received with bad offset */
-/*	u_long	tcps_rcvshort;	*/	/* packets received too short */
 	u_long	tcps_rcvduppack;	/* duplicate-only packets received */
 	u_long	tcps_rcvdupbyte;	/* duplicate-only bytes received */
 	u_long	tcps_rcvpartduppack;	/* packets with some duplicate data */
@@ -215,7 +212,6 @@ struct tcpstat {
 	u_long	tcps_rcvackpack;	/* rcvd ack packets */
 	u_long	tcps_rcvackbyte;	/* bytes acked by rcvd acks */
 	u_long	tcps_rcvwinupd;		/* rcvd window update packets */
-/*	u_long	tcps_pawsdrop;	*/	/* segments dropped due to PAWS */
 	u_long	tcps_predack;		/* times hdr predict ok for acks */
 	u_long	tcps_preddat;		/* times hdr predict ok for data pkts */
 	u_long	tcps_socachemiss;	/* tcp_last_so misses */
diff --git a/slirp/tftp.c b/slirp/tftp.c
index 7cb095f..3358e2b 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -23,7 +23,7 @@
  */
 
 #include <slirp.h>
-#include "qemu-common.h" // for pstrcpy
+#include "qemu-common.h"
 
 struct tftp_session {
     int in_use;
diff --git a/slirp/udp.c b/slirp/udp.c
index 60fe754..3798e34 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -50,16 +50,6 @@ struct socket udb;
 static u_int8_t udp_tos(struct socket *so);
 static void udp_emu(struct socket *so, struct mbuf *m);
 
-/*
- * UDP protocol implementation.
- * Per RFC 768, August, 1980.
- */
-#ifndef	COMPAT_42
-#define UDPCKSUM 1
-#else
-#define UDPCKSUM 0 /* XXX */
-#endif
-
 struct	socket *udp_last_so = &udb;
 
 void
@@ -76,7 +66,6 @@ udp_input(register struct mbuf *m, int iphlen)
 {
 	register struct ip *ip;
 	register struct udphdr *uh;
-/*	struct mbuf *opts = 0;*/
 	int len;
 	struct ip save_ip;
 	struct socket *so;
@@ -129,14 +118,10 @@ udp_input(register struct mbuf *m, int iphlen)
 	/*
 	 * Checksum extended UDP header and data.
 	 */
-	if (UDPCKSUM && uh->uh_sum) {
+	if (uh->uh_sum) {
       memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
 	  ((struct ipovly *)ip)->ih_x1 = 0;
 	  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
-	  /* keep uh_sum for ICMP reply
-	   * uh->uh_sum = cksum(m, len + sizeof (struct ip));
-	   * if (uh->uh_sum) {
-	   */
 	  if(cksum(m, len + sizeof(struct ip))) {
 	    STAT(udpstat.udps_badsum++);
 	    goto bad;
@@ -201,7 +186,6 @@ udp_input(register struct mbuf *m, int iphlen)
 	  /*
 	   * Setup fields
 	   */
-	  /* udp_last_so = so; */
 	  so->so_laddr = ip->ip_src;
 	  so->so_lport = uh->uh_sport;
 
@@ -246,7 +230,6 @@ udp_input(register struct mbuf *m, int iphlen)
 	return;
 bad:
 	m_freem(m);
-	/* if (opts) m_freem(opts); */
 	return;
 }
 
@@ -277,7 +260,7 @@ int udp_output2(struct socket *so, struct mbuf *m,
     memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
 	ui->ui_x1 = 0;
 	ui->ui_pr = IPPROTO_UDP;
-	ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
+	ui->ui_len = htons(m->m_len - sizeof(struct ip));
 	/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
         ui->ui_src = saddr->sin_addr;
 	ui->ui_dst = daddr->sin_addr;
@@ -289,10 +272,8 @@ int udp_output2(struct socket *so, struct mbuf *m,
 	 * Stuff checksum and output datagram.
 	 */
 	ui->ui_sum = 0;
-	if (UDPCKSUM) {
-	    if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
+	if ((ui->ui_sum = cksum(m, m->m_len)) == 0)
 		ui->ui_sum = 0xffff;
-	}
 	((struct ip *)ui)->ip_len = m->m_len;
 
 	((struct ip *)ui)->ip_ttl = IPDEFTTL;
@@ -363,8 +344,6 @@ void
 udp_detach(struct socket *so)
 {
 	closesocket(so->s);
-	/* if (so->so_m) m_free(so->so_m);    done by sofree */
-
 	sofree(so);
 }
 
@@ -651,7 +630,6 @@ udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
 		return NULL;
 	}
 	setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
-/*	setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
 
 	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 14/41] slirp: Mark sockets of incoming TCP connections
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (15 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 13/41] slirp: Do not allow to remove non-hostfwd sockets Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 20/41] slirp: tftp: Cleanup tftp_prefix check Jan Kiszka
                   ` (24 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Required for pretty-printing.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/socket.h   |    1 +
 slirp/tcp_subr.c |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/slirp/socket.h b/slirp/socket.h
index 979b191..d241a48 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -73,6 +73,7 @@ struct socket {
 
 #define SS_PERSISTENT_MASK	0xf000	/* Unremovable state bits */
 #define SS_HOSTFWD		0x1000	/* Socket describes host->guest forwarding */
+#define SS_INCOMING		0x2000	/* Connection was initiated by a host on the internet */
 
 extern struct socket tcb;
 
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 6fa4223..219f1dd 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -483,6 +483,7 @@ tcp_connect(struct socket *inso)
 					   /* if it's not FACCEPTONCE, it's already NOFDREF */
 	}
 	so->s = s;
+	so->so_state |= SS_INCOMING;
 
 	so->so_iptos = tcp_tos(so);
 	tp = sototcpcb(so);

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 18/41] slirp: Cleanup and basic reanimation of debug code
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (13 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 15/41] slirp: Add info usernet for dumping connection states Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 13/41] slirp: Do not allow to remove non-hostfwd sockets Jan Kiszka
                   ` (26 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 Makefile       |    2 +-
 slirp/bootp.c  |    2 +-
 slirp/debug.c  |   12 ------------
 slirp/debug.h  |   15 ++++++---------
 slirp/misc.c   |    4 ++++
 slirp/slirp.h  |    2 --
 slirp/socket.c |    3 ++-
 7 files changed, 14 insertions(+), 26 deletions(-)
 delete mode 100644 slirp/debug.c

diff --git a/Makefile b/Makefile
index a06c9bf..c627bfb 100644
--- a/Makefile
+++ b/Makefile
@@ -190,7 +190,7 @@ ifdef CONFIG_SLIRP
 CPPFLAGS+=-I$(SRC_PATH)/slirp
 SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
 slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
-tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
+tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o
 OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
 endif
 
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 97c2811..fec52c0 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -42,7 +42,7 @@ static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
 #ifdef DEBUG
 #define dprintf(fmt, ...) \
-if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ##  __VA_ARGS__); fflush(dfd); }
+do if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ##  __VA_ARGS__); fflush(dfd); } while (0)
 #else
 #define dprintf(fmt, ...)
 #endif
diff --git a/slirp/debug.c b/slirp/debug.c
deleted file mode 100644
index ad02df7..0000000
--- a/slirp/debug.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 1995 Danny Gasparovski.
- * Portions copyright (c) 2000 Kelly Price.
- *
- * Please read the file COPYRIGHT for the
- * terms and conditions of the copyright.
- */
-
-#include <slirp.h>
-
-FILE *dfd = NULL;
-int slirp_debug = 0;
diff --git a/slirp/debug.h b/slirp/debug.h
index 963ffda..6cfa61e 100644
--- a/slirp/debug.h
+++ b/slirp/debug.h
@@ -5,25 +5,24 @@
  * terms and conditions of the copyright.
  */
 
-#define PRN_STDERR	1
-#define PRN_SPRINTF	2
+//#define DEBUG 1
 
-extern FILE *dfd;
-extern int slirp_debug;
+#ifdef DEBUG
 
 #define DBG_CALL 0x1
 #define DBG_MISC 0x2
 #define DBG_ERROR 0x4
-#define DEBUG_DEFAULT DBG_CALL|DBG_MISC|DBG_ERROR
 
-#ifdef DEBUG
+#define dfd stderr
+
+extern int slirp_debug;
+
 #define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, "%s...\n", x); fflush(dfd); }
 #define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\n', dfd); fflush(dfd); }
 #define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); }
 #define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); }
 #define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {fprintf x ; fflush(dfd); }
 
-
 #else
 
 #define DEBUG_CALL(x)
@@ -33,5 +32,3 @@ extern int slirp_debug;
 #define DEBUG_ERROR(x)
 
 #endif
-
-void debug_init _P((char *, int));
diff --git a/slirp/misc.c b/slirp/misc.c
index 9587112..ae6f211 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -10,6 +10,10 @@
 
 #include "monitor.h"
 
+#ifdef DEBUG
+int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
+#endif
+
 u_int curtime, time_fasttimo, last_slowtimo;
 
 /*
diff --git a/slirp/slirp.h b/slirp/slirp.h
index c308582..1bd7c89 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -1,8 +1,6 @@
 #ifndef __COMMON_H__
 #define __COMMON_H__
 
-//#define DEBUG 1
-
 #include "config-host.h"
 #include "slirp_config.h"
 
diff --git a/slirp/socket.c b/slirp/socket.c
index a911b29..f7b212f 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -584,7 +584,8 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags
 	socklen_t addrlen = sizeof(addr);
 
 	DEBUG_CALL("tcp_listen");
-	DEBUG_ARG("port = %d", port);
+	DEBUG_ARG("haddr = %x", haddr);
+	DEBUG_ARG("hport = %d", hport);
 	DEBUG_ARG("laddr = %x", laddr);
 	DEBUG_ARG("lport = %d", lport);
 	DEBUG_ARG("flags = %x", flags);

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 23/41] slirp: tftp: Rework filename handling
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (19 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 17/41] slirp: Drop statistic code Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 30/41] slirp: Drop link_up checks from if_output and slirp_socket_can_recv Jan Kiszka
                   ` (20 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

This changes the filename handling from a static buffer in tftp_session
for the client-provided name + prefix to a dynamically allocated buffer
that keeps the combined path in one place.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/tftp.c |   38 ++++++++++++++++----------------------
 1 files changed, 16 insertions(+), 22 deletions(-)

diff --git a/slirp/tftp.c b/slirp/tftp.c
index 8351908..31a1e25 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -27,7 +27,7 @@
 
 struct tftp_session {
     int in_use;
-    char filename[TFTP_FILENAME_MAX];
+    char *filename;
 
     struct in_addr client_ip;
     u_int16_t client_port;
@@ -47,6 +47,7 @@ static void tftp_session_update(struct tftp_session *spt)
 
 static void tftp_session_terminate(struct tftp_session *spt)
 {
+  qemu_free(spt->filename);
   spt->in_use = 0;
 }
 
@@ -62,8 +63,10 @@ static int tftp_session_allocate(struct tftp_t *tp)
         goto found;
 
     /* sessions time out after 5 inactive seconds */
-    if ((int)(curtime - spt->timestamp) > 5000)
+    if ((int)(curtime - spt->timestamp) > 5000) {
+        qemu_free(spt->filename);
         goto found;
+    }
   }
 
   return -1;
@@ -103,15 +106,8 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
 {
   int fd;
   int bytes_read = 0;
-  char buffer[1024];
-  int n;
-
-  n = snprintf(buffer, sizeof(buffer), "%s/%s",
-	       tftp_prefix, spt->filename);
-  if (n >= sizeof(buffer))
-    return -1;
 
-  fd = open(buffer, O_RDONLY | O_BINARY);
+  fd = open(spt->filename, O_RDONLY | O_BINARY);
 
   if (fd < 0) {
     return -1;
@@ -274,6 +270,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 {
   struct tftp_session *spt;
   int s, k;
+  size_t prefix_len;
   char *req_fname;
 
   s = tftp_session_allocate(tp);
@@ -294,8 +291,13 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
   k = 0;
   pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
 
+  /* prepend tftp_prefix */
+  prefix_len = strlen(tftp_prefix);
+  spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 1);
+  memcpy(spt->filename, tftp_prefix, prefix_len);
+
   /* get name */
-  req_fname = spt->filename;
+  req_fname = spt->filename + prefix_len;
 
   while (1) {
     if (k >= TFTP_FILENAME_MAX || k >= pktlen) {
@@ -322,10 +324,8 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
   k += 6; /* skipping octet */
 
   /* do sanity checks on the filename */
-
-  if ((spt->filename[0] != '/')
-      || (spt->filename[strlen((char *)spt->filename) - 1] == '/')
-      ||  strstr((char *)spt->filename, "/../")) {
+  if (req_fname[0] != '/' || req_fname[strlen(req_fname) - 1] == '/' ||
+      strstr(req_fname, "/../")) {
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
   }
@@ -360,13 +360,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 	  struct stat stat_p;
 
 	  if (tsize == 0) {
-	      char buffer[1024];
-	      int len;
-
-	      len = snprintf(buffer, sizeof(buffer), "%s/%s",
-			     tftp_prefix, spt->filename);
-
-	      if (stat(buffer, &stat_p) == 0)
+	      if (stat(spt->filename, &stat_p) == 0)
 		  tsize = stat_p.st_size;
 	      else {
 		  tftp_send_error(spt, 1, "File not found", tp);

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 24/41] slirp: Factor out one-time initialization
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (26 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 28/41] slirp: Drop redundant checks from slirp_output Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 21/41] slirp: tftp: Clean up tftp_send_error Jan Kiszka
                   ` (13 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

In order to prepare re-initialization and multi-instance slirp, factor
out init code that is of global scope and (at least for now) only need
to be run once.

This also fixes the potentially uninitialized use of our_addr in
get_dns_addr.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/misc.c  |   17 ----------------
 slirp/misc.h  |    1 -
 slirp/slirp.c |   60 +++++++++++++++++++++++++++++++++++++++------------------
 3 files changed, 41 insertions(+), 37 deletions(-)

diff --git a/slirp/misc.c b/slirp/misc.c
index ae6f211..cffb3a0 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -16,23 +16,6 @@ int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
 
 u_int curtime, time_fasttimo, last_slowtimo;
 
-/*
- * Get our IP address and put it in our_addr
- */
-void
-getouraddr(void)
-{
-	char buff[256];
-	struct hostent *he = NULL;
-
-	if (gethostname(buff,256) == 0)
-            he = gethostbyname(buff);
-        if (he)
-            our_addr = *(struct in_addr *)he->h_addr;
-        if (our_addr.s_addr == 0)
-            our_addr.s_addr = loopback_addr.s_addr;
-}
-
 struct quehead {
 	struct quehead *qh_link;
 	struct quehead *qh_rlink;
diff --git a/slirp/misc.h b/slirp/misc.h
index 82dd596..c21f69b 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -63,7 +63,6 @@ extern int x_port, x_server, x_display;
 
 int show_x _P((char *, struct socket *));
 void redir_x _P((u_int32_t, int, int, int));
-void getouraddr _P((void));
 void slirp_insque _P((void *, void *));
 void slirp_remque _P((void *));
 int add_exec _P((struct ex_list **, int, char *, struct in_addr, int));
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 44a53cd..ea66c0c 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -102,6 +102,11 @@ static int get_dns_addr(struct in_addr *pdns_addr)
     return 0;
 }
 
+static void winsock_cleanup(void)
+{
+    WSACleanup();
+}
+
 #else
 
 static int get_dns_addr(struct in_addr *pdns_addr)
@@ -152,13 +157,44 @@ static int get_dns_addr(struct in_addr *pdns_addr)
 
 #endif
 
-#ifdef _WIN32
-static void slirp_cleanup(void)
+static void slirp_init_once(void)
 {
-    WSACleanup();
-}
+    static int initialized;
+    struct hostent *he;
+    char our_name[256];
+#ifdef _WIN32
+    WSADATA Data;
 #endif
 
+    if (initialized) {
+        return;
+    }
+    initialized = 1;
+
+#ifdef _WIN32
+    WSAStartup(MAKEWORD(2,0), &Data);
+    atexit(winsock_cleanup);
+#endif
+
+    loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+    /* FIXME: This address may change during runtime */
+    if (gethostname(our_name, sizeof(our_name)) == 0) {
+        he = gethostbyname(our_name);
+        if (he) {
+            our_addr = *(struct in_addr *)he->h_addr;
+        }
+    }
+    if (our_addr.s_addr == 0) {
+        our_addr = loopback_addr;
+    }
+
+    /* FIXME: This address may change during runtime */
+    if (get_dns_addr(&dns_addr) < 0) {
+        dns_addr = loopback_addr;
+    }
+}
+
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
@@ -168,12 +204,7 @@ void slirp_init(int restricted, struct in_addr vnetwork,
                 const char *bootfile, struct in_addr vdhcp_start,
                 struct in_addr vnameserver)
 {
-#ifdef _WIN32
-    WSADATA Data;
-
-    WSAStartup(MAKEWORD(2,0), &Data);
-    atexit(slirp_cleanup);
-#endif
+    slirp_init_once();
 
     link_up = 1;
     slirp_restrict = restricted;
@@ -184,14 +215,6 @@ void slirp_init(int restricted, struct in_addr vnetwork,
     /* Initialise mbufs *after* setting the MTU */
     m_init();
 
-    /* set default addresses */
-    inet_aton("127.0.0.1", &loopback_addr);
-
-    if (get_dns_addr(&dns_addr) < 0) {
-        dns_addr = loopback_addr;
-        fprintf (stderr, "Warning: No DNS servers found\n");
-    }
-
     vnetwork_addr = vnetwork;
     vnetwork_mask = vnetmask;
     vhost_addr = vhost;
@@ -211,7 +234,6 @@ void slirp_init(int restricted, struct in_addr vnetwork,
     vdhcp_startaddr = vdhcp_start;
     vnameserver_addr = vnameserver;
 
-    getouraddr();
     register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
 }
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 21/41] slirp: tftp: Clean up tftp_send_error
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (27 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 24/41] slirp: Factor out one-time initialization Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 26/41] slirp: Clean up updtime Jan Kiszka
                   ` (12 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

The return code of tftp_send_error is not used, drop it. And also make
sure to always terminate the session.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/tftp.c |   13 +++++--------
 1 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/slirp/tftp.c b/slirp/tftp.c
index 5d5614a..75aa4b2 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -167,11 +167,9 @@ static int tftp_send_oack(struct tftp_session *spt,
     return 0;
 }
 
-
-
-static int tftp_send_error(struct tftp_session *spt,
-			   u_int16_t errorcode, const char *msg,
-			   struct tftp_t *recv_tp)
+static void tftp_send_error(struct tftp_session *spt,
+                            u_int16_t errorcode, const char *msg,
+                            struct tftp_t *recv_tp)
 {
   struct sockaddr_in saddr, daddr;
   struct mbuf *m;
@@ -181,7 +179,7 @@ static int tftp_send_error(struct tftp_session *spt,
   m = m_get();
 
   if (!m) {
-    return -1;
+    goto out;
   }
 
   memset(m->m_data, 0, m->m_size);
@@ -207,9 +205,8 @@ static int tftp_send_error(struct tftp_session *spt,
 
   udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 
+out:
   tftp_session_terminate(spt);
-
-  return 0;
 }
 
 static int tftp_send_data(struct tftp_session *spt,

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 29/41] slirp: Clean up timeout handling around slirp_select_fill/poll
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (24 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 27/41] slirp: Kill slirp_is_inited Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 28/41] slirp: Drop redundant checks from slirp_output Jan Kiszka
                   ` (15 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Again lot of dead code. Remove it.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/misc.c  |    2 --
 slirp/misc.h  |    1 -
 slirp/slirp.c |   40 ++++------------------------------------
 3 files changed, 4 insertions(+), 39 deletions(-)

diff --git a/slirp/misc.c b/slirp/misc.c
index cffb3a0..ee14db5 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -14,8 +14,6 @@
 int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
 #endif
 
-u_int curtime, time_fasttimo, last_slowtimo;
-
 struct quehead {
 	struct quehead *qh_link;
 	struct quehead *qh_rlink;
diff --git a/slirp/misc.h b/slirp/misc.h
index c21f69b..2f47888 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -17,7 +17,6 @@ struct ex_list {
 };
 
 extern struct ex_list *exec_list;
-extern u_int time_fasttimo, last_slowtimo;
 
 #ifndef HAVE_STRDUP
 char *strdup _P((const char *));
diff --git a/slirp/slirp.c b/slirp/slirp.c
index cf52d36..9b51c0b 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -52,13 +52,16 @@ static struct in_addr client_ipaddr;
 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
 
 int slirp_restrict;
-static int do_slowtimo;
 int link_up;
 struct ex_list *exec_list;
 
 /* 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;
+
 char slirp_hostname[33];
 
 #ifdef _WIN32
@@ -267,9 +270,7 @@ void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds)
 {
     struct socket *so, *so_next;
-    struct timeval timeout;
     int nfds;
-    int tmp_time;
 
     if (!link_up) {
         return;
@@ -380,39 +381,6 @@ void slirp_select_fill(int *pnfds,
 			}
 		}
 
-	/*
-	 * Setup timeout to use minimum CPU usage, especially when idle
-	 */
-
-	/*
-	 * First, see the timeout needed by *timo
-	 */
-	timeout.tv_sec = 0;
-	timeout.tv_usec = -1;
-	/*
-	 * If a slowtimo is needed, set timeout to 500ms from the last
-	 * slow timeout. If a fast timeout is needed, set timeout within
-	 * 200ms of when it was requested.
-	 */
-	if (do_slowtimo) {
-		/* XXX + 10000 because some select()'s aren't that accurate */
-		timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
-		if (timeout.tv_usec < 0)
-		   timeout.tv_usec = 0;
-		else if (timeout.tv_usec > 510000)
-		   timeout.tv_usec = 510000;
-
-		/* Can only fasttimo if we also slowtimo */
-		if (time_fasttimo) {
-			tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
-			if (tmp_time < 0)
-			   tmp_time = 0;
-
-			/* Choose the smallest of the 2 */
-			if (tmp_time < timeout.tv_usec)
-			   timeout.tv_usec = (u_int)tmp_time;
-		}
-	}
         *pnfds = nfds;
 }
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (22 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 22/41] slirp: tftp: Refactor tftp_handle_rrq Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 14:34   ` Filip Navara
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 27/41] slirp: Kill slirp_is_inited Jan Kiszka
                   ` (17 subsequent siblings)
  41 siblings, 1 reply; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Currently, ip_id is always initialized to 0 on slirp startup (despite
the broken attempt to derive it from the clock). This is good for
reproducibility. But it is not preserved across save/restore. This patch
therefore drops the dead initialization code from ip_init and introduces
ip_id to the persistent slirp state.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/ip_input.c |    1 -
 slirp/slirp.c    |    8 +++++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 0356eb5..b07d3d5 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -59,7 +59,6 @@ void
 ip_init(void)
 {
 	ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
-	ip_id = tt.tv_sec & 0xffff;
 	udp_init();
 	tcp_init();
 }
diff --git a/slirp/slirp.c b/slirp/slirp.c
index ea66c0c..02f6fe5 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -234,7 +234,7 @@ void slirp_init(int restricted, struct in_addr vnetwork,
     vdhcp_startaddr = vdhcp_start;
     vnameserver_addr = vnameserver;
 
-    register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
+    register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, NULL);
 }
 
 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -973,6 +973,8 @@ static void slirp_state_save(QEMUFile *f, void *opaque)
             slirp_socket_save(f, so);
         }
     qemu_put_byte(f, 0);
+
+    qemu_put_be16(f, ip_id);
 }
 
 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
@@ -1103,5 +1105,9 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         so->extra = (void *)ex_ptr->ex_exec;
     }
 
+    if (version_id >= 2) {
+        ip_id = qemu_get_be16(f);
+    }
+
     return 0;
 }

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 27/41] slirp: Kill slirp_is_inited
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (23 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 29/41] slirp: Clean up timeout handling around slirp_select_fill/poll Jan Kiszka
                   ` (16 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Avoid the need for slirp_is_inited by refactoring the protected
slirp_select_* functions. This also avoids the clearing of all fd sets
on select errors.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |    9 +--------
 net.h            |    1 -
 slirp/libslirp.h |   14 +++++++++++++-
 slirp/slirp.c    |   20 +++++++++++++-------
 vl.c             |   23 +++++------------------
 5 files changed, 32 insertions(+), 35 deletions(-)

diff --git a/net.c b/net.c
index 99726cd..b2ec4c1 100644
--- a/net.c
+++ b/net.c
@@ -120,9 +120,7 @@
 #include "qemu_socket.h"
 #include "qemu-log.h"
 
-#if defined(CONFIG_SLIRP)
-#include "libslirp.h"
-#endif
+#include "slirp/libslirp.h"
 
 
 static VLANState *first_vlan;
@@ -712,11 +710,6 @@ void slirp_output(const uint8_t *pkt, int pkt_len)
     qemu_send_packet(slirp_vc, pkt, pkt_len);
 }
 
-int slirp_is_inited(void)
-{
-    return slirp_inited;
-}
-
 static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
 {
 #ifdef DEBUG_SLIRP
diff --git a/net.h b/net.h
index 5a608e0..7fcb49d 100644
--- a/net.h
+++ b/net.h
@@ -134,7 +134,6 @@ void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str);
 void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str);
 void net_slirp_redir(const char *redir_str);
 void net_cleanup(void);
-int slirp_is_inited(void);
 void net_client_check(void);
 void net_set_boot_mask(int boot_mask);
 void net_host_device_add(Monitor *mon, const char *device, const char *opts);
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 8117187..b0496d5 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -3,6 +3,8 @@
 
 #include <qemu-common.h>
 
+#ifdef CONFIG_SLIRP
+
 void slirp_init(int restricted, struct in_addr vnetwork,
                 struct in_addr vnetmask, struct in_addr vhost,
                 const char *vhostname, const char *tftp_path,
@@ -12,7 +14,8 @@ void slirp_init(int restricted, struct in_addr vnetwork,
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
 
-void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds);
+void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
+                       int select_error);
 
 void slirp_input(const uint8_t *pkt, int pkt_len);
 
@@ -32,4 +35,13 @@ void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
                        const uint8_t *buf, int size);
 size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port);
 
+#else /* !CONFIG_SLIRP */
+
+static inline void slirp_select_fill(int *pnfds, fd_set *readfds,
+                                     fd_set *writefds, fd_set *xfds) { }
+
+static inline void slirp_select_poll(fd_set *readfds, fd_set *writefds,
+                                     fd_set *xfds, int select_error) { }
+#endif /* !CONFIG_SLIRP */
+
 #endif
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 20c691f..cf52d36 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -271,6 +271,10 @@ void slirp_select_fill(int *pnfds,
     int nfds;
     int tmp_time;
 
+    if (!link_up) {
+        return;
+    }
+
     /* fail safe */
     global_readfds = NULL;
     global_writefds = NULL;
@@ -281,7 +285,7 @@ void slirp_select_fill(int *pnfds,
 	 * First, TCP sockets
 	 */
 	do_slowtimo = 0;
-	if (link_up) {
+
 		/*
 		 * *_slowtimo needs calling if there are IP fragments
 		 * in the fragment queue, or there are TCP connections active
@@ -375,7 +379,6 @@ void slirp_select_fill(int *pnfds,
 				UPD_NFDS(so->s);
 			}
 		}
-	}
 
 	/*
 	 * Setup timeout to use minimum CPU usage, especially when idle
@@ -413,11 +416,16 @@ void slirp_select_fill(int *pnfds,
         *pnfds = nfds;
 }
 
-void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
+void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
+                       int select_error)
 {
     struct socket *so, *so_next;
     int ret;
 
+    if (!link_up) {
+        return;
+    }
+
     global_readfds = readfds;
     global_writefds = writefds;
     global_xfds = xfds;
@@ -428,7 +436,6 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
 	/*
 	 * See if anything has timed out
 	 */
-	if (link_up) {
 		if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
 			tcp_fasttimo();
 			time_fasttimo = 0;
@@ -438,12 +445,11 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
 			tcp_slowtimo();
 			last_slowtimo = curtime;
 		}
-	}
 
 	/*
 	 * Check sockets
 	 */
-	if (link_up) {
+	if (!select_error) {
 		/*
 		 * Check TCP sockets
 		 */
@@ -576,7 +582,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
 	/*
 	 * See if we can start outputting
 	 */
-	if (if_queued && link_up)
+	if (if_queued)
 	   if_start();
 
 	/* clear global file descriptor sets.
diff --git a/vl.c b/vl.c
index c24655e..0f20d07 100644
--- a/vl.c
+++ b/vl.c
@@ -165,9 +165,7 @@ int main(int argc, char **argv)
 
 #include "qemu_socket.h"
 
-#if defined(CONFIG_SLIRP)
-#include "libslirp.h"
-#endif
+#include "slirp/libslirp.h"
 
 //#define DEBUG_UNUSED_IOPORT
 //#define DEBUG_IOPORT
@@ -4266,11 +4264,8 @@ void main_loop_wait(int timeout)
     tv.tv_sec = timeout / 1000;
     tv.tv_usec = (timeout % 1000) * 1000;
 
-#if defined(CONFIG_SLIRP)
-    if (slirp_is_inited()) {
-        slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
-    }
-#endif
+    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+
     qemu_mutex_unlock_iothread();
     ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
     qemu_mutex_lock_iothread();
@@ -4297,16 +4292,8 @@ void main_loop_wait(int timeout)
                 pioh = &ioh->next;
         }
     }
-#if defined(CONFIG_SLIRP)
-    if (slirp_is_inited()) {
-        if (ret < 0) {
-            FD_ZERO(&rfds);
-            FD_ZERO(&wfds);
-            FD_ZERO(&xfds);
-        }
-        slirp_select_poll(&rfds, &wfds, &xfds);
-    }
-#endif
+
+    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
 
     /* rearm timer, if not periodic */
     if (alarm_timer->flags & ALARM_FLAG_EXPIRED) {

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 26/41] slirp: Clean up updtime
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (28 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 21/41] slirp: tftp: Clean up tftp_send_error Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 33/41] slirp: Allocate/free stack instance dynamically Jan Kiszka
                   ` (11 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Drop redundant typecasts in both variants and remove the pointless
round-up in the UNIX version.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/main.h  |    1 -
 slirp/slirp.c |   13 +++++--------
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/slirp/main.h b/slirp/main.h
index 891220a..6fd38f9 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -11,7 +11,6 @@
 
 #define TOWRITEMAX 512
 
-extern struct timeval tt;
 extern int link_up;
 extern int slirp_socket;
 extern int slirp_socket_unit;
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 02f6fe5..20c691f 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -54,7 +54,6 @@ static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
 int slirp_restrict;
 static int do_slowtimo;
 int link_up;
-struct timeval tt;
 struct ex_list *exec_list;
 
 /* XXX: suppress those select globals */
@@ -250,19 +249,17 @@ static void updtime(void)
     struct _timeb tb;
 
     _ftime(&tb);
-    curtime = (u_int)tb.time * (u_int)1000;
-    curtime += (u_int)tb.millitm;
+
+    curtime = tb.time * 1000 + tb.millitm;
 }
 #else
 static void updtime(void)
 {
-        gettimeofday(&tt, NULL);
+    struct timeval tv;
 
-	curtime = (u_int)tt.tv_sec * (u_int)1000;
-	curtime += (u_int)tt.tv_usec / (u_int)1000;
+    gettimeofday(&tv, NULL);
 
-	if ((tt.tv_usec % 1000) >= 500)
-	   curtime++;
+    curtime = tv.tv_sec * 1000 + tv.tv_usec / 1000;
 }
 #endif
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 28/41] slirp: Drop redundant checks from slirp_output
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (25 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 29/41] slirp: Clean up timeout handling around slirp_select_fill/poll Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 24/41] slirp: Factor out one-time initialization Jan Kiszka
                   ` (14 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Slirp doesn't invoke slirp[_can]_output before it is initialized. The
motivation for these checks (3b7f5d479c) no longer applies. So drop
them.

Note: slirp_vc will become invalid if the slirp stack is removed during
runtime. But this is no new bug and will be fixed later.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/net.c b/net.c
index b2ec4c1..3ceaf33 100644
--- a/net.c
+++ b/net.c
@@ -696,7 +696,7 @@ static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr);
 
 int slirp_can_output(void)
 {
-    return !slirp_vc || qemu_can_send_packet(slirp_vc);
+    return qemu_can_send_packet(slirp_vc);
 }
 
 void slirp_output(const uint8_t *pkt, int pkt_len)
@@ -705,8 +705,6 @@ void slirp_output(const uint8_t *pkt, int pkt_len)
     printf("slirp output:\n");
     hex_dump(stdout, pkt, pkt_len);
 #endif
-    if (!slirp_vc)
-        return;
     qemu_send_packet(slirp_vc, pkt, pkt_len);
 }
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 30/41] slirp: Drop link_up checks from if_output and slirp_socket_can_recv
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (20 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 23/41] slirp: tftp: Rework filename handling Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 22/41] slirp: tftp: Refactor tftp_handle_rrq Jan Kiszka
                   ` (19 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

link_up is true once slirp is initialized, so these check are really not
required.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/if.c    |    5 +----
 slirp/slirp.c |    3 ---
 2 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/slirp/if.c b/slirp/if.c
index 1ef4bf9..58ab4c7 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -138,10 +138,7 @@ diddit:
 	/*
 	 * This prevents us from malloc()ing too many mbufs
 	 */
-	if (link_up) {
-		/* if_start will check towrite */
-		if_start();
-	}
+	if_start();
 #endif
 }
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 9b51c0b..71f79a3 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -824,9 +824,6 @@ size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
 	struct iovec iov[2];
 	struct socket *so;
 
-    if (!link_up)
-        return 0;
-
 	so = slirp_find_ctl_socket(guest_addr, guest_port);
 
 	if (!so || so->so_state & SS_NOFDREF)

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 22/41] slirp: tftp: Refactor tftp_handle_rrq
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (21 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 30/41] slirp: Drop link_up checks from if_output and slirp_socket_can_recv Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent Jan Kiszka
                   ` (18 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Specifically make the filename extraction more readable, and always
report errors back to the client.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/tftp.c |   49 +++++++++++++++++++++----------------------------
 1 files changed, 21 insertions(+), 28 deletions(-)

diff --git a/slirp/tftp.c b/slirp/tftp.c
index 75aa4b2..8351908 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -27,7 +27,7 @@
 
 struct tftp_session {
     int in_use;
-    unsigned char filename[TFTP_FILENAME_MAX];
+    char filename[TFTP_FILENAME_MAX];
 
     struct in_addr client_ip;
     u_int16_t client_port;
@@ -273,8 +273,8 @@ static int tftp_send_data(struct tftp_session *spt,
 static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
 {
   struct tftp_session *spt;
-  int s, k, n;
-  u_int8_t *src, *dst;
+  int s, k;
+  char *req_fname;
 
   s = tftp_session_allocate(tp);
 
@@ -290,37 +290,31 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
       return;
   }
 
-  src = tp->x.tp_buf;
-  dst = spt->filename;
-  n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
+  /* skip header fields */
+  k = 0;
+  pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
 
   /* get name */
+  req_fname = spt->filename;
 
-  for (k = 0; k < n; k++) {
-    if (k < TFTP_FILENAME_MAX) {
-      dst[k] = src[k];
-    }
-    else {
+  while (1) {
+    if (k >= TFTP_FILENAME_MAX || k >= pktlen) {
+      tftp_send_error(spt, 2, "Access violation", tp);
       return;
     }
-
-    if (src[k] == '\0') {
+    req_fname[k] = (char)tp->x.tp_buf[k];
+    if (req_fname[k++] == '\0') {
       break;
     }
   }
 
-  if (k >= n) {
-    return;
-  }
-
-  k++;
-
   /* check mode */
-  if ((n - k) < 6) {
+  if ((pktlen - k) < 6) {
+    tftp_send_error(spt, 2, "Access violation", tp);
     return;
   }
 
-  if (memcmp(&src[k], "octet\0", 6) != 0) {
+  if (memcmp(&tp->x.tp_buf[k], "octet\0", 6) != 0) {
       tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
       return;
   }
@@ -337,29 +331,28 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
   }
 
   /* check if the file exists */
-
-  if (tftp_read_data(spt, 0, spt->filename, 0) < 0) {
+  if (tftp_read_data(spt, 0, NULL, 0) < 0) {
       tftp_send_error(spt, 1, "File not found", tp);
       return;
   }
 
-  if (src[n - 1] != 0) {
+  if (tp->x.tp_buf[pktlen - 1] != 0) {
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
   }
 
-  while (k < n) {
+  while (k < pktlen) {
       const char *key, *value;
 
-      key = (char *)src + k;
+      key = (const char *)&tp->x.tp_buf[k];
       k += strlen(key) + 1;
 
-      if (k >= n) {
+      if (k >= pktlen) {
 	  tftp_send_error(spt, 2, "Access violation", tp);
 	  return;
       }
 
-      value = (char *)src + k;
+      value = (const char *)&tp->x.tp_buf[k];
       k += strlen(value) + 1;
 
       if (strcmp(key, "tsize") == 0) {

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 36/41] slirp: Use shell to erase smb directory
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (32 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 37/41] slirp: Improve error handling in slirp_smb Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 39/41] net: Provide VLAN client lookup helper Jan Kiszka
                   ` (7 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Instead of open-coding this, we can use the power of the shell to remove
the smb_dir on exit.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   30 ++++--------------------------
 1 files changed, 4 insertions(+), 26 deletions(-)

diff --git a/net.c b/net.c
index 0c1a99b..edf7ca6 100644
--- a/net.c
+++ b/net.c
@@ -1014,35 +1014,13 @@ void net_slirp_redir(const char *redir_str)
 
 static char smb_dir[1024];
 
-static void erase_dir(char *dir_name)
-{
-    DIR *d;
-    struct dirent *de;
-    char filename[1024];
-
-    /* erase all the files in the directory */
-    if ((d = opendir(dir_name)) != NULL) {
-        for(;;) {
-            de = readdir(d);
-            if (!de)
-                break;
-            if (strcmp(de->d_name, ".") != 0 &&
-                strcmp(de->d_name, "..") != 0) {
-                snprintf(filename, sizeof(filename), "%s/%s",
-                         smb_dir, de->d_name);
-                if (unlink(filename) != 0)  /* is it a directory? */
-                    erase_dir(filename);
-            }
-        }
-        closedir(d);
-        rmdir(dir_name);
-    }
-}
-
 /* automatic user mode samba server configuration */
 static void smb_exit(void)
 {
-    erase_dir(smb_dir);
+    char cmd[1024];
+
+    snprintf(cmd, sizeof(cmd), "rm -rf %s", smb_dir);
+    system(cmd);
 }
 
 static void slirp_smb(SlirpState* s, const char *exported_dir,

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 35/41] slirp: Save/restore bootp client states
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (35 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 32/41] slirp: Use internal state in interface Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 38/41] slirp: Enable multi-instance support for the smb service Jan Kiszka
                   ` (4 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/slirp.c |   28 +++++++++++++++++++++++++++-
 1 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/slirp/slirp.c b/slirp/slirp.c
index fb666e6..0ce62a3 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -222,7 +222,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     slirp->opaque = opaque;
 
-    register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
+    register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
 
     TAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
 
@@ -942,6 +942,16 @@ static void slirp_socket_save(QEMUFile *f, struct socket *so)
     slirp_tcp_save(f, so->so_tcpcb);
 }
 
+static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
+{
+    int i;
+
+    for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
+        qemu_put_be16(f, slirp->bootp_clients[i].allocated);
+        qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
+    }
+}
+
 static void slirp_state_save(QEMUFile *f, void *opaque)
 {
     Slirp *slirp = opaque;
@@ -961,6 +971,8 @@ static void slirp_state_save(QEMUFile *f, void *opaque)
     qemu_put_byte(f, 0);
 
     qemu_put_be16(f, slirp->ip_id);
+
+    slirp_bootp_save(f, slirp);
 }
 
 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
@@ -1057,6 +1069,16 @@ static int slirp_socket_load(QEMUFile *f, struct socket *so)
     return 0;
 }
 
+static void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
+{
+    int i;
+
+    for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
+        slirp->bootp_clients[i].allocated = qemu_get_be16(f);
+        qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
+    }
+}
+
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
 {
     Slirp *slirp = opaque;
@@ -1096,5 +1118,9 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         slirp->ip_id = qemu_get_be16(f);
     }
 
+    if (version_id >= 3) {
+        slirp_bootp_load(f, slirp);
+    }
+
     return 0;
 }

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 32/41] slirp: Use internal state in interface
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (34 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 39/41] net: Provide VLAN client lookup helper Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 35/41] slirp: Save/restore bootp client states Jan Kiszka
                   ` (5 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

This now also exports the internal state to the slirp users in qemu,
returning it from slirp_init and expecting it along with service
invocations. Additionally provide an opaque value interface for the
callbacks from slirp into the qemu core.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  105 +++++++++++++++++++++++++++++++++---------------------
 slirp/if.c       |    2 +
 slirp/libslirp.h |   35 ++++++++++--------
 slirp/misc.c     |    3 +-
 slirp/slirp.c    |   46 +++++++++++-------------
 slirp/slirp.h    |    1 +
 6 files changed, 108 insertions(+), 84 deletions(-)

diff --git a/net.c b/net.c
index 3ceaf33..5a4791b 100644
--- a/net.c
+++ b/net.c
@@ -677,44 +677,55 @@ struct slirp_config_str {
     int legacy_format;
 };
 
-static int slirp_inited;
+typedef struct SlirpState {
+    VLANClientState *vc;
+    Slirp *slirp;
+} SlirpState;
+
 static struct slirp_config_str *slirp_configs;
 const char *legacy_tftp_prefix;
 const char *legacy_bootp_filename;
-static VLANClientState *slirp_vc;
+static SlirpState *slirp_state;
 
-static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str,
                           int legacy_format);
-static void slirp_guestfwd(Monitor *mon, const char *config_str,
+static void slirp_guestfwd(SlirpState *s, Monitor *mon, const char *config_str,
                            int legacy_format);
 
 #ifndef _WIN32
 static const char *legacy_smb_export;
 
-static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr);
+static void slirp_smb(SlirpState *s, const char *exported_dir,
+                      struct in_addr vserver_addr);
 #endif
 
-int slirp_can_output(void)
+int slirp_can_output(void *opaque)
 {
-    return qemu_can_send_packet(slirp_vc);
+    SlirpState *s = opaque;
+
+    return qemu_can_send_packet(s->vc);
 }
 
-void slirp_output(const uint8_t *pkt, int pkt_len)
+void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
 {
+    SlirpState *s = opaque;
+
 #ifdef DEBUG_SLIRP
     printf("slirp output:\n");
     hex_dump(stdout, pkt, pkt_len);
 #endif
-    qemu_send_packet(slirp_vc, pkt, pkt_len);
+    qemu_send_packet(s->vc, pkt, pkt_len);
 }
 
 static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
 {
+    SlirpState *s = vc->opaque;
+
 #ifdef DEBUG_SLIRP
     printf("slirp input:\n");
     hex_dump(stdout, buf, size);
 #endif
-    slirp_input(buf, size);
+    slirp_input(s->slirp, buf, size);
     return size;
 }
 
@@ -733,11 +744,13 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
                           const char *vnameserver, const char *smb_export,
                           const char *vsmbserver)
 {
+    SlirpState *s = slirp_state;
+
     if (slirp_in_use) {
         /* slirp only supports a single instance so far */
         return -1;
     }
-    if (!slirp_inited) {
+    if (!s) {
         /* default settings according to historic slirp */
         struct in_addr net  = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
         struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
@@ -830,18 +843,19 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
         }
 #endif
 
-        slirp_init(restricted, net, mask, host, vhostname, tftp_export,
-                   bootfile, dhcp, dns);
-        slirp_inited = 1;
+        s = qemu_mallocz(sizeof(SlirpState));
+        s->slirp = slirp_init(restricted, net, mask, host, vhostname,
+                              tftp_export, bootfile, dhcp, dns, s);
+        slirp_state = s;
 
         while (slirp_configs) {
             struct slirp_config_str *config = slirp_configs;
 
             if (config->flags & SLIRP_CFG_HOSTFWD) {
-                slirp_hostfwd(mon, config->str,
+                slirp_hostfwd(s, mon, config->str,
                               config->flags & SLIRP_CFG_LEGACY);
             } else {
-                slirp_guestfwd(mon, config->str,
+                slirp_guestfwd(s, mon, config->str,
                                config->flags & SLIRP_CFG_LEGACY);
             }
             slirp_configs = config->next;
@@ -852,14 +866,14 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
             smb_export = legacy_smb_export;
         }
         if (smb_export) {
-            slirp_smb(smb_export, smbsrv);
+            slirp_smb(s, smb_export, smbsrv);
         }
 #endif
     }
 
-    slirp_vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive,
-                                    NULL, net_slirp_cleanup, NULL);
-    slirp_vc->info_str[0] = '\0';
+    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL,
+                                 net_slirp_cleanup, s);
+    s->vc->info_str[0] = '\0';
     slirp_in_use = 1;
     return 0;
 }
@@ -873,7 +887,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
     int is_udp = 0;
     int err;
 
-    if (!slirp_inited) {
+    if (!slirp_state) {
         monitor_printf(mon, "user mode network stack not in use\n");
         return;
     }
@@ -900,7 +914,8 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
 
     host_port = atoi(p);
 
-    err = slirp_remove_hostfwd(is_udp, host_addr, host_port);
+    err = slirp_remove_hostfwd(slirp_state->slirp, is_udp,
+                               host_addr, host_port);
 
     monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
                    err ? "removed" : "not found");
@@ -910,7 +925,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
     monitor_printf(mon, "invalid format\n");
 }
 
-static void slirp_hostfwd(Monitor *mon, const char *redir_str,
+static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str,
                           int legacy_format)
 {
     struct in_addr host_addr = { .s_addr = INADDR_ANY };
@@ -962,8 +977,8 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str,
         goto fail_syntax;
     }
 
-    if (slirp_add_hostfwd(is_udp, host_addr, host_port,
-                          guest_addr, guest_port) < 0) {
+    if (slirp_add_hostfwd(s->slirp, is_udp, host_addr, host_port, guest_addr,
+                          guest_port) < 0) {
         config_error(mon, "could not set up host forwarding rule '%s'\n",
                      redir_str);
     }
@@ -975,19 +990,19 @@ static void slirp_hostfwd(Monitor *mon, const char *redir_str,
 
 void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str)
 {
-    if (!slirp_inited) {
+    if (!slirp_state) {
         monitor_printf(mon, "user mode network stack not in use\n");
         return;
     }
 
-    slirp_hostfwd(mon, redir_str, 0);
+    slirp_hostfwd(slirp_state, mon, redir_str, 0);
 }
 
 void net_slirp_redir(const char *redir_str)
 {
     struct slirp_config_str *config;
 
-    if (!slirp_inited) {
+    if (!slirp_state) {
         config = qemu_malloc(sizeof(*config));
         pstrcpy(config->str, sizeof(config->str), redir_str);
         config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
@@ -996,7 +1011,7 @@ void net_slirp_redir(const char *redir_str)
         return;
     }
 
-    slirp_hostfwd(NULL, redir_str, 1);
+    slirp_hostfwd(slirp_state, NULL, redir_str, 1);
 }
 
 #ifndef _WIN32
@@ -1034,7 +1049,8 @@ static void smb_exit(void)
     erase_dir(smb_dir);
 }
 
-static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr)
+static void slirp_smb(SlirpState* s, const char *exported_dir,
+                      struct in_addr vserver_addr)
 {
     char smb_conf[1024];
     char smb_cmdline[1024];
@@ -1080,7 +1096,7 @@ static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr)
     snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
              SMBD_COMMAND, smb_conf);
 
-    if (slirp_add_exec(0, smb_cmdline, vserver_addr, 139) < 0) {
+    if (slirp_add_exec(s->slirp, 0, smb_cmdline, vserver_addr, 139) < 0) {
         fprintf(stderr, "conflicting/invalid smbserver address\n");
         exit(1);
     }
@@ -1096,8 +1112,8 @@ void net_slirp_smb(const char *exported_dir)
         exit(1);
     }
     legacy_smb_export = exported_dir;
-    if (slirp_inited) {
-        slirp_smb(exported_dir, vserver_addr);
+    if (slirp_state) {
+        slirp_smb(slirp_state, exported_dir, vserver_addr);
     }
 }
 
@@ -1107,21 +1123,22 @@ struct GuestFwd {
     CharDriverState *hd;
     struct in_addr server;
     int port;
+    Slirp *slirp;
 };
 
 static int guestfwd_can_read(void *opaque)
 {
     struct GuestFwd *fwd = opaque;
-    return slirp_socket_can_recv(fwd->server, fwd->port);
+    return slirp_socket_can_recv(fwd->slirp, fwd->server, fwd->port);
 }
 
 static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
 {
     struct GuestFwd *fwd = opaque;
-    slirp_socket_recv(fwd->server, fwd->port, buf, size);
+    slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
 }
 
-static void slirp_guestfwd(Monitor *mon, const char *config_str,
+static void slirp_guestfwd(SlirpState *s, Monitor *mon, const char *config_str,
                            int legacy_format)
 {
     struct in_addr server = { .s_addr = 0 };
@@ -1169,8 +1186,9 @@ static void slirp_guestfwd(Monitor *mon, const char *config_str,
     }
     fwd->server = server;
     fwd->port = port;
+    fwd->slirp = s->slirp;
 
-    if (slirp_add_exec(3, fwd->hd, server, port) < 0) {
+    if (slirp_add_exec(s->slirp, 3, fwd->hd, server, port) < 0) {
         config_error(mon, "conflicting/invalid host:port in guest forwarding "
                      "rule '%s'\n", config_str);
         qemu_free(fwd);
@@ -1186,8 +1204,13 @@ static void slirp_guestfwd(Monitor *mon, const char *config_str,
 
 void do_info_usernet(Monitor *mon)
 {
-    monitor_printf(mon, "VLAN %d (%s):\n", slirp_vc->vlan->id, slirp_vc->name);
-    slirp_connection_info(mon);
+    SlirpState *s = slirp_state;
+
+    if (!s) {
+        return;
+    }
+    monitor_printf(mon, "VLAN %d (%s):\n", s->vc->vlan->id, s->vc->name);
+    slirp_connection_info(s->slirp, mon);
 }
 
 #endif /* CONFIG_SLIRP */
@@ -2482,7 +2505,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         qemu_free(smb_export);
         qemu_free(vsmbsrv);
     } else if (!strcmp(device, "channel")) {
-        if (!slirp_inited) {
+        if (!slirp_state) {
             struct slirp_config_str *config;
 
             config = qemu_malloc(sizeof(*config));
@@ -2491,7 +2514,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
             config->next = slirp_configs;
             slirp_configs = config;
         } else {
-            slirp_guestfwd(mon, p, 1);
+            slirp_guestfwd(slirp_state, mon, p, 1);
         }
         ret = 0;
     } else
diff --git a/slirp/if.c b/slirp/if.c
index 75b15e4..0f04e13 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -162,7 +162,7 @@ if_start(Slirp *slirp)
 
  again:
         /* check if we can really output */
-        if (!slirp_can_output())
+        if (!slirp_can_output(slirp->opaque))
             return;
 
 	/*
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 3bda691..521de3e 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -8,11 +8,11 @@
 struct Slirp;
 typedef struct Slirp Slirp;
 
-void slirp_init(int restricted, struct in_addr vnetwork,
-                struct in_addr vnetmask, struct in_addr vhost,
-                const char *vhostname, const char *tftp_path,
-                const char *bootfile, struct in_addr vdhcp_start,
-                struct in_addr vnameserver);
+Slirp *slirp_init(int restricted, struct in_addr vnetwork,
+                  struct in_addr vnetmask, struct in_addr vhost,
+                  const char *vhostname, const char *tftp_path,
+                  const char *bootfile, struct in_addr vdhcp_start,
+                  struct in_addr vnameserver, void *opaque);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -20,23 +20,26 @@ void slirp_select_fill(int *pnfds,
 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                        int select_error);
 
-void slirp_input(const uint8_t *pkt, int pkt_len);
+void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
 
 /* you must provide the following functions: */
-int slirp_can_output(void);
-void slirp_output(const uint8_t *pkt, int pkt_len);
+int slirp_can_output(void *opaque);
+void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len);
 
-int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
+int slirp_add_hostfwd(Slirp *slirp, int is_udp,
+                      struct in_addr host_addr, int host_port,
                       struct in_addr guest_addr, int guest_port);
-int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port);
-int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
-                   int guest_port);
+int slirp_remove_hostfwd(Slirp *slirp, int is_udp,
+                         struct in_addr host_addr, int host_port);
+int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
+                   struct in_addr guest_addr, int guest_port);
 
-void slirp_connection_info(Monitor *mon);
+void slirp_connection_info(Slirp *slirp, Monitor *mon);
 
-void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
-                       const uint8_t *buf, int size);
-size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port);
+void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,
+                       int guest_port, const uint8_t *buf, int size);
+size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
+                             int guest_port);
 
 #else /* !CONFIG_SLIRP */
 
diff --git a/slirp/misc.c b/slirp/misc.c
index c2b66fd..e9f08fd 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -370,7 +370,7 @@ fd_block(int fd)
 #endif
 }
 
-void slirp_connection_info(Monitor *mon)
+void slirp_connection_info(Slirp *slirp, Monitor *mon)
 {
     const char * const tcpstates[] = {
         [TCPS_CLOSED]       = "CLOSED",
@@ -385,7 +385,6 @@ void slirp_connection_info(Monitor *mon)
         [TCPS_FIN_WAIT_2]   = "FIN_WAIT_2",
         [TCPS_TIME_WAIT]    = "TIME_WAIT",
     };
-    Slirp *slirp = &slirp_instance;
     struct in_addr dst_addr;
     struct sockaddr_in src;
     socklen_t src_len;
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 25bc8a4..7e86124 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -187,11 +187,11 @@ static void slirp_init_once(void)
 static void slirp_state_save(QEMUFile *f, void *opaque);
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
-void slirp_init(int restricted, struct in_addr vnetwork,
-                struct in_addr vnetmask, struct in_addr vhost,
-                const char *vhostname, const char *tftp_path,
-                const char *bootfile, struct in_addr vdhcp_start,
-                struct in_addr vnameserver)
+Slirp *slirp_init(int restricted, struct in_addr vnetwork,
+                  struct in_addr vnetmask, struct in_addr vhost,
+                  const char *vhostname, const char *tftp_path,
+                  const char *bootfile, struct in_addr vdhcp_start,
+                  struct in_addr vnameserver, void *opaque)
 {
     Slirp *slirp = &slirp_instance;
 
@@ -226,7 +226,11 @@ void slirp_init(int restricted, struct in_addr vnetwork,
     slirp->vdhcp_startaddr = vdhcp_start;
     slirp->vnameserver_addr = vnameserver;
 
+    slirp->opaque = opaque;
+
     register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
+
+    return slirp;
 }
 
 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -635,7 +639,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(arp_reply, sizeof(arp_reply));
+            slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
         }
         break;
     case ARPOP_REPLY:
@@ -650,9 +654,8 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
     }
 }
 
-void slirp_input(const uint8_t *pkt, int pkt_len)
+void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
 {
-    Slirp *slirp = &slirp_instance;
     struct mbuf *m;
     int proto;
 
@@ -724,7 +727,7 @@ void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
         /* target IP */
         rah->ar_tip = iph->ip_dst.s_addr;
         slirp->client_ipaddr = iph->ip_dst;
-        slirp_output(arp_req, sizeof(arp_req));
+        slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
     } else {
         memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
         memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
@@ -732,14 +735,14 @@ void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
         memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
         eh->h_proto = htons(ETH_P_IP);
         memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
-        slirp_output(buf, ip_data_len + ETH_HLEN);
+        slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
     }
 }
 
 /* Drop host forwarding rule, return 0 if found. */
-int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
+int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
+                         int host_port)
 {
-    Slirp *slirp = &slirp_instance;
     struct socket *so;
     struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
     struct sockaddr_in addr;
@@ -761,11 +764,9 @@ int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
     return -1;
 }
 
-int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
-                      struct in_addr guest_addr, int guest_port)
+int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
+                      int host_port, struct in_addr guest_addr, int guest_port)
 {
-    Slirp *slirp = &slirp_instance;
-
     if (!guest_addr.s_addr) {
         guest_addr = slirp->vdhcp_startaddr;
     }
@@ -781,11 +782,9 @@ int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
     return 0;
 }
 
-int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
-                   int guest_port)
+int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
+                   struct in_addr guest_addr, int guest_port)
 {
-    Slirp *slirp = &slirp_instance;
-
     if (!guest_addr.s_addr) {
         guest_addr.s_addr = slirp->vnetwork_addr.s_addr |
             (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
@@ -824,9 +823,9 @@ slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
     return NULL;
 }
 
-size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
+size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
+                             int guest_port)
 {
-	Slirp *slirp = &slirp_instance;
 	struct iovec iov[2];
 	struct socket *so;
 
@@ -841,10 +840,9 @@ size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
 	return sopreprbuf(so, iov, NULL);
 }
 
-void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
+void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
                        const uint8_t *buf, int size)
 {
-    Slirp *slirp = &slirp_instance;
     int ret;
     struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index b1e8d4e..cb1a746 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -256,6 +256,7 @@ struct Slirp {
     char *tftp_prefix;
     struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
 
+    void *opaque;
 };
 
 extern Slirp slirp_instance;

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 33/41] slirp: Allocate/free stack instance dynamically
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (29 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 26/41] slirp: Clean up updtime Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 34/41] slirp: Enable multiple instances Jan Kiszka
                   ` (10 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Allocate the internal slirp state dynamically and provide and call
slirp_cleanup to properly release it after use. This patch finally
unbreaks slirp release and re-instantiation via host_net_* monitor
commands.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c            |  212 ++++++++++++++++++++++++++----------------------------
 slirp/libslirp.h |    1 
 slirp/main.h     |    1 
 slirp/slirp.c    |   32 +++++---
 slirp/slirp.h    |    2 -
 5 files changed, 124 insertions(+), 124 deletions(-)

diff --git a/net.c b/net.c
index 5a4791b..0c58124 100644
--- a/net.c
+++ b/net.c
@@ -729,11 +729,13 @@ static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t siz
     return size;
 }
 
-static int slirp_in_use;
-
 static void net_slirp_cleanup(VLANClientState *vc)
 {
-    slirp_in_use = 0;
+    SlirpState *s = vc->opaque;
+
+    slirp_cleanup(s->slirp);
+    slirp_state = NULL;
+    qemu_free(s);
 }
 
 static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
@@ -744,137 +746,129 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
                           const char *vnameserver, const char *smb_export,
                           const char *vsmbserver)
 {
-    SlirpState *s = slirp_state;
-
-    if (slirp_in_use) {
-        /* slirp only supports a single instance so far */
-        return -1;
-    }
-    if (!s) {
-        /* default settings according to historic slirp */
-        struct in_addr net  = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
-        struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
-        struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
-        struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
-        struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
+    /* default settings according to historic slirp */
+    struct in_addr net  = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
+    struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
+    struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
+    struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
+    struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
 #ifndef _WIN32
-        struct in_addr smbsrv = { .s_addr = 0 };
+    struct in_addr smbsrv = { .s_addr = 0 };
 #endif
-        char buf[20];
-        uint32_t addr;
-        int shift;
-        char *end;
+    SlirpState *s;
+    char buf[20];
+    uint32_t addr;
+    int shift;
+    char *end;
 
-        if (!tftp_export) {
-            tftp_export = legacy_tftp_prefix;
-        }
-        if (!bootfile) {
-            bootfile = legacy_bootp_filename;
-        }
+    if (!tftp_export) {
+        tftp_export = legacy_tftp_prefix;
+    }
+    if (!bootfile) {
+        bootfile = legacy_bootp_filename;
+    }
 
-        if (vnetwork) {
-            if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
-                if (!inet_aton(vnetwork, &net)) {
-                    return -1;
-                }
-                addr = ntohl(net.s_addr);
-                if (!(addr & 0x80000000)) {
-                    mask.s_addr = htonl(0xff000000); /* class A */
-                } else if ((addr & 0xfff00000) == 0xac100000) {
-                    mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
-                } else if ((addr & 0xc0000000) == 0x80000000) {
-                    mask.s_addr = htonl(0xffff0000); /* class B */
-                } else if ((addr & 0xffff0000) == 0xc0a80000) {
-                    mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
-                } else if ((addr & 0xffff0000) == 0xc6120000) {
-                    mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
-                } else if ((addr & 0xe0000000) == 0xe0000000) {
-                    mask.s_addr = htonl(0xffffff00); /* class C */
-                } else {
-                    mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
-                }
+    if (vnetwork) {
+        if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
+            if (!inet_aton(vnetwork, &net)) {
+                return -1;
+            }
+            addr = ntohl(net.s_addr);
+            if (!(addr & 0x80000000)) {
+                mask.s_addr = htonl(0xff000000); /* class A */
+            } else if ((addr & 0xfff00000) == 0xac100000) {
+                mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
+            } else if ((addr & 0xc0000000) == 0x80000000) {
+                mask.s_addr = htonl(0xffff0000); /* class B */
+            } else if ((addr & 0xffff0000) == 0xc0a80000) {
+                mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
+            } else if ((addr & 0xffff0000) == 0xc6120000) {
+                mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
+            } else if ((addr & 0xe0000000) == 0xe0000000) {
+                mask.s_addr = htonl(0xffffff00); /* class C */
             } else {
-                if (!inet_aton(buf, &net)) {
-                    return -1;
-                }
-                shift = strtol(vnetwork, &end, 10);
-                if (*end != '\0') {
-                    if (!inet_aton(vnetwork, &mask)) {
-                        return -1;
-                    }
-                } else if (shift < 4 || shift > 32) {
+                mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
+            }
+        } else {
+            if (!inet_aton(buf, &net)) {
+                return -1;
+            }
+            shift = strtol(vnetwork, &end, 10);
+            if (*end != '\0') {
+                if (!inet_aton(vnetwork, &mask)) {
                     return -1;
-                } else {
-                    mask.s_addr = htonl(0xffffffff << (32 - shift));
                 }
+            } else if (shift < 4 || shift > 32) {
+                return -1;
+            } else {
+                mask.s_addr = htonl(0xffffffff << (32 - shift));
             }
-            net.s_addr &= mask.s_addr;
-            host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
-            dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
-            dns.s_addr  = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
         }
+        net.s_addr &= mask.s_addr;
+        host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
+        dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
+        dns.s_addr  = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
+    }
 
-        if (vhost && !inet_aton(vhost, &host)) {
-            return -1;
-        }
-        if ((host.s_addr & mask.s_addr) != net.s_addr) {
-            return -1;
-        }
+    if (vhost && !inet_aton(vhost, &host)) {
+        return -1;
+    }
+    if ((host.s_addr & mask.s_addr) != net.s_addr) {
+        return -1;
+    }
 
-        if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
-            return -1;
-        }
-        if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
-            dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
-            return -1;
-        }
+    if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
+        return -1;
+    }
+    if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
+        dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
+        return -1;
+    }
 
-        if (vnameserver && !inet_aton(vnameserver, &dns)) {
-            return -1;
-        }
-        if ((dns.s_addr & mask.s_addr) != net.s_addr ||
-            dns.s_addr == host.s_addr) {
-            return -1;
-        }
+    if (vnameserver && !inet_aton(vnameserver, &dns)) {
+        return -1;
+    }
+    if ((dns.s_addr & mask.s_addr) != net.s_addr ||
+        dns.s_addr == host.s_addr) {
+        return -1;
+    }
 
 #ifndef _WIN32
-        if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
-            return -1;
-        }
+    if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
+        return -1;
+    }
 #endif
 
-        s = qemu_mallocz(sizeof(SlirpState));
-        s->slirp = slirp_init(restricted, net, mask, host, vhostname,
-                              tftp_export, bootfile, dhcp, dns, s);
-        slirp_state = s;
+    s = qemu_mallocz(sizeof(SlirpState));
+    s->slirp = slirp_init(restricted, net, mask, host, vhostname,
+                          tftp_export, bootfile, dhcp, dns, s);
+    slirp_state = s;
 
-        while (slirp_configs) {
-            struct slirp_config_str *config = slirp_configs;
+    while (slirp_configs) {
+        struct slirp_config_str *config = slirp_configs;
 
-            if (config->flags & SLIRP_CFG_HOSTFWD) {
-                slirp_hostfwd(s, mon, config->str,
-                              config->flags & SLIRP_CFG_LEGACY);
-            } else {
-                slirp_guestfwd(s, mon, config->str,
-                               config->flags & SLIRP_CFG_LEGACY);
-            }
-            slirp_configs = config->next;
-            qemu_free(config);
+        if (config->flags & SLIRP_CFG_HOSTFWD) {
+            slirp_hostfwd(s, mon, config->str,
+                          config->flags & SLIRP_CFG_LEGACY);
+        } else {
+            slirp_guestfwd(s, mon, config->str,
+                           config->flags & SLIRP_CFG_LEGACY);
         }
+        slirp_configs = config->next;
+        qemu_free(config);
+    }
 #ifndef _WIN32
-        if (!smb_export) {
-            smb_export = legacy_smb_export;
-        }
-        if (smb_export) {
-            slirp_smb(s, smb_export, smbsrv);
-        }
-#endif
+    if (!smb_export) {
+        smb_export = legacy_smb_export;
+    }
+    if (smb_export) {
+        slirp_smb(s, smb_export, smbsrv);
     }
+#endif
 
     s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL,
                                  net_slirp_cleanup, s);
     s->vc->info_str[0] = '\0';
-    slirp_in_use = 1;
     return 0;
 }
 
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 521de3e..3bcc392 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -13,6 +13,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
                   const char *vhostname, const char *tftp_path,
                   const char *bootfile, struct in_addr vdhcp_start,
                   struct in_addr vnameserver, void *opaque);
+void slirp_cleanup(Slirp *slirp);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
diff --git a/slirp/main.h b/slirp/main.h
index 90deb58..28d92d8 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -11,7 +11,6 @@
 
 #define TOWRITEMAX 512
 
-extern int link_up;
 extern int slirp_socket;
 extern int slirp_socket_unit;
 extern int slirp_socket_port;
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 7e86124..43aba3d 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -40,8 +40,6 @@ static const uint8_t special_ethaddr[6] = {
 
 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
 
-int link_up; // FIXME: kill this
-
 /* XXX: suppress those select globals */
 fd_set *global_readfds, *global_writefds, *global_xfds;
 
@@ -49,7 +47,7 @@ u_int curtime;
 static u_int time_fasttimo, last_slowtimo;
 static int do_slowtimo;
 
-Slirp slirp_instance;
+Slirp *slirp_instance;
 
 #ifdef _WIN32
 
@@ -193,11 +191,10 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
                   const char *bootfile, struct in_addr vdhcp_start,
                   struct in_addr vnameserver, void *opaque)
 {
-    Slirp *slirp = &slirp_instance;
+    Slirp *slirp = qemu_mallocz(sizeof(Slirp));
 
     slirp_init_once();
 
-    link_up = 1;
     slirp->restricted = restricted;
 
     if_init(slirp);
@@ -213,13 +210,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
         pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
                 vhostname);
     }
-    qemu_free(slirp->tftp_prefix);
-    slirp->tftp_prefix = NULL;
     if (tftp_path) {
         slirp->tftp_prefix = qemu_strdup(tftp_path);
     }
-    qemu_free(slirp->bootp_filename);
-    slirp->bootp_filename = NULL;
     if (bootfile) {
         slirp->bootp_filename = qemu_strdup(bootfile);
     }
@@ -230,9 +223,22 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
 
+    slirp_instance = slirp;
+
     return slirp;
 }
 
+void slirp_cleanup(Slirp *slirp)
+{
+    unregister_savevm("slirp", slirp);
+
+    qemu_free(slirp->tftp_prefix);
+    qemu_free(slirp->bootp_filename);
+    qemu_free(slirp);
+
+    slirp_instance = NULL;
+}
+
 #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)
@@ -263,11 +269,11 @@ static void updtime(void)
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds)
 {
-    Slirp *slirp = &slirp_instance;
+    Slirp *slirp = slirp_instance;
     struct socket *so, *so_next;
     int nfds;
 
-    if (!link_up) {
+    if (!slirp_instance) {
         return;
     }
 
@@ -384,11 +390,11 @@ void slirp_select_fill(int *pnfds,
 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                        int select_error)
 {
-    Slirp *slirp = &slirp_instance;
+    Slirp *slirp = slirp_instance;
     struct socket *so, *so_next;
     int ret;
 
-    if (!link_up) {
+    if (!slirp_instance) {
         return;
     }
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index cb1a746..5d8861c 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -259,7 +259,7 @@ struct Slirp {
     void *opaque;
 };
 
-extern Slirp slirp_instance;
+extern Slirp *slirp_instance;
 
 #ifndef NULL
 #define NULL (void *)0

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 31/41] slirp: Factor out internal state structure
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (37 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 38/41] slirp: Enable multi-instance support for the smb service Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 40/41] slirp: Make hostfwd_add/remove multi-instance-aware Jan Kiszka
                   ` (2 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

The essence of this patch is to stuff (almost) all global variables of
the slirp stack into the structure Slirp. In this step, we still keep
the structure as global variable, directly accessible by the whole
stack. Changes to the external interface of slirp will be applied in
the following patches.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/bootp.c      |   80 ++++++++++-------------
 slirp/bootp.h      |    7 ++
 slirp/if.c         |   50 +++++++-------
 slirp/if.h         |    6 --
 slirp/ip.h         |    3 -
 slirp/ip_icmp.c    |   19 +++--
 slirp/ip_input.c   |   80 ++++++++++++-----------
 slirp/ip_output.c  |    7 +-
 slirp/libslirp.h   |    3 +
 slirp/main.h       |   12 ---
 slirp/mbuf.c       |   30 ++++-----
 slirp/mbuf.h       |    9 +--
 slirp/misc.c       |    5 +
 slirp/misc.h       |    2 -
 slirp/slirp.c      |  182 +++++++++++++++++++++++++++-------------------------
 slirp/slirp.h      |   66 +++++++++++++++++--
 slirp/socket.c     |   37 +++++++----
 slirp/socket.h     |    9 +--
 slirp/tcp.h        |    4 -
 slirp/tcp_input.c  |   35 +++++-----
 slirp/tcp_output.c |    4 +
 slirp/tcp_subr.c   |   74 +++++++++++++--------
 slirp/tcp_timer.c  |   18 ++---
 slirp/tcp_timer.h  |    4 +
 slirp/tcp_var.h    |    2 -
 slirp/tftp.c       |   65 ++++++++-----------
 slirp/tftp.h       |   10 +++
 slirp/udp.c        |   56 +++++++++-------
 slirp/udp.h        |    8 +-
 29 files changed, 479 insertions(+), 408 deletions(-)

diff --git a/slirp/bootp.c b/slirp/bootp.c
index fec52c0..911ec71 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -25,19 +25,8 @@
 
 /* XXX: only DHCP is supported */
 
-#define NB_ADDR 16
-
 #define LEASE_TIME (24 * 3600)
 
-typedef struct {
-    uint8_t allocated;
-    uint8_t macaddr[6];
-} BOOTPClient;
-
-static BOOTPClient bootp_clients[NB_ADDR];
-
-char *bootp_filename;
-
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
 #ifdef DEBUG
@@ -47,35 +36,35 @@ do if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ##  __VA_ARGS__); fflush(dfd)
 #define dprintf(fmt, ...)
 #endif
 
-static BOOTPClient *get_new_addr(struct in_addr *paddr,
+static BOOTPClient *get_new_addr(Slirp *slirp, struct in_addr *paddr,
                                  const uint8_t *macaddr)
 {
     BOOTPClient *bc;
     int i;
 
-    for(i = 0; i < NB_ADDR; i++) {
-        bc = &bootp_clients[i];
+    for(i = 0; i < NB_BOOTP_CLIENTS; i++) {
+        bc = &slirp->bootp_clients[i];
         if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6))
             goto found;
     }
     return NULL;
  found:
-    bc = &bootp_clients[i];
+    bc = &slirp->bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i);
+    paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);
     return bc;
 }
 
-static BOOTPClient *request_addr(const struct in_addr *paddr,
+static BOOTPClient *request_addr(Slirp *slirp, const struct in_addr *paddr,
                                  const uint8_t *macaddr)
 {
     uint32_t req_addr = ntohl(paddr->s_addr);
-    uint32_t dhcp_addr = ntohl(vdhcp_startaddr.s_addr);
+    uint32_t dhcp_addr = ntohl(slirp->vdhcp_startaddr.s_addr);
     BOOTPClient *bc;
 
     if (req_addr >= dhcp_addr &&
-        req_addr < (dhcp_addr + NB_ADDR)) {
-        bc = &bootp_clients[req_addr - dhcp_addr];
+        req_addr < (dhcp_addr + NB_BOOTP_CLIENTS)) {
+        bc = &slirp->bootp_clients[req_addr - dhcp_addr];
         if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) {
             bc->allocated = 1;
             return bc;
@@ -84,20 +73,21 @@ static BOOTPClient *request_addr(const struct in_addr *paddr,
     return NULL;
 }
 
-static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
+static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr,
+                              const uint8_t *macaddr)
 {
     BOOTPClient *bc;
     int i;
 
-    for(i = 0; i < NB_ADDR; i++) {
-        if (!memcmp(macaddr, bootp_clients[i].macaddr, 6))
+    for(i = 0; i < NB_BOOTP_CLIENTS; i++) {
+        if (!memcmp(macaddr, slirp->bootp_clients[i].macaddr, 6))
             goto found;
     }
     return NULL;
  found:
-    bc = &bootp_clients[i];
+    bc = &slirp->bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = vdhcp_startaddr.s_addr + htonl(i);
+    paddr->s_addr = slirp->vdhcp_startaddr.s_addr + htonl(i);
     return bc;
 }
 
@@ -148,7 +138,7 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
     }
 }
 
-static void bootp_reply(const struct bootp_t *bp)
+static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
 {
     BOOTPClient *bc = NULL;
     struct mbuf *m;
@@ -173,10 +163,12 @@ static void bootp_reply(const struct bootp_t *bp)
         dhcp_msg_type != DHCPREQUEST)
         return;
     /* XXX: this is a hack to get the client mac address */
-    memcpy(client_ethaddr, bp->bp_hwaddr, 6);
+    memcpy(slirp->client_ethaddr, bp->bp_hwaddr, 6);
 
-    if ((m = m_get()) == NULL)
+    m = m_get(slirp);
+    if (!m) {
         return;
+    }
     m->m_data += IF_MAXLINKHDR;
     rbp = (struct bootp_t *)m->m_data;
     m->m_data += sizeof(struct udpiphdr);
@@ -184,30 +176,30 @@ static void bootp_reply(const struct bootp_t *bp)
 
     if (dhcp_msg_type == DHCPDISCOVER) {
         if (preq_addr) {
-            bc = request_addr(preq_addr, client_ethaddr);
+            bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
             if (bc) {
                 daddr.sin_addr = *preq_addr;
             }
         }
         if (!bc) {
          new_addr:
-            bc = get_new_addr(&daddr.sin_addr, client_ethaddr);
+            bc = get_new_addr(slirp, &daddr.sin_addr, slirp->client_ethaddr);
             if (!bc) {
                 dprintf("no address left\n");
                 return;
             }
         }
-        memcpy(bc->macaddr, client_ethaddr, 6);
+        memcpy(bc->macaddr, slirp->client_ethaddr, 6);
     } else if (preq_addr) {
-        bc = request_addr(preq_addr, client_ethaddr);
+        bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
         if (bc) {
             daddr.sin_addr = *preq_addr;
-            memcpy(bc->macaddr, client_ethaddr, 6);
+            memcpy(bc->macaddr, slirp->client_ethaddr, 6);
         } else {
             daddr.sin_addr.s_addr = 0;
         }
     } else {
-        bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
+        bc = find_addr(slirp, &daddr.sin_addr, bp->bp_hwaddr);
         if (!bc) {
             /* if never assigned, behaves as if it was already
                assigned (windows fix because it remembers its address) */
@@ -215,7 +207,7 @@ static void bootp_reply(const struct bootp_t *bp)
         }
     }
 
-    saddr.sin_addr = vhost_addr;
+    saddr.sin_addr = slirp->vhost_addr;
     saddr.sin_port = htons(BOOTP_SERVER);
 
     daddr.sin_port = htons(BOOTP_CLIENT);
@@ -248,9 +240,9 @@ static void bootp_reply(const struct bootp_t *bp)
             *q++ = DHCPACK;
         }
 
-        if (bootp_filename)
+        if (slirp->bootp_filename)
             snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s",
-                     bootp_filename);
+                     slirp->bootp_filename);
 
         *q++ = RFC2132_SRV_ID;
         *q++ = 4;
@@ -259,10 +251,10 @@ static void bootp_reply(const struct bootp_t *bp)
 
         *q++ = RFC1533_NETMASK;
         *q++ = 4;
-        memcpy(q, &vnetwork_mask, 4);
+        memcpy(q, &slirp->vnetwork_mask, 4);
         q += 4;
 
-        if (!slirp_restrict) {
+        if (!slirp->restricted) {
             *q++ = RFC1533_GATEWAY;
             *q++ = 4;
             memcpy(q, &saddr.sin_addr, 4);
@@ -270,7 +262,7 @@ static void bootp_reply(const struct bootp_t *bp)
 
             *q++ = RFC1533_DNS;
             *q++ = 4;
-            memcpy(q, &vnameserver_addr, 4);
+            memcpy(q, &slirp->vnameserver_addr, 4);
             q += 4;
         }
 
@@ -280,11 +272,11 @@ static void bootp_reply(const struct bootp_t *bp)
         memcpy(q, &val, 4);
         q += 4;
 
-        if (*slirp_hostname) {
-            val = strlen(slirp_hostname);
+        if (*slirp->client_hostname) {
+            val = strlen(slirp->client_hostname);
             *q++ = RFC1533_HOSTNAME;
             *q++ = val;
-            memcpy(q, slirp_hostname, val);
+            memcpy(q, slirp->client_hostname, val);
             q += val;
         }
     } else {
@@ -315,6 +307,6 @@ void bootp_input(struct mbuf *m)
     struct bootp_t *bp = mtod(m, struct bootp_t *);
 
     if (bp->bp_op == BOOTP_REQUEST) {
-        bootp_reply(bp);
+        bootp_reply(m->slirp, bp);
     }
 }
diff --git a/slirp/bootp.h b/slirp/bootp.h
index 3d80515..30c30ab 100644
--- a/slirp/bootp.h
+++ b/slirp/bootp.h
@@ -112,4 +112,11 @@ struct bootp_t {
     uint8_t bp_vend[DHCP_OPT_LEN];
 };
 
+typedef struct {
+    uint16_t allocated;
+    uint8_t macaddr[6];
+} BOOTPClient;
+
+#define NB_BOOTP_CLIENTS 16
+
 void bootp_input(struct mbuf *m);
diff --git a/slirp/if.c b/slirp/if.c
index 58ab4c7..75b15e4 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -7,12 +7,6 @@
 
 #include <slirp.h>
 
-int     if_queued = 0;                  /* Number of packets queued so far */
-
-struct  mbuf if_fastq;                  /* fast queue (for interactive data) */
-struct  mbuf if_batchq;                 /* queue for non-interactive data */
-struct	mbuf *next_m;			/* Pointer to next mbuf to output */
-
 #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
 
 static void
@@ -32,11 +26,11 @@ ifs_remque(struct mbuf *ifm)
 }
 
 void
-if_init(void)
+if_init(Slirp *slirp)
 {
-	if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
-	if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
-	next_m = &if_batchq;
+    slirp->if_fastq.ifq_next = slirp->if_fastq.ifq_prev = &slirp->if_fastq;
+    slirp->if_batchq.ifq_next = slirp->if_batchq.ifq_prev = &slirp->if_batchq;
+    slirp->next_m = &slirp->if_batchq;
 }
 
 /*
@@ -55,6 +49,7 @@ if_init(void)
 void
 if_output(struct socket *so, struct mbuf *ifm)
 {
+	Slirp *slirp = ifm->slirp;
 	struct mbuf *ifq;
 	int on_fastq = 1;
 
@@ -79,7 +74,8 @@ if_output(struct socket *so, struct mbuf *ifm)
 	 * We mustn't put this packet back on the fastq (or we'll send it out of order)
 	 * XXX add cache here?
 	 */
-	for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) {
+	for (ifq = slirp->if_batchq.ifq_prev; ifq != &slirp->if_batchq;
+	     ifq = ifq->ifq_prev) {
 		if (so == ifq->ifq_so) {
 			/* A match! */
 			ifm->ifq_so = so;
@@ -90,7 +86,7 @@ if_output(struct socket *so, struct mbuf *ifm)
 
 	/* No match, check which queue to put it on */
 	if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
-		ifq = if_fastq.ifq_prev;
+		ifq = slirp->if_fastq.ifq_prev;
 		on_fastq = 1;
 		/*
 		 * Check if this packet is a part of the last
@@ -102,7 +98,7 @@ if_output(struct socket *so, struct mbuf *ifm)
 			goto diddit;
 		}
 	} else
-		ifq = if_batchq.ifq_prev;
+		ifq = slirp->if_batchq.ifq_prev;
 
 	/* Create a new doubly linked list for this session */
 	ifm->ifq_so = so;
@@ -110,7 +106,7 @@ if_output(struct socket *so, struct mbuf *ifm)
 	insque(ifm, ifq);
 
 diddit:
-	++if_queued;
+	slirp->if_queued++;
 
 	if (so) {
 		/* Update *_queued */
@@ -130,7 +126,7 @@ diddit:
 			remque(ifm->ifs_next);
 
 			/* ...And insert in the new.  That'll teach ya! */
-			insque(ifm->ifs_next, &if_batchq);
+			insque(ifm->ifs_next, &slirp->if_batchq);
 		}
 	}
 
@@ -138,7 +134,7 @@ diddit:
 	/*
 	 * This prevents us from malloc()ing too many mbufs
 	 */
-	if_start();
+	if_start(ifm->slirp);
 #endif
 }
 
@@ -155,13 +151,13 @@ diddit:
  * to the first, etc. etc.
  */
 void
-if_start(void)
+if_start(Slirp *slirp)
 {
 	struct mbuf *ifm, *ifqt;
 
 	DEBUG_CALL("if_start");
 
-	if (if_queued == 0)
+	if (slirp->if_queued == 0)
 	   return; /* Nothing to do */
 
  again:
@@ -173,22 +169,22 @@ if_start(void)
 	 * See which queue to get next packet from
 	 * If there's something in the fastq, select it immediately
 	 */
-	if (if_fastq.ifq_next != &if_fastq) {
-		ifm = if_fastq.ifq_next;
+	if (slirp->if_fastq.ifq_next != &slirp->if_fastq) {
+		ifm = slirp->if_fastq.ifq_next;
 	} else {
 		/* Nothing on fastq, see if next_m is valid */
-		if (next_m != &if_batchq)
-		   ifm = next_m;
+		if (slirp->next_m != &slirp->if_batchq)
+		   ifm = slirp->next_m;
 		else
-		   ifm = if_batchq.ifq_next;
+		   ifm = slirp->if_batchq.ifq_next;
 
 		/* Set which packet to send on next iteration */
-		next_m = ifm->ifq_next;
+		slirp->next_m = ifm->ifq_next;
 	}
 	/* Remove it from the queue */
 	ifqt = ifm->ifq_prev;
 	remque(ifm);
-	--if_queued;
+	slirp->if_queued--;
 
 	/* If there are more packets for this session, re-queue them */
 	if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
@@ -204,10 +200,10 @@ if_start(void)
 	}
 
 	/* Encapsulate the packet for sending */
-        if_encap((uint8_t *)ifm->m_data, ifm->m_len);
+        if_encap(slirp, (uint8_t *)ifm->m_data, ifm->m_len);
 
         m_free(ifm);
 
-	if (if_queued)
+	if (slirp->if_queued)
 	   goto again;
 }
diff --git a/slirp/if.h b/slirp/if.h
index 2fdc354..2dac1c7 100644
--- a/slirp/if.h
+++ b/slirp/if.h
@@ -20,12 +20,6 @@
 /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
 #define IF_MAXLINKHDR (2 + 14 + 40)
 
-extern int	if_queued;	/* Number of packets queued so far */
-
-extern	struct mbuf if_fastq;                  /* fast queue (for interactive data) */
-extern	struct mbuf if_batchq;                 /* queue for non-interactive data */
-extern	struct mbuf *next_m;
-
 #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
 
 #endif
diff --git a/slirp/ip.h b/slirp/ip.h
index e0d7674..574fc01 100644
--- a/slirp/ip.h
+++ b/slirp/ip.h
@@ -250,7 +250,4 @@ struct ipoption {
 	int8_t	ipopt_list[MAX_IPOPTLEN];	/* options proper */
 };
 
-extern struct	ipq	ipq;			/* ip reass. queue */
-extern u_int16_t	ip_id;				/* ip packet ctr, for ids */
-
 #endif
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index 66b4d23..95a4b39 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -69,6 +69,7 @@ icmp_input(struct mbuf *m, int hlen)
   register struct icmp *icp;
   register struct ip *ip=mtod(m, struct ip *);
   int icmplen=ip->ip_len;
+  Slirp *slirp = m->slirp;
 
   DEBUG_CALL("icmp_input");
   DEBUG_ARG("m = %lx", (long )m);
@@ -98,12 +99,12 @@ icmp_input(struct mbuf *m, int hlen)
   case ICMP_ECHO:
     icp->icmp_type = ICMP_ECHOREPLY;
     ip->ip_len += hlen;	             /* since ip_input subtracts this */
-    if (ip->ip_dst.s_addr == vhost_addr.s_addr) {
+    if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
       icmp_reflect(m);
     } else {
       struct socket *so;
       struct sockaddr_in addr;
-      if ((so = socreate()) == NULL) goto freeit;
+      if ((so = socreate(slirp)) == NULL) goto freeit;
       if(udp_attach(so) == -1) {
 	DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
 		    errno,strerror(errno)));
@@ -122,10 +123,10 @@ icmp_input(struct mbuf *m, int hlen)
 
       /* Send the packet */
       addr.sin_family = AF_INET;
-      if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
-          vnetwork_addr.s_addr) {
+      if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+          slirp->vnetwork_addr.s_addr) {
 	/* It's an alias */
-	if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
+	if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
 	  addr.sin_addr = dns_addr;
 	} else {
 	  addr.sin_addr = loopback_addr;
@@ -222,7 +223,11 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
   }
 
   /* make a copy */
-  if(!(m=m_get())) goto end_error;               /* get mbuf */
+  m = m_get(msrc->slirp);
+  if (!m) {
+      goto end_error;
+  }
+
   { int new_m_size;
     new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
     if(new_m_size>m->m_size) m_inc(m, new_m_size);
@@ -285,7 +290,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
   ip->ip_ttl = MAXTTL;
   ip->ip_p = IPPROTO_ICMP;
   ip->ip_dst = ip->ip_src;    /* ip adresses */
-  ip->ip_src = vhost_addr;
+  ip->ip_src = m->slirp->vhost_addr;
 
   (void ) ip_output((struct socket *)NULL, m);
 
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index b07d3d5..35230f8 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -42,11 +42,8 @@
 #include <osdep.h>
 #include "ip_icmp.h"
 
-struct ipq ipq;
-
-static struct ip *ip_reass(register struct ip *ip,
-                           register struct ipq *fp);
-static void ip_freef(struct ipq *fp);
+static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp);
+static void ip_freef(Slirp *slirp, struct ipq *fp);
 static void ip_enq(register struct ipasfrag *p,
                    register struct ipasfrag *prev);
 static void ip_deq(register struct ipasfrag *p);
@@ -56,11 +53,11 @@ static void ip_deq(register struct ipasfrag *p);
  * All protocols not implemented in kernel go to raw IP protocol handler.
  */
 void
-ip_init(void)
+ip_init(Slirp *slirp)
 {
-	ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
-	udp_init();
-	tcp_init();
+    slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link;
+    udp_init(slirp);
+    tcp_init(slirp);
 }
 
 /*
@@ -70,6 +67,7 @@ ip_init(void)
 void
 ip_input(struct mbuf *m)
 {
+	Slirp *slirp = m->slirp;
 	register struct ip *ip;
 	int hlen;
 
@@ -120,19 +118,19 @@ ip_input(struct mbuf *m)
 		goto bad;
 	}
 
-    if (slirp_restrict) {
-        if ((ip->ip_dst.s_addr & vnetwork_mask.s_addr) ==
-            vnetwork_addr.s_addr) {
+    if (slirp->restricted) {
+        if ((ip->ip_dst.s_addr & slirp->vnetwork_mask.s_addr) ==
+            slirp->vnetwork_addr.s_addr) {
             if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)
                 goto bad;
         } else {
+            uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
             struct ex_list *ex_ptr;
 
-            if ((ip->ip_dst.s_addr & ~vnetwork_mask.s_addr) ==
-                ~vnetwork_mask.s_addr)
+            if ((ip->ip_dst.s_addr & inv_mask) == inv_mask) {
                 goto bad;
-
-            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+            }
+            for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
                 if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr)
                     break;
 
@@ -167,7 +165,8 @@ ip_input(struct mbuf *m)
 		 * Look for queue of fragments
 		 * of this datagram.
 		 */
-		for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) {
+		for (l = slirp->ipq.ip_link.next; l != &slirp->ipq.ip_link;
+		     l = l->next) {
             fp = container_of(l, struct ipq, ip_link);
             if (ip->ip_id == fp->ipq_id &&
                     ip->ip_src.s_addr == fp->ipq_src.s_addr &&
@@ -197,13 +196,13 @@ ip_input(struct mbuf *m)
 		 * attempt reassembly; if it succeeds, proceed.
 		 */
 		if (ip->ip_tos & 1 || ip->ip_off) {
-			ip = ip_reass(ip, fp);
+			ip = ip_reass(slirp, ip, fp);
                         if (ip == NULL)
 				return;
-			m = dtom(ip);
+			m = dtom(slirp, ip);
 		} else
 			if (fp)
-		   	   ip_freef(fp);
+		   	   ip_freef(slirp, fp);
 
 	} else
 		ip->ip_len -= hlen;
@@ -239,9 +238,9 @@ bad:
  * is given as fp; otherwise have to make a chain.
  */
 static struct ip *
-ip_reass(register struct ip *ip, register struct ipq *fp)
+ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)
 {
-	register struct mbuf *m = dtom(ip);
+	register struct mbuf *m = dtom(slirp, ip);
 	register struct ipasfrag *q;
 	int hlen = ip->ip_hl << 2;
 	int i, next;
@@ -263,10 +262,13 @@ ip_reass(register struct ip *ip, register struct ipq *fp)
 	 * If first fragment to arrive, create a reassembly queue.
 	 */
         if (fp == NULL) {
-	  struct mbuf *t;
-	  if ((t = m_get()) == NULL) goto dropfrag;
+	  struct mbuf *t = m_get(slirp);
+
+	  if (t == NULL) {
+	      goto dropfrag;
+	  }
 	  fp = mtod(t, struct ipq *);
-	  insque(&fp->ip_link, &ipq.ip_link);
+	  insque(&fp->ip_link, &slirp->ipq.ip_link);
 	  fp->ipq_ttl = IPFRAGTTL;
 	  fp->ipq_p = ip->ip_p;
 	  fp->ipq_id = ip->ip_id;
@@ -296,7 +298,7 @@ ip_reass(register struct ip *ip, register struct ipq *fp)
 		if (i > 0) {
 			if (i >= ip->ip_len)
 				goto dropfrag;
-			m_adj(dtom(ip), i);
+			m_adj(dtom(slirp, ip), i);
 			ip->ip_off += i;
 			ip->ip_len -= i;
 		}
@@ -312,11 +314,11 @@ ip_reass(register struct ip *ip, register struct ipq *fp)
 		if (i < q->ipf_len) {
 			q->ipf_len -= i;
 			q->ipf_off += i;
-			m_adj(dtom(q), i);
+			m_adj(dtom(slirp, q), i);
 			break;
 		}
 		q = q->ipf_next;
-		m_freem(dtom(q->ipf_prev));
+		m_freem(dtom(slirp, q->ipf_prev));
 		ip_deq(q->ipf_prev);
 	}
 
@@ -340,11 +342,11 @@ insert:
 	 * Reassembly is complete; concatenate fragments.
 	 */
     q = fp->frag_link.next;
-	m = dtom(q);
+	m = dtom(slirp, q);
 
 	q = (struct ipasfrag *) q->ipf_next;
 	while (q != (struct ipasfrag*)&fp->frag_link) {
-	  struct mbuf *t = dtom(q);
+	  struct mbuf *t = dtom(slirp, q);
 	  q = (struct ipasfrag *) q->ipf_next;
 	  m_cat(m, t);
 	}
@@ -375,7 +377,7 @@ insert:
 	ip->ip_src = fp->ipq_src;
 	ip->ip_dst = fp->ipq_dst;
 	remque(&fp->ip_link);
-	(void) m_free(dtom(fp));
+	(void) m_free(dtom(slirp, fp));
 	m->m_len += (ip->ip_hl << 2);
 	m->m_data -= (ip->ip_hl << 2);
 
@@ -391,17 +393,17 @@ dropfrag:
  * associated datagrams.
  */
 static void
-ip_freef(struct ipq *fp)
+ip_freef(Slirp *slirp, struct ipq *fp)
 {
 	register struct ipasfrag *q, *p;
 
 	for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
 		p = q->ipf_next;
 		ip_deq(q);
-		m_freem(dtom(q));
+		m_freem(dtom(slirp, q));
 	}
 	remque(&fp->ip_link);
-	(void) m_free(dtom(fp));
+	(void) m_free(dtom(slirp, fp));
 }
 
 /*
@@ -435,24 +437,24 @@ ip_deq(register struct ipasfrag *p)
  * queue, discard it.
  */
 void
-ip_slowtimo(void)
+ip_slowtimo(Slirp *slirp)
 {
     struct qlink *l;
 
 	DEBUG_CALL("ip_slowtimo");
 
-    l = ipq.ip_link.next;
+    l = slirp->ipq.ip_link.next;
 
         if (l == NULL)
 	   return;
 
-	while (l != &ipq.ip_link) {
+    while (l != &slirp->ipq.ip_link) {
         struct ipq *fp = container_of(l, struct ipq, ip_link);
         l = l->next;
 		if (--fp->ipq_ttl == 0) {
-			ip_freef(fp);
+			ip_freef(slirp, fp);
 		}
-	}
+    }
 }
 
 /*
diff --git a/slirp/ip_output.c b/slirp/ip_output.c
index 3031f4d..dba2784 100644
--- a/slirp/ip_output.c
+++ b/slirp/ip_output.c
@@ -40,8 +40,6 @@
 
 #include <slirp.h>
 
-u_int16_t ip_id;
-
 /* Number of packets queued before we start sending
  * (to prevent allocing too many mbufs) */
 #define IF_THRESH 10
@@ -55,6 +53,7 @@ u_int16_t ip_id;
 int
 ip_output(struct socket *so, struct mbuf *m0)
 {
+	Slirp *slirp = m0->slirp;
 	register struct ip *ip;
 	register struct mbuf *m = m0;
 	register int hlen = sizeof(struct ip );
@@ -70,7 +69,7 @@ ip_output(struct socket *so, struct mbuf *m0)
 	 */
 	ip->ip_v = IPVERSION;
 	ip->ip_off &= IP_DF;
-	ip->ip_id = htons(ip_id++);
+	ip->ip_id = htons(slirp->ip_id++);
 	ip->ip_hl = hlen >> 2;
 
 	/*
@@ -113,7 +112,7 @@ ip_output(struct socket *so, struct mbuf *m0)
 	mhlen = sizeof (struct ip);
 	for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
 	  register struct ip *mhip;
-	  m = m_get();
+	  m = m_get(slirp);
           if (m == NULL) {
 	    error = -1;
 	    goto sendorfree;
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index b0496d5..3bda691 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -5,6 +5,9 @@
 
 #ifdef CONFIG_SLIRP
 
+struct Slirp;
+typedef struct Slirp Slirp;
+
 void slirp_init(int restricted, struct in_addr vnetwork,
                 struct in_addr vnetmask, struct in_addr vhost,
                 const char *vhostname, const char *tftp_path,
diff --git a/slirp/main.h b/slirp/main.h
index 6fd38f9..90deb58 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -31,11 +31,6 @@ extern char *slirp_tty;
 extern char *exec_shell;
 extern u_int curtime;
 extern fd_set *global_readfds, *global_writefds, *global_xfds;
-extern struct in_addr vnetwork_addr;
-extern struct in_addr vnetwork_mask;
-extern struct in_addr vhost_addr;
-extern struct in_addr vdhcp_startaddr;
-extern struct in_addr vnameserver_addr;
 extern struct in_addr our_addr;
 extern struct in_addr loopback_addr;
 extern struct in_addr dns_addr;
@@ -44,16 +39,11 @@ extern char *socket_path;
 extern int towrite_max;
 extern int ppp_exit;
 extern int tcp_keepintvl;
-extern uint8_t client_ethaddr[6];
-extern int slirp_restrict;
-extern char slirp_hostname[33];
-extern char *tftp_prefix;
-extern char *bootp_filename;
 
 #define PROTO_SLIP 0x1
 #ifdef USE_PPP
 #define PROTO_PPP 0x2
 #endif
 
-void if_encap(const uint8_t *ip_data, int ip_data_len);
+void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len);
 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index 888de86..7652fea 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -17,8 +17,6 @@
 
 #include <slirp.h>
 
-static int mbuf_alloced;
-struct mbuf m_freelist, m_usedlist;
 #define MBUF_THRESH 30
 
 /*
@@ -28,10 +26,10 @@ struct mbuf m_freelist, m_usedlist;
 #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
 
 void
-m_init(void)
+m_init(Slirp *slirp)
 {
-	m_freelist.m_next = m_freelist.m_prev = &m_freelist;
-	m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
+    slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist;
+    slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist;
 }
 
 /*
@@ -43,26 +41,27 @@ m_init(void)
  * which tells m_free to actually free() it
  */
 struct mbuf *
-m_get(void)
+m_get(Slirp *slirp)
 {
 	register struct mbuf *m;
 	int flags = 0;
 
 	DEBUG_CALL("m_get");
 
-	if (m_freelist.m_next == &m_freelist) {
+	if (slirp->m_freelist.m_next == &slirp->m_freelist) {
 		m = (struct mbuf *)malloc(SLIRP_MSIZE);
 		if (m == NULL) goto end_error;
-		mbuf_alloced++;
-		if (mbuf_alloced > MBUF_THRESH)
+		slirp->mbuf_alloced++;
+		if (slirp->mbuf_alloced > MBUF_THRESH)
 			flags = M_DOFREE;
+		m->slirp = slirp;
 	} else {
-		m = m_freelist.m_next;
+		m = slirp->m_freelist.m_next;
 		remque(m);
 	}
 
 	/* Insert it in the used list */
-	insque(m,&m_usedlist);
+	insque(m,&slirp->m_usedlist);
 	m->m_flags = (flags | M_USEDLIST);
 
 	/* Initialise it */
@@ -97,9 +96,9 @@ m_free(struct mbuf *m)
 	 */
 	if (m->m_flags & M_DOFREE) {
 		free(m);
-		mbuf_alloced--;
+		m->slirp->mbuf_alloced--;
 	} else if ((m->m_flags & M_FREELIST) == 0) {
-		insque(m,&m_freelist);
+		insque(m,&m->slirp->m_freelist);
 		m->m_flags = M_FREELIST; /* Clobber other flags */
 	}
   } /* if(m) */
@@ -194,7 +193,7 @@ m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
  * Fortunately, it's not used often
  */
 struct mbuf *
-dtom(void *dat)
+dtom(Slirp *slirp, void *dat)
 {
 	struct mbuf *m;
 
@@ -202,7 +201,8 @@ dtom(void *dat)
 	DEBUG_ARG("dat = %lx", (long )dat);
 
 	/* bug corrected for M_EXT buffers */
-	for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) {
+	for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
+	     m = m->m_next) {
 	  if (m->m_flags & M_EXT) {
 	    if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
 	      return m;
diff --git a/slirp/mbuf.h b/slirp/mbuf.h
index c482753..99fca43 100644
--- a/slirp/mbuf.h
+++ b/slirp/mbuf.h
@@ -84,6 +84,7 @@ struct m_hdr {
 
 struct mbuf {
 	struct	m_hdr m_hdr;
+	Slirp *slirp;
 	union M_dat {
 		char	m_dat_[1]; /* ANSI don't like 0 sized arrays */
 		char	*m_ext_;
@@ -114,15 +115,13 @@ struct mbuf {
 #define M_DOFREE		0x08	/* when m_free is called on the mbuf, free()
 					 * it rather than putting it on the free list */
 
-extern struct mbuf m_freelist, m_usedlist;
-
-void m_init _P((void));
-struct mbuf * m_get _P((void));
+void m_init _P((Slirp *));
+struct mbuf * m_get _P((Slirp *));
 void m_free _P((struct mbuf *));
 void m_cat _P((register struct mbuf *, register struct mbuf *));
 void m_inc _P((struct mbuf *, int));
 void m_adj _P((struct mbuf *, int));
 int m_copy _P((struct mbuf *, struct mbuf *, int, int));
-struct mbuf * dtom _P((void *));
+struct mbuf * dtom _P((Slirp *, void *));
 
 #endif
diff --git a/slirp/misc.c b/slirp/misc.c
index ee14db5..c2b66fd 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -385,6 +385,7 @@ void slirp_connection_info(Monitor *mon)
         [TCPS_FIN_WAIT_2]   = "FIN_WAIT_2",
         [TCPS_TIME_WAIT]    = "TIME_WAIT",
     };
+    Slirp *slirp = &slirp_instance;
     struct in_addr dst_addr;
     struct sockaddr_in src;
     socklen_t src_len;
@@ -397,7 +398,7 @@ void slirp_connection_info(Monitor *mon)
     monitor_printf(mon, "  Protocol[State]    FD  Source Address  Port   "
                         "Dest. Address  Port RecvQ SendQ\n");
 
-    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+    for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
         if (so->so_state & SS_HOSTFWD) {
             state = "HOST_FORWARD";
         } else if (so->so_tcpcb) {
@@ -427,7 +428,7 @@ void slirp_connection_info(Monitor *mon)
                        so->so_rcv.sb_cc, so->so_snd.sb_cc);
     }
 
-    for (so = udb.so_next; so != &udb; so = so->so_next) {
+    for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) {
         if (so->so_state & SS_HOSTFWD) {
             n = snprintf(buf, sizeof(buf), "  UDP[HOST_FORWARD]");
             src_len = sizeof(src);
diff --git a/slirp/misc.h b/slirp/misc.h
index 2f47888..e43519d 100644
--- a/slirp/misc.h
+++ b/slirp/misc.h
@@ -16,8 +16,6 @@ struct ex_list {
 	struct ex_list *ex_next;
 };
 
-extern struct ex_list *exec_list;
-
 #ifndef HAVE_STRDUP
 char *strdup _P((const char *));
 #endif
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 71f79a3..25bc8a4 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -33,27 +33,14 @@ struct in_addr dns_addr;
 /* host loopback address */
 struct in_addr loopback_addr;
 
-/* virtual network configuration */
-struct in_addr vnetwork_addr;
-struct in_addr vnetwork_mask;
-struct in_addr vhost_addr;
-struct in_addr vdhcp_startaddr;
-struct in_addr vnameserver_addr;
-
 /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
 static const uint8_t special_ethaddr[6] = {
     0x52, 0x55, 0x00, 0x00, 0x00, 0x00
 };
 
-/* ARP cache for the guest IP addresses (XXX: allow many entries) */
-uint8_t client_ethaddr[6];
-static struct in_addr client_ipaddr;
-
 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
 
-int slirp_restrict;
-int link_up;
-struct ex_list *exec_list;
+int link_up; // FIXME: kill this
 
 /* XXX: suppress those select globals */
 fd_set *global_readfds, *global_writefds, *global_xfds;
@@ -62,7 +49,7 @@ u_int curtime;
 static u_int time_fasttimo, last_slowtimo;
 static int do_slowtimo;
 
-char slirp_hostname[33];
+Slirp slirp_instance;
 
 #ifdef _WIN32
 
@@ -206,37 +193,40 @@ void slirp_init(int restricted, struct in_addr vnetwork,
                 const char *bootfile, struct in_addr vdhcp_start,
                 struct in_addr vnameserver)
 {
+    Slirp *slirp = &slirp_instance;
+
     slirp_init_once();
 
     link_up = 1;
-    slirp_restrict = restricted;
+    slirp->restricted = restricted;
 
-    if_init();
-    ip_init();
+    if_init(slirp);
+    ip_init(slirp);
 
     /* Initialise mbufs *after* setting the MTU */
-    m_init();
+    m_init(slirp);
 
-    vnetwork_addr = vnetwork;
-    vnetwork_mask = vnetmask;
-    vhost_addr = vhost;
+    slirp->vnetwork_addr = vnetwork;
+    slirp->vnetwork_mask = vnetmask;
+    slirp->vhost_addr = vhost;
     if (vhostname) {
-        pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname);
+        pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
+                vhostname);
     }
-    qemu_free(tftp_prefix);
-    tftp_prefix = NULL;
+    qemu_free(slirp->tftp_prefix);
+    slirp->tftp_prefix = NULL;
     if (tftp_path) {
-        tftp_prefix = qemu_strdup(tftp_path);
+        slirp->tftp_prefix = qemu_strdup(tftp_path);
     }
-    qemu_free(bootp_filename);
-    bootp_filename = NULL;
+    qemu_free(slirp->bootp_filename);
+    slirp->bootp_filename = NULL;
     if (bootfile) {
-        bootp_filename = qemu_strdup(bootfile);
+        slirp->bootp_filename = qemu_strdup(bootfile);
     }
-    vdhcp_startaddr = vdhcp_start;
-    vnameserver_addr = vnameserver;
+    slirp->vdhcp_startaddr = vdhcp_start;
+    slirp->vnameserver_addr = vnameserver;
 
-    register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, NULL);
+    register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
 }
 
 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -269,6 +259,7 @@ static void updtime(void)
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds)
 {
+    Slirp *slirp = &slirp_instance;
     struct socket *so, *so_next;
     int nfds;
 
@@ -291,10 +282,11 @@ void slirp_select_fill(int *pnfds,
 		 * *_slowtimo needs calling if there are IP fragments
 		 * in the fragment queue, or there are TCP connections active
 		 */
-		do_slowtimo = ((tcb.so_next != &tcb) ||
-                (&ipq.ip_link != ipq.ip_link.next));
+		do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
+		    (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
 
-		for (so = tcb.so_next; so != &tcb; so = so_next) {
+		for (so = slirp->tcb.so_next; so != &slirp->tcb;
+		     so = so_next) {
 			so_next = so->so_next;
 
 			/*
@@ -351,7 +343,8 @@ void slirp_select_fill(int *pnfds,
 		/*
 		 * UDP sockets
 		 */
-		for (so = udb.so_next; so != &udb; so = so_next) {
+		for (so = slirp->udb.so_next; so != &slirp->udb;
+		     so = so_next) {
 			so_next = so->so_next;
 
 			/*
@@ -387,6 +380,7 @@ void slirp_select_fill(int *pnfds,
 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                        int select_error)
 {
+    Slirp *slirp = &slirp_instance;
     struct socket *so, *so_next;
     int ret;
 
@@ -405,12 +399,12 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 	 * See if anything has timed out
 	 */
 		if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
-			tcp_fasttimo();
+			tcp_fasttimo(slirp);
 			time_fasttimo = 0;
 		}
 		if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
-			ip_slowtimo();
-			tcp_slowtimo();
+			ip_slowtimo(slirp);
+			tcp_slowtimo(slirp);
 			last_slowtimo = curtime;
 		}
 
@@ -421,7 +415,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 		/*
 		 * Check TCP sockets
 		 */
-		for (so = tcb.so_next; so != &tcb; so = so_next) {
+		for (so = slirp->tcb.so_next; so != &slirp->tcb;
+		     so = so_next) {
 			so_next = so->so_next;
 
 			/*
@@ -538,7 +533,8 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 		 * Incoming packets are sent straight away, they're not buffered.
 		 * Incoming UDP data isn't buffered either.
 		 */
-		for (so = udb.so_next; so != &udb; so = so_next) {
+		for (so = slirp->udb.so_next; so != &slirp->udb;
+		     so = so_next) {
 			so_next = so->so_next;
 
 			if (so->s != -1 && FD_ISSET(so->s, readfds)) {
@@ -550,8 +546,9 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 	/*
 	 * See if we can start outputting
 	 */
-	if (if_queued)
-	   if_start();
+	if (slirp->if_queued) {
+	    if_start(slirp);
+	}
 
 	/* clear global file descriptor sets.
 	 * these reside on the stack in vl.c
@@ -596,7 +593,7 @@ struct arphdr
 	uint32_t		ar_tip	;		/* target IP address		*/
 } __attribute__((packed));
 
-static void arp_input(const uint8_t *pkt, int pkt_len)
+static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
 {
     struct ethhdr *eh = (struct ethhdr *)pkt;
     struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
@@ -609,18 +606,19 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
     ar_op = ntohs(ah->ar_op);
     switch(ar_op) {
     case ARPOP_REQUEST:
-        if ((ah->ar_tip & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
-            if (ah->ar_tip == vnameserver_addr.s_addr ||
-                ah->ar_tip == vhost_addr.s_addr)
+        if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
+            slirp->vnetwork_addr.s_addr) {
+            if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
+                ah->ar_tip == slirp->vhost_addr.s_addr)
                 goto arp_ok;
-            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+            for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
                 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
                     goto arp_ok;
             }
             return;
         arp_ok:
             /* XXX: make an ARP request to have the client address */
-            memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
+            memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
 
             /* ARP request for alias/dns mac address */
             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
@@ -642,9 +640,9 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
         break;
     case ARPOP_REPLY:
         /* reply to request of client mac address ? */
-        if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
-            ah->ar_sip == client_ipaddr.s_addr) {
-            memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
+        if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
+            ah->ar_sip == slirp->client_ipaddr.s_addr) {
+            memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
         }
         break;
     default:
@@ -654,6 +652,7 @@ static void arp_input(const uint8_t *pkt, int pkt_len)
 
 void slirp_input(const uint8_t *pkt, int pkt_len)
 {
+    Slirp *slirp = &slirp_instance;
     struct mbuf *m;
     int proto;
 
@@ -663,10 +662,10 @@ void slirp_input(const uint8_t *pkt, int pkt_len)
     proto = ntohs(*(uint16_t *)(pkt + 12));
     switch(proto) {
     case ETH_P_ARP:
-        arp_input(pkt, pkt_len);
+        arp_input(slirp, pkt, pkt_len);
         break;
     case ETH_P_IP:
-        m = m_get();
+        m = m_get(slirp);
         if (!m)
             return;
         /* Note: we add to align the IP header */
@@ -687,7 +686,7 @@ void slirp_input(const uint8_t *pkt, int pkt_len)
 }
 
 /* output the IP packet to the ethernet device */
-void if_encap(const uint8_t *ip_data, int ip_data_len)
+void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
 {
     uint8_t buf[1600];
     struct ethhdr *eh = (struct ethhdr *)buf;
@@ -695,7 +694,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
     if (ip_data_len + ETH_HLEN > sizeof(buf))
         return;
     
-    if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
+    if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
         uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
         struct ethhdr *reh = (struct ethhdr *)arp_req;
         struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
@@ -708,7 +707,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
            will retry sending its packet. */
         memset(reh->h_dest, 0xff, ETH_ALEN);
         memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
-        memcpy(&reh->h_source[2], &vhost_addr, 4);
+        memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
         reh->h_proto = htons(ETH_P_ARP);
         rah->ar_hrd = htons(1);
         rah->ar_pro = htons(ETH_P_IP);
@@ -717,20 +716,20 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
         rah->ar_op = htons(ARPOP_REQUEST);
         /* source hw addr */
         memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
-        memcpy(&rah->ar_sha[2], &vhost_addr, 4);
+        memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
         /* source IP */
-        rah->ar_sip = vhost_addr.s_addr;
+        rah->ar_sip = slirp->vhost_addr.s_addr;
         /* target hw addr (none) */
         memset(rah->ar_tha, 0, ETH_ALEN);
         /* target IP */
         rah->ar_tip = iph->ip_dst.s_addr;
-        client_ipaddr = iph->ip_dst;
+        slirp->client_ipaddr = iph->ip_dst;
         slirp_output(arp_req, sizeof(arp_req));
     } else {
-        memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
+        memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
         memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
         /* XXX: not correct */
-        memcpy(&eh->h_source[2], &vhost_addr, 4);
+        memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
         eh->h_proto = htons(ETH_P_IP);
         memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
         slirp_output(buf, ip_data_len + ETH_HLEN);
@@ -740,8 +739,9 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
 /* Drop host forwarding rule, return 0 if found. */
 int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
 {
+    Slirp *slirp = &slirp_instance;
     struct socket *so;
-    struct socket *head = (is_udp ? &udb : &tcb);
+    struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
     struct sockaddr_in addr;
     int port = htons(host_port);
     socklen_t addr_len;
@@ -764,16 +764,18 @@ int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
 int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
                       struct in_addr guest_addr, int guest_port)
 {
+    Slirp *slirp = &slirp_instance;
+
     if (!guest_addr.s_addr) {
-        guest_addr = vdhcp_startaddr;
+        guest_addr = slirp->vdhcp_startaddr;
     }
     if (is_udp) {
-        if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
-                        htons(guest_port), SS_HOSTFWD))
+        if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
+                        guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
             return -1;
     } else {
-        if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
-                        htons(guest_port), SS_HOSTFWD))
+        if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
+                        guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
             return -1;
     }
     return 0;
@@ -782,16 +784,19 @@ int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
 int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
                    int guest_port)
 {
+    Slirp *slirp = &slirp_instance;
+
     if (!guest_addr.s_addr) {
-        guest_addr.s_addr =
-            vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr);
+        guest_addr.s_addr = slirp->vnetwork_addr.s_addr |
+            (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
     }
-    if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
-        guest_addr.s_addr == vhost_addr.s_addr ||
-        guest_addr.s_addr == vnameserver_addr.s_addr) {
+    if ((guest_addr.s_addr & slirp->vnetwork_mask.s_addr) !=
+        slirp->vnetwork_addr.s_addr ||
+        guest_addr.s_addr == slirp->vhost_addr.s_addr ||
+        guest_addr.s_addr == slirp->vnameserver_addr.s_addr) {
         return -1;
     }
-    return add_exec(&exec_list, do_pty, (char *)args, guest_addr,
+    return add_exec(&slirp->exec_list, do_pty, (char *)args, guest_addr,
                     htons(guest_port));
 }
 
@@ -806,11 +811,11 @@ ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
 }
 
 static struct socket *
-slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
+slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
 {
     struct socket *so;
 
-    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+    for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
         if (so->so_faddr.s_addr == guest_addr.s_addr &&
             htons(so->so_fport) == guest_port) {
             return so;
@@ -821,10 +826,11 @@ slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
 
 size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
 {
+	Slirp *slirp = &slirp_instance;
 	struct iovec iov[2];
 	struct socket *so;
 
-	so = slirp_find_ctl_socket(guest_addr, guest_port);
+	so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
 
 	if (!so || so->so_state & SS_NOFDREF)
 		return 0;
@@ -838,8 +844,9 @@ size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
 void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
                        const uint8_t *buf, int size)
 {
+    Slirp *slirp = &slirp_instance;
     int ret;
-    struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
+    struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
 
     if (!so)
         return;
@@ -928,12 +935,14 @@ static void slirp_socket_save(QEMUFile *f, struct socket *so)
 
 static void slirp_state_save(QEMUFile *f, void *opaque)
 {
+    Slirp *slirp = opaque;
     struct ex_list *ex_ptr;
 
-    for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+    for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
         if (ex_ptr->ex_pty == 3) {
             struct socket *so;
-            so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
+            so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
+                                       ntohs(ex_ptr->ex_fport));
             if (!so)
                 continue;
 
@@ -942,7 +951,7 @@ static void slirp_state_save(QEMUFile *f, void *opaque)
         }
     qemu_put_byte(f, 0);
 
-    qemu_put_be16(f, ip_id);
+    qemu_put_be16(f, slirp->ip_id);
 }
 
 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
@@ -1041,12 +1050,13 @@ static int slirp_socket_load(QEMUFile *f, struct socket *so)
 
 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
 {
+    Slirp *slirp = opaque;
     struct ex_list *ex_ptr;
     int r;
 
     while ((r = qemu_get_byte(f))) {
         int ret;
-        struct socket *so = socreate();
+        struct socket *so = socreate(slirp);
 
         if (!so)
             return -ENOMEM;
@@ -1056,11 +1066,11 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
         if (ret < 0)
             return ret;
 
-        if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) !=
-            vnetwork_addr.s_addr) {
+        if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
+            slirp->vnetwork_addr.s_addr) {
             return -EINVAL;
         }
-        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_pty == 3 &&
                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
                 so->so_fport == ex_ptr->ex_fport) {
@@ -1074,7 +1084,7 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
     }
 
     if (version_id >= 2) {
-        ip_id = qemu_get_be16(f);
+        slirp->ip_id = qemu_get_be16(f);
     }
 
     return 0;
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 063e5f6..b1e8d4e 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -185,6 +185,7 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 
 #include "debug.h"
 
+#include "libslirp.h"
 #include "ip.h"
 #include "tcp.h"
 #include "tcp_timer.h"
@@ -204,14 +205,67 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 
 #include "bootp.h"
 #include "tftp.h"
-#include "libslirp.h"
+
+struct Slirp {
+    /* virtual network configuration */
+    struct in_addr vnetwork_addr;
+    struct in_addr vnetwork_mask;
+    struct in_addr vhost_addr;
+    struct in_addr vdhcp_startaddr;
+    struct in_addr vnameserver_addr;
+
+    /* ARP cache for the guest IP addresses (XXX: allow many entries) */
+    uint8_t client_ethaddr[6];
+
+    struct in_addr client_ipaddr;
+    char client_hostname[33];
+
+    int restricted;
+    struct timeval tt;
+    struct ex_list *exec_list;
+
+    /* mbuf states */
+    struct mbuf m_freelist, m_usedlist;
+    int mbuf_alloced;
+
+    /* if states */
+    int if_queued;          /* number of packets queued so far */
+    struct mbuf if_fastq;   /* fast queue (for interactive data) */
+    struct mbuf if_batchq;  /* queue for non-interactive data */
+    struct mbuf *next_m;    /* pointer to next mbuf to output */
+
+    /* ip states */
+    struct ipq ipq;         /* ip reass. queue */
+    u_int16_t ip_id;        /* ip packet ctr, for ids */
+
+    /* bootp/dhcp states */
+    BOOTPClient bootp_clients[NB_BOOTP_CLIENTS];
+    char *bootp_filename;
+
+    /* tcp states */
+    struct socket tcb;
+    struct socket *tcp_last_so;
+    tcp_seq tcp_iss;        /* tcp initial send seq # */
+    u_int32_t tcp_now;      /* for RFC 1323 timestamps */
+
+    /* udp states */
+    struct socket udb;
+    struct socket *udp_last_so;
+
+    /* tftp states */
+    char *tftp_prefix;
+    struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
+
+};
+
+extern Slirp slirp_instance;
 
 #ifndef NULL
 #define NULL (void *)0
 #endif
 
 #ifndef FULL_BOLT
-void if_start _P((void));
+void if_start _P((Slirp *));
 #else
 void if_start _P((struct ttys *));
 #endif
@@ -257,13 +311,13 @@ void lprint _P((const char *, ...));
 int cksum(struct mbuf *m, int len);
 
 /* if.c */
-void if_init _P((void));
+void if_init _P((Slirp *));
 void if_output _P((struct socket *, struct mbuf *));
 
 /* ip_input.c */
-void ip_init _P((void));
+void ip_init _P((Slirp *));
 void ip_input _P((struct mbuf *));
-void ip_slowtimo _P((void));
+void ip_slowtimo _P((Slirp *));
 void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
 
 /* ip_output.c */
@@ -278,7 +332,7 @@ int tcp_output _P((register struct tcpcb *));
 void tcp_setpersist _P((register struct tcpcb *));
 
 /* tcp_subr.c */
-void tcp_init _P((void));
+void tcp_init _P((Slirp *));
 void tcp_template _P((struct tcpcb *));
 void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
 struct tcpcb * tcp_newtcpcb _P((struct socket *));
diff --git a/slirp/socket.c b/slirp/socket.c
index f7b212f..d8fbe89 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -41,7 +41,7 @@ solookup(struct socket *head, struct in_addr laddr, u_int lport,
  * insque() it into the correct linked-list
  */
 struct socket *
-socreate(void)
+socreate(Slirp *slirp)
 {
   struct socket *so;
 
@@ -50,6 +50,7 @@ socreate(void)
     memset(so, 0, sizeof(struct socket));
     so->so_state = SS_NOFDREF;
     so->s = -1;
+    so->slirp = slirp;
   }
   return(so);
 }
@@ -60,15 +61,17 @@ socreate(void)
 void
 sofree(struct socket *so)
 {
+  Slirp *slirp = so->slirp;
+
   if (so->so_emu==EMU_RSH && so->extra) {
 	sofree(so->extra);
 	so->extra=NULL;
   }
-  if (so == tcp_last_so)
-    tcp_last_so = &tcb;
-  else if (so == udp_last_so)
-    udp_last_so = &udb;
-
+  if (so == slirp->tcp_last_so) {
+      slirp->tcp_last_so = &slirp->tcb;
+  } else if (so == slirp->udp_last_so) {
+      slirp->udp_last_so = &slirp->udb;
+  }
   m_free(so->so_m);
 
   if(so->so_next && so->so_prev)
@@ -473,7 +476,10 @@ sorecvfrom(struct socket *so)
           int n;
 #endif
 
-	  if (!(m = m_get())) return;
+	  m = m_get(so->slirp);
+	  if (!m) {
+	      return;
+	  }
 	  m->m_data += IF_MAXLINKHDR;
 
 	  /*
@@ -533,6 +539,7 @@ sorecvfrom(struct socket *so)
 int
 sosendto(struct socket *so, struct mbuf *m)
 {
+	Slirp *slirp = so->slirp;
 	int ret;
 	struct sockaddr_in addr;
 
@@ -541,10 +548,10 @@ sosendto(struct socket *so, struct mbuf *m)
 	DEBUG_ARG("m = %lx", (long)m);
 
         addr.sin_family = AF_INET;
-	if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
-	    vnetwork_addr.s_addr) {
+	if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+	    slirp->vnetwork_addr.s_addr) {
 	  /* It's an alias */
-	  if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
+	  if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
 	    addr.sin_addr = dns_addr;
 	  } else {
 	    addr.sin_addr = loopback_addr;
@@ -576,7 +583,8 @@ sosendto(struct socket *so, struct mbuf *m)
  * Listen for incoming TCP connections
  */
 struct socket *
-tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags)
+tcp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,
+           u_int lport, int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
@@ -590,7 +598,8 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags
 	DEBUG_ARG("lport = %d", lport);
 	DEBUG_ARG("flags = %x", flags);
 
-	if ((so = socreate()) == NULL) {
+	so = socreate(slirp);
+	if (!so) {
 	  return NULL;
 	}
 
@@ -599,7 +608,7 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags
 		free(so);
 		return NULL;
 	}
-	insque(so,&tcb);
+	insque(so, &slirp->tcb);
 
 	/*
 	 * SS_FACCEPTONCE sockets must time out.
@@ -637,7 +646,7 @@ tcp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport, int flags
 	getsockname(s,(struct sockaddr *)&addr,&addrlen);
 	so->so_fport = addr.sin_port;
 	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = vhost_addr;
+	   so->so_faddr = slirp->vhost_addr;
 	else
 	   so->so_faddr = addr.sin_addr;
 
diff --git a/slirp/socket.h b/slirp/socket.h
index 4db2147..dcf2743 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -20,6 +20,8 @@ struct socket {
 
   int s;                           /* The actual socket */
 
+  Slirp *slirp;			   /* managing slirp instance */
+
 			/* XXX union these with not-yet-used sbuf params */
   struct mbuf *so_m;	           /* Pointer to the original SYN packet,
 				    * for non-blocking connect()'s, and
@@ -72,10 +74,8 @@ struct socket {
 #define SS_HOSTFWD		0x1000	/* Socket describes host->guest forwarding */
 #define SS_INCOMING		0x2000	/* Connection was initiated by a host on the internet */
 
-extern struct socket tcb;
-
 struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
-struct socket * socreate _P((void));
+struct socket * socreate _P((Slirp *));
 void sofree _P((struct socket *));
 int soread _P((struct socket *));
 void sorecvoob _P((struct socket *));
@@ -83,7 +83,8 @@ int sosendoob _P((struct socket *));
 int sowrite _P((struct socket *));
 void sorecvfrom _P((struct socket *));
 int sosendto _P((struct socket *, struct mbuf *));
-struct socket * tcp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
+struct socket * tcp_listen _P((Slirp *, u_int32_t, u_int, u_int32_t, u_int,
+                               int));
 void soisfconnecting _P((register struct socket *));
 void soisfconnected _P((register struct socket *));
 void sofwdrain _P((struct socket *));
diff --git a/slirp/tcp.h b/slirp/tcp.h
index 4a18ed8..c65ed43 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -38,8 +38,6 @@ typedef	u_int32_t	tcp_seq;
 #define      PR_SLOWHZ       2               /* 2 slow timeouts per second (approx) */
 #define      PR_FASTHZ       5               /* 5 fast timeouts per second (not important) */
 
-extern struct socket *tcp_last_so;
-
 #define TCP_SNDSPACE 8192
 #define TCP_RCVSPACE 8192
 
@@ -163,6 +161,4 @@ struct tcphdr {
 
 #define TCP_ISSINCR     (125*1024)      /* increment for tcp_iss each second */
 
-extern tcp_seq tcp_iss;                /* tcp initial send seq # */
-
 #endif
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index b7a67e5..47cf0ad 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -41,12 +41,7 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
-struct socket tcb;
-
 #define	TCPREXMTTHRESH 3
-struct	socket *tcp_last_so = &tcb;
-
-tcp_seq tcp_iss;                /* tcp initial send seq # */
 
 #define TCP_PAWS_IDLE	(24 * 24 * 60 * 60 * PR_SLOWHZ)
 
@@ -233,6 +228,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	u_long tiwin;
 	int ret;
     struct ex_list *ex_ptr;
+    Slirp *slirp;
 
 	DEBUG_CALL("tcp_input");
 	DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
@@ -243,6 +239,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	 */
 	if (m == NULL) {
 		so = inso;
+		slirp = so->slirp;
 
 		/* Re-set a few variables */
 		tp = sototcpcb(so);
@@ -254,6 +251,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 
 		goto cont_conn;
 	}
+	slirp = m->slirp;
 
 	/*
 	 * Get IP and TCP header together in first mbuf.
@@ -318,8 +316,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 	m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 
-    if (slirp_restrict) {
-        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+    if (slirp->restricted) {
+        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_fport == ti->ti_dport &&
                 ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
                 break;
@@ -332,15 +330,15 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	 * Locate pcb for segment.
 	 */
 findso:
-	so = tcp_last_so;
+	so = slirp->tcp_last_so;
 	if (so->so_fport != ti->ti_dport ||
 	    so->so_lport != ti->ti_sport ||
 	    so->so_laddr.s_addr != ti->ti_src.s_addr ||
 	    so->so_faddr.s_addr != ti->ti_dst.s_addr) {
-		so = solookup(&tcb, ti->ti_src, ti->ti_sport,
+		so = solookup(&slirp->tcb, ti->ti_src, ti->ti_sport,
 			       ti->ti_dst, ti->ti_dport);
 		if (so)
-			tcp_last_so = so;
+			slirp->tcp_last_so = so;
 	}
 
 	/*
@@ -360,7 +358,7 @@ findso:
 	  if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
 	    goto dropwithreset;
 
-	  if ((so = socreate()) == NULL)
+	  if ((so = socreate(slirp)) == NULL)
 	    goto dropwithreset;
 	  if (tcp_attach(so) < 0) {
 	    free(so); /* Not sofree (if it failed, it's not insqued) */
@@ -555,12 +553,13 @@ findso:
 	   * If this is destined for the control address, then flag to
 	   * tcp_ctl once connected, otherwise connect
 	   */
-	  if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
-	      vnetwork_addr.s_addr) {
-	    if (so->so_faddr.s_addr != vhost_addr.s_addr &&
-		so->so_faddr.s_addr != vnameserver_addr.s_addr) {
+	  if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+	      slirp->vnetwork_addr.s_addr) {
+	    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
+		so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
 		/* May be an add exec */
-		for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+		for (ex_ptr = slirp->exec_list; ex_ptr;
+		     ex_ptr = ex_ptr->ex_next) {
 		  if(ex_ptr->ex_fport == so->so_fport &&
 		     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
 		    so->so_state |= SS_CTL;
@@ -631,8 +630,8 @@ findso:
 	  if (iss)
 	    tp->iss = iss;
 	  else
-	    tp->iss = tcp_iss;
-	  tcp_iss += TCP_ISSINCR/2;
+	    tp->iss = slirp->tcp_iss;
+	  slirp->tcp_iss += TCP_ISSINCR/2;
 	  tp->irs = ti->ti_seq;
 	  tcp_sendseqinit(tp);
 	  tcp_rcvseqinit(tp);
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 686e90d..0d6011a 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -290,7 +290,7 @@ send:
 	 * the template for sends on this connection.
 	 */
 	if (len) {
-		m = m_get();
+		m = m_get(so->slirp);
 		if (m == NULL) {
 			error = 1;
 			goto out;
@@ -310,7 +310,7 @@ send:
 		if (off + len == so->so_snd.sb_cc)
 			flags |= TH_PUSH;
 	} else {
-		m = m_get();
+		m = m_get(so->slirp);
 		if (m == NULL) {
 			error = 1;
 			goto out;
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 868382a..51b3834 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -48,10 +48,11 @@
  * Tcp initialization
  */
 void
-tcp_init(void)
+tcp_init(Slirp *slirp)
 {
-	tcp_iss = 1;		/* wrong */
-	tcb.so_next = tcb.so_prev = &tcb;
+    slirp->tcp_iss = 1;		/* wrong */
+    slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb;
+    slirp->tcp_last_so = &slirp->tcb;
 }
 
 /*
@@ -116,7 +117,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 	if (tp)
 		win = sbspace(&tp->t_socket->so_rcv);
         if (m == NULL) {
-		if ((m = m_get()) == NULL)
+		if ((m = m_get(tp->t_socket->slirp)) == NULL)
 			return;
 		tlen = 0;
 		m->m_data += IF_MAXLINKHDR;
@@ -237,6 +238,7 @@ tcp_close(struct tcpcb *tp)
 {
 	register struct tcpiphdr *t;
 	struct socket *so = tp->t_socket;
+	Slirp *slirp = so->slirp;
 	register struct mbuf *m;
 
 	DEBUG_CALL("tcp_close");
@@ -253,8 +255,8 @@ tcp_close(struct tcpcb *tp)
 	free(tp);
         so->so_tcpcb = NULL;
 	/* clobber input socket cache if we're closing the cached connection */
-	if (so == tcp_last_so)
-		tcp_last_so = &tcb;
+	if (so == slirp->tcp_last_so)
+		slirp->tcp_last_so = &slirp->tcb;
 	closesocket(so->s);
 	sbfree(&so->so_rcv);
 	sbfree(&so->so_snd);
@@ -317,6 +319,7 @@ tcp_sockclosed(struct tcpcb *tp)
  */
 int tcp_fconnect(struct socket *so)
 {
+  Slirp *slirp = so->slirp;
   int ret=0;
 
   DEBUG_CALL("tcp_fconnect");
@@ -333,9 +336,10 @@ int tcp_fconnect(struct socket *so)
     setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
 
     addr.sin_family = AF_INET;
-    if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
+    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+        slirp->vnetwork_addr.s_addr) {
       /* It's an alias */
-      if (so->so_faddr.s_addr == vnameserver_addr.s_addr) {
+      if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
 	addr.sin_addr = dns_addr;
       } else {
 	addr.sin_addr = loopback_addr;
@@ -375,6 +379,7 @@ int tcp_fconnect(struct socket *so)
 void
 tcp_connect(struct socket *inso)
 {
+	Slirp *slirp = inso->slirp;
 	struct socket *so;
 	struct sockaddr_in addr;
 	socklen_t addrlen = sizeof(struct sockaddr_in);
@@ -392,7 +397,7 @@ tcp_connect(struct socket *inso)
 		/* FACCEPTONCE already have a tcpcb */
 		so = inso;
 	} else {
-		if ((so = socreate()) == NULL) {
+		if ((so = socreate(slirp)) == NULL) {
 			/* If it failed, get rid of the pending connection */
 			closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
 			return;
@@ -423,7 +428,7 @@ tcp_connect(struct socket *inso)
 	so->so_faddr = addr.sin_addr;
 	/* Translate connections from localhost to the real hostname */
 	if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
-	   so->so_faddr = vhost_addr;
+	   so->so_faddr = slirp->vhost_addr;
 
 	/* Close the accept() socket, set right state */
 	if (inso->so_state & SS_FACCEPTONCE) {
@@ -441,8 +446,8 @@ tcp_connect(struct socket *inso)
 
 	tp->t_state = TCPS_SYN_SENT;
 	tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
-	tp->iss = tcp_iss;
-	tcp_iss += TCP_ISSINCR/2;
+	tp->iss = slirp->tcp_iss;
+	slirp->tcp_iss += TCP_ISSINCR/2;
 	tcp_sendseqinit(tp);
 	tcp_output(tp);
 }
@@ -456,7 +461,7 @@ tcp_attach(struct socket *so)
 	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
 	   return -1;
 
-	insque(so, &tcb);
+	insque(so, &so->slirp->tcb);
 
 	return 0;
 }
@@ -539,6 +544,7 @@ tcp_tos(struct socket *so)
 int
 tcp_emu(struct socket *so, struct mbuf *m)
 {
+	Slirp *slirp = so->slirp;
 	u_int n1, n2, n3, n4, n5, n6;
         char buff[257];
 	u_int32_t laddr;
@@ -572,7 +578,9 @@ tcp_emu(struct socket *so, struct mbuf *m)
 					HTONS(n1);
 					HTONS(n2);
 					/* n2 is the one on our host */
-					for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
+					for (tmpso = slirp->tcb.so_next;
+					     tmpso != &slirp->tcb;
+					     tmpso = tmpso->so_next) {
 						if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
 						    tmpso->so_lport == n2 &&
 						    tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
@@ -608,9 +616,10 @@ tcp_emu(struct socket *so, struct mbuf *m)
 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 			lport = htons((n5 << 8) | (n6));
 
-			if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
+			                     lport, SS_FACCEPTONCE)) == NULL) {
 			   return 1;
-
+			}
 			n6 = ntohs(so->so_fport);
 
 			n5 = (n6 >> 8) & 0xff;
@@ -640,9 +649,10 @@ tcp_emu(struct socket *so, struct mbuf *m)
 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 			lport = htons((n5 << 8) | (n6));
 
-			if ((so = tcp_listen(INADDR_ANY, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
+			                     lport, SS_FACCEPTONCE)) == NULL) {
 			   return 1;
-
+			}
 			n6 = ntohs(so->so_fport);
 
 			n5 = (n6 >> 8) & 0xff;
@@ -680,7 +690,8 @@ tcp_emu(struct socket *so, struct mbuf *m)
 			lport += m->m_data[i] - '0';
 		}
 		if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
-		    (so = tcp_listen(INADDR_ANY, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
+		    (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr,
+		                     htons(lport), SS_FACCEPTONCE)) != NULL)
                     m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
                                         ntohs(so->so_fport)) + 1;
 		return 1;
@@ -695,27 +706,33 @@ tcp_emu(struct socket *so, struct mbuf *m)
 
 		/* The %256s is for the broken mIRC */
 		if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
-			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(slirp, INADDR_ANY, 0,
+			                     htonl(laddr), htons(lport),
+			                     SS_FACCEPTONCE)) == NULL) {
 				return 1;
-
+			}
 			m->m_len = bptr - m->m_data; /* Adjust length */
                         m->m_len += snprintf(bptr, m->m_hdr.mh_size,
                                              "DCC CHAT chat %lu %u%c\n",
                                              (unsigned long)ntohl(so->so_faddr.s_addr),
                                              ntohs(so->so_fport), 1);
 		} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
-			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(slirp, INADDR_ANY, 0,
+			                     htonl(laddr), htons(lport),
+			                     SS_FACCEPTONCE)) == NULL) {
 				return 1;
-
+			}
 			m->m_len = bptr - m->m_data; /* Adjust length */
                         m->m_len += snprintf(bptr, m->m_hdr.mh_size,
                                              "DCC SEND %s %lu %u %u%c\n", buff,
                                              (unsigned long)ntohl(so->so_faddr.s_addr),
                                              ntohs(so->so_fport), n1, 1);
 		} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
-			if ((so = tcp_listen(INADDR_ANY, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = tcp_listen(slirp, INADDR_ANY, 0,
+			                     htonl(laddr), htons(lport),
+			                     SS_FACCEPTONCE)) == NULL) {
 				return 1;
-
+			}
 			m->m_len = bptr - m->m_data; /* Adjust length */
                         m->m_len += snprintf(bptr, m->m_hdr.mh_size,
                                              "DCC MOVE %s %lu %u %u%c\n", buff,
@@ -828,7 +845,7 @@ tcp_emu(struct socket *so, struct mbuf *m)
 
 				/* try to get udp port between 6970 - 7170 */
 				for (p = 6970; p < 7071; p++) {
-					if (udp_listen(INADDR_ANY,
+					if (udp_listen(slirp, INADDR_ANY,
 						       htons(p),
 						       so->so_laddr.s_addr,
 						       htons(lport),
@@ -865,6 +882,7 @@ tcp_emu(struct socket *so, struct mbuf *m)
  */
 int tcp_ctl(struct socket *so)
 {
+    Slirp *slirp = so->slirp;
     struct sbuf *sb = &so->so_snd;
     struct ex_list *ex_ptr;
     int do_pty;
@@ -872,9 +890,9 @@ int tcp_ctl(struct socket *so)
     DEBUG_CALL("tcp_ctl");
     DEBUG_ARG("so = %lx", (long )so);
 
-    if (so->so_faddr.s_addr != vhost_addr.s_addr) {
+    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
         /* Check if it's pty_exec */
-        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
             if (ex_ptr->ex_fport == so->so_fport &&
                 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
                 if (ex_ptr->ex_pty == 3) {
diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c
index cd71572..556e32e 100644
--- a/slirp/tcp_timer.c
+++ b/slirp/tcp_timer.c
@@ -32,24 +32,22 @@
 
 #include <slirp.h>
 
-u_int32_t        tcp_now;                /* for RFC 1323 timestamps */
-
 static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
 
 /*
  * Fast timeout routine for processing delayed acks
  */
 void
-tcp_fasttimo(void)
+tcp_fasttimo(Slirp *slirp)
 {
 	register struct socket *so;
 	register struct tcpcb *tp;
 
 	DEBUG_CALL("tcp_fasttimo");
 
-	so = tcb.so_next;
+	so = slirp->tcb.so_next;
 	if (so)
-	for (; so != &tcb; so = so->so_next)
+	for (; so != &slirp->tcb; so = so->so_next)
 		if ((tp = (struct tcpcb *)so->so_tcpcb) &&
 		    (tp->t_flags & TF_DELACK)) {
 			tp->t_flags &= ~TF_DELACK;
@@ -64,7 +62,7 @@ tcp_fasttimo(void)
  * causes finite state machine actions if timers expire.
  */
 void
-tcp_slowtimo(void)
+tcp_slowtimo(Slirp *slirp)
 {
 	register struct socket *ip, *ipnxt;
 	register struct tcpcb *tp;
@@ -75,10 +73,10 @@ tcp_slowtimo(void)
 	/*
 	 * Search through tcb's and update active timers.
 	 */
-	ip = tcb.so_next;
+	ip = slirp->tcb.so_next;
 	if (ip == 0)
 	   return;
-	for (; ip != &tcb; ip = ipnxt) {
+	for (; ip != &slirp->tcb; ip = ipnxt) {
 		ipnxt = ip->so_next;
 		tp = sototcpcb(ip);
 		if (tp == 0)
@@ -96,8 +94,8 @@ tcp_slowtimo(void)
 tpgone:
 		;
 	}
-	tcp_iss += TCP_ISSINCR/PR_SLOWHZ;		/* increment iss */
-	tcp_now++;					/* for timestamps */
+	slirp->tcp_iss += TCP_ISSINCR/PR_SLOWHZ;	/* increment iss */
+	slirp->tcp_now++;				/* for timestamps */
 }
 
 /*
diff --git a/slirp/tcp_timer.h b/slirp/tcp_timer.h
index f648ed0..cfb06ff 100644
--- a/slirp/tcp_timer.h
+++ b/slirp/tcp_timer.h
@@ -120,8 +120,8 @@ extern const int tcp_backoff[];
 
 struct tcpcb;
 
-void tcp_fasttimo _P((void));
-void tcp_slowtimo _P((void));
+void tcp_fasttimo _P((Slirp *));
+void tcp_slowtimo _P((Slirp *));
 void tcp_canceltimers _P((struct tcpcb *));
 
 #endif
diff --git a/slirp/tcp_var.h b/slirp/tcp_var.h
index db0a9c9..4ffbe04 100644
--- a/slirp/tcp_var.h
+++ b/slirp/tcp_var.h
@@ -158,6 +158,4 @@ struct tcpcb {
 #define	TCP_REXMTVAL(tp) \
 	(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
 
-extern u_int32_t	tcp_now;		/* for RFC 1323 timestamps */
-
 #endif
diff --git a/slirp/tftp.c b/slirp/tftp.c
index 31a1e25..3b8643b 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -25,41 +25,31 @@
 #include <slirp.h>
 #include "qemu-common.h"
 
-struct tftp_session {
-    int in_use;
-    char *filename;
-
-    struct in_addr client_ip;
-    u_int16_t client_port;
-
-    int timestamp;
-};
-
-static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
-
-char *tftp_prefix;
+static inline int tftp_session_in_use(struct tftp_session *spt)
+{
+    return (spt->slirp != NULL);
+}
 
-static void tftp_session_update(struct tftp_session *spt)
+static inline void tftp_session_update(struct tftp_session *spt)
 {
     spt->timestamp = curtime;
-    spt->in_use = 1;
 }
 
 static void tftp_session_terminate(struct tftp_session *spt)
 {
-  qemu_free(spt->filename);
-  spt->in_use = 0;
+    qemu_free(spt->filename);
+    spt->slirp = NULL;
 }
 
-static int tftp_session_allocate(struct tftp_t *tp)
+static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
 {
   struct tftp_session *spt;
   int k;
 
   for (k = 0; k < TFTP_SESSIONS_MAX; k++) {
-    spt = &tftp_sessions[k];
+    spt = &slirp->tftp_sessions[k];
 
-    if (!spt->in_use)
+    if (!tftp_session_in_use(spt))
         goto found;
 
     /* sessions time out after 5 inactive seconds */
@@ -75,21 +65,22 @@ static int tftp_session_allocate(struct tftp_t *tp)
   memset(spt, 0, sizeof(*spt));
   memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));
   spt->client_port = tp->udp.uh_sport;
+  spt->slirp = slirp;
 
   tftp_session_update(spt);
 
   return k;
 }
 
-static int tftp_session_find(struct tftp_t *tp)
+static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
 {
   struct tftp_session *spt;
   int k;
 
   for (k = 0; k < TFTP_SESSIONS_MAX; k++) {
-    spt = &tftp_sessions[k];
+    spt = &slirp->tftp_sessions[k];
 
-    if (spt->in_use) {
+    if (tftp_session_in_use(spt)) {
       if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
 	if (spt->client_port == tp->udp.uh_sport) {
 	  return k;
@@ -133,7 +124,7 @@ static int tftp_send_oack(struct tftp_session *spt,
     struct tftp_t *tp;
     int n = 0;
 
-    m = m_get();
+    m = m_get(spt->slirp);
 
     if (!m)
 	return -1;
@@ -172,7 +163,7 @@ static void tftp_send_error(struct tftp_session *spt,
   struct tftp_t *tp;
   int nobytes;
 
-  m = m_get();
+  m = m_get(spt->slirp);
 
   if (!m) {
     goto out;
@@ -218,7 +209,7 @@ static int tftp_send_data(struct tftp_session *spt,
     return -1;
   }
 
-  m = m_get();
+  m = m_get(spt->slirp);
 
   if (!m) {
     return -1;
@@ -266,23 +257,23 @@ static int tftp_send_data(struct tftp_session *spt,
   return 0;
 }
 
-static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
+static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
 {
   struct tftp_session *spt;
   int s, k;
   size_t prefix_len;
   char *req_fname;
 
-  s = tftp_session_allocate(tp);
+  s = tftp_session_allocate(slirp, tp);
 
   if (s < 0) {
     return;
   }
 
-  spt = &tftp_sessions[s];
+  spt = &slirp->tftp_sessions[s];
 
   /* unspecifed prefix means service disabled */
-  if (!tftp_prefix) {
+  if (!slirp->tftp_prefix) {
       tftp_send_error(spt, 2, "Access violation", tp);
       return;
   }
@@ -292,9 +283,9 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
   pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
 
   /* prepend tftp_prefix */
-  prefix_len = strlen(tftp_prefix);
+  prefix_len = strlen(slirp->tftp_prefix);
   spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 1);
-  memcpy(spt->filename, tftp_prefix, prefix_len);
+  memcpy(spt->filename, slirp->tftp_prefix, prefix_len);
 
   /* get name */
   req_fname = spt->filename + prefix_len;
@@ -375,17 +366,17 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
   tftp_send_data(spt, 1, tp);
 }
 
-static void tftp_handle_ack(struct tftp_t *tp, int pktlen)
+static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
 {
   int s;
 
-  s = tftp_session_find(tp);
+  s = tftp_session_find(slirp, tp);
 
   if (s < 0) {
     return;
   }
 
-  if (tftp_send_data(&tftp_sessions[s],
+  if (tftp_send_data(&slirp->tftp_sessions[s],
 		     ntohs(tp->x.tp_data.tp_block_nr) + 1,
 		     tp) < 0) {
     return;
@@ -398,11 +389,11 @@ void tftp_input(struct mbuf *m)
 
   switch(ntohs(tp->tp_op)) {
   case TFTP_RRQ:
-    tftp_handle_rrq(tp, m->m_len);
+    tftp_handle_rrq(m->slirp, tp, m->m_len);
     break;
 
   case TFTP_ACK:
-    tftp_handle_ack(tp, m->m_len);
+    tftp_handle_ack(m->slirp, tp, m->m_len);
     break;
   }
 }
diff --git a/slirp/tftp.h b/slirp/tftp.h
index 8f2675e..1415c85 100644
--- a/slirp/tftp.h
+++ b/slirp/tftp.h
@@ -30,4 +30,14 @@ struct tftp_t {
   } x;
 };
 
+struct tftp_session {
+    Slirp *slirp;
+    char *filename;
+
+    struct in_addr client_ip;
+    u_int16_t client_port;
+
+    int timestamp;
+};
+
 void tftp_input(struct mbuf *m);
diff --git a/slirp/udp.c b/slirp/udp.c
index 240e1bf..e0a6693 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -41,17 +41,14 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
-struct socket udb;
-
 static u_int8_t udp_tos(struct socket *so);
 static void udp_emu(struct socket *so, struct mbuf *m);
 
-struct	socket *udp_last_so = &udb;
-
 void
-udp_init(void)
+udp_init(Slirp *slirp)
 {
-	udb.so_next = udb.so_prev = &udb;
+    slirp->udb.so_next = slirp->udb.so_prev = &slirp->udb;
+    slirp->udp_last_so = &slirp->udb;
 }
 /* m->m_data  points at ip packet header
  * m->m_len   length ip packet
@@ -60,6 +57,7 @@ udp_init(void)
 void
 udp_input(register struct mbuf *m, int iphlen)
 {
+	Slirp *slirp = m->slirp;
 	register struct ip *ip;
 	register struct udphdr *uh;
 	int len;
@@ -128,8 +126,9 @@ udp_input(register struct mbuf *m, int iphlen)
             goto bad;
         }
 
-        if (slirp_restrict)
+        if (slirp->restricted) {
             goto bad;
+        }
 
         /*
          *  handle TFTP
@@ -142,22 +141,23 @@ udp_input(register struct mbuf *m, int iphlen)
 	/*
 	 * Locate pcb for datagram.
 	 */
-	so = udp_last_so;
+	so = slirp->udp_last_so;
 	if (so->so_lport != uh->uh_sport ||
 	    so->so_laddr.s_addr != ip->ip_src.s_addr) {
 		struct socket *tmp;
 
-		for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
+		for (tmp = slirp->udb.so_next; tmp != &slirp->udb;
+		     tmp = tmp->so_next) {
 			if (tmp->so_lport == uh->uh_sport &&
 			    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
 				so = tmp;
 				break;
 			}
 		}
-		if (tmp == &udb) {
+		if (tmp == &slirp->udb) {
 		  so = NULL;
 		} else {
-		  udp_last_so = so;
+		  slirp->udp_last_so = so;
 		}
 	}
 
@@ -166,7 +166,10 @@ udp_input(register struct mbuf *m, int iphlen)
 	   * If there's no socket for this packet,
 	   * create one
 	   */
-	  if ((so = socreate()) == NULL) goto bad;
+	  so = socreate(slirp);
+	  if (!so) {
+	      goto bad;
+	  }
 	  if(udp_attach(so) == -1) {
 	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
 			errno,strerror(errno)));
@@ -279,15 +282,18 @@ int udp_output(struct socket *so, struct mbuf *m,
                struct sockaddr_in *addr)
 
 {
+    Slirp *slirp = so->slirp;
     struct sockaddr_in saddr, daddr;
 
     saddr = *addr;
-    if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
-        if ((so->so_faddr.s_addr & ~vnetwork_mask.s_addr) ==
-            ~vnetwork_mask.s_addr) {
-            saddr.sin_addr = vhost_addr;
+    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+        slirp->vnetwork_addr.s_addr) {
+        uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr;
+
+        if ((so->so_faddr.s_addr & inv_mask) == inv_mask) {
+            saddr.sin_addr = slirp->vhost_addr;
         } else if (addr->sin_addr.s_addr == loopback_addr.s_addr ||
-                   so->so_faddr.s_addr != vhost_addr.s_addr) {
+                   so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
             saddr.sin_addr = so->so_faddr;
         }
     }
@@ -323,7 +329,7 @@ udp_attach(struct socket *so)
     } else {
       /* success, insert in queue */
       so->so_expire = curtime + SO_EXPIRE;
-      insque(so,&udb);
+      insque(so, &so->slirp->udb);
     }
   }
   return(so->s);
@@ -595,20 +601,20 @@ struct cu_header {
 }
 
 struct socket *
-udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
-           int flags)
+udp_listen(Slirp *slirp, u_int32_t haddr, u_int hport, u_int32_t laddr,
+           u_int lport, int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
 	socklen_t addrlen = sizeof(struct sockaddr_in), opt = 1;
 
-	if ((so = socreate()) == NULL) {
-		free(so);
-		return NULL;
+	so = socreate(slirp);
+	if (!so) {
+	    return NULL;
 	}
 	so->s = socket(AF_INET,SOCK_DGRAM,0);
 	so->so_expire = curtime + SO_EXPIRE;
-	insque(so,&udb);
+	insque(so, &slirp->udb);
 
 	addr.sin_family = AF_INET;
 	addr.sin_addr.s_addr = haddr;
@@ -624,7 +630,7 @@ udp_listen(u_int32_t haddr, u_int hport, u_int32_t laddr, u_int lport,
 	so->so_fport = addr.sin_port;
 	if (addr.sin_addr.s_addr == 0 ||
 	    addr.sin_addr.s_addr == loopback_addr.s_addr) {
-	   so->so_faddr = vhost_addr;
+	   so->so_faddr = slirp->vhost_addr;
 	} else {
 	   so->so_faddr = addr.sin_addr;
 	}
diff --git a/slirp/udp.h b/slirp/udp.h
index 3eed14a..cc814a3 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -36,8 +36,6 @@
 #define UDP_TTL 0x60
 #define UDP_UDPDATALEN 16192
 
-extern struct socket *udp_last_so;
-
 /*
  * Udp protocol header.
  * Per RFC 768, September, 1981.
@@ -73,15 +71,15 @@ struct udpiphdr {
 #define UDPCTL_CHECKSUM         1       /* checksum UDP packets */
 #define UDPCTL_MAXID            2
 
-extern struct socket udb;
 struct mbuf;
 
-void udp_init _P((void));
+void udp_init _P((Slirp *));
 void udp_input _P((register struct mbuf *, int));
 int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
 int udp_attach _P((struct socket *));
 void udp_detach _P((struct socket *));
-struct socket * udp_listen _P((u_int32_t, u_int, u_int32_t, u_int, int));
+struct socket * udp_listen _P((Slirp *, u_int32_t, u_int, u_int32_t, u_int,
+                               int));
 int udp_output2(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos);

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 34/41] slirp: Enable multiple instances
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (30 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 33/41] slirp: Allocate/free stack instance dynamically Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 37/41] slirp: Improve error handling in slirp_smb Jan Kiszka
                   ` (9 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Once again this was a long journey to reach the destination: Allow to
instantiate slirp multiple times. But as in the past, the journey was
worthwhile, cleaning up, fixing and enhancing various parts of the user
space network stack along the way.

What is this particular change good for? Multiple slirps instances
allow separated user space networks for guests with multiple NICs. This
is already possible, but without any slirp support for the second
network, ie. without a chance to talk to that network from the host via
IP. We have a legacy guest system here that benefits from this slirp
enhancement, allowing us to run both of its NICs purely over
unprivileged user space IP stacks.

Another benefit of this patch is that it simply removes an artificial
restriction of the configuration space qemu is providing, avoiding
another source of surprises that users may face when playing with
possible setups.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c         |   37 +++++++++++++++++++------------------
 slirp/slirp.c |   23 ++++++++++++++---------
 slirp/slirp.h |    4 ++++
 3 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/net.c b/net.c
index 0c58124..0c1a99b 100644
--- a/net.c
+++ b/net.c
@@ -678,6 +678,7 @@ struct slirp_config_str {
 };
 
 typedef struct SlirpState {
+    TAILQ_ENTRY(SlirpState) entry;
     VLANClientState *vc;
     Slirp *slirp;
 } SlirpState;
@@ -685,7 +686,8 @@ typedef struct SlirpState {
 static struct slirp_config_str *slirp_configs;
 const char *legacy_tftp_prefix;
 const char *legacy_bootp_filename;
-static SlirpState *slirp_state;
+static TAILQ_HEAD(slirp_stacks, SlirpState) slirp_stacks =
+    TAILQ_HEAD_INITIALIZER(slirp_stacks);
 
 static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str,
                           int legacy_format);
@@ -734,7 +736,7 @@ static void net_slirp_cleanup(VLANClientState *vc)
     SlirpState *s = vc->opaque;
 
     slirp_cleanup(s->slirp);
-    slirp_state = NULL;
+    TAILQ_REMOVE(&slirp_stacks, s, entry);
     qemu_free(s);
 }
 
@@ -842,7 +844,7 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
     s = qemu_mallocz(sizeof(SlirpState));
     s->slirp = slirp_init(restricted, net, mask, host, vhostname,
                           tftp_export, bootfile, dhcp, dns, s);
-    slirp_state = s;
+    TAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
 
     while (slirp_configs) {
         struct slirp_config_str *config = slirp_configs;
@@ -881,7 +883,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
     int is_udp = 0;
     int err;
 
-    if (!slirp_state) {
+    if (TAILQ_EMPTY(&slirp_stacks)) {
         monitor_printf(mon, "user mode network stack not in use\n");
         return;
     }
@@ -908,7 +910,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
 
     host_port = atoi(p);
 
-    err = slirp_remove_hostfwd(slirp_state->slirp, is_udp,
+    err = slirp_remove_hostfwd(TAILQ_FIRST(&slirp_stacks)->slirp, is_udp,
                                host_addr, host_port);
 
     monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
@@ -984,19 +986,19 @@ static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str,
 
 void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str)
 {
-    if (!slirp_state) {
+    if (TAILQ_EMPTY(&slirp_stacks)) {
         monitor_printf(mon, "user mode network stack not in use\n");
         return;
     }
 
-    slirp_hostfwd(slirp_state, mon, redir_str, 0);
+    slirp_hostfwd(TAILQ_FIRST(&slirp_stacks), mon, redir_str, 0);
 }
 
 void net_slirp_redir(const char *redir_str)
 {
     struct slirp_config_str *config;
 
-    if (!slirp_state) {
+    if (TAILQ_EMPTY(&slirp_stacks)) {
         config = qemu_malloc(sizeof(*config));
         pstrcpy(config->str, sizeof(config->str), redir_str);
         config->flags = SLIRP_CFG_HOSTFWD | SLIRP_CFG_LEGACY;
@@ -1005,7 +1007,7 @@ void net_slirp_redir(const char *redir_str)
         return;
     }
 
-    slirp_hostfwd(slirp_state, NULL, redir_str, 1);
+    slirp_hostfwd(TAILQ_FIRST(&slirp_stacks), NULL, redir_str, 1);
 }
 
 #ifndef _WIN32
@@ -1106,8 +1108,8 @@ void net_slirp_smb(const char *exported_dir)
         exit(1);
     }
     legacy_smb_export = exported_dir;
-    if (slirp_state) {
-        slirp_smb(slirp_state, exported_dir, vserver_addr);
+    if (!TAILQ_EMPTY(&slirp_stacks)) {
+        slirp_smb(TAILQ_FIRST(&slirp_stacks), exported_dir, vserver_addr);
     }
 }
 
@@ -1198,13 +1200,12 @@ static void slirp_guestfwd(SlirpState *s, Monitor *mon, const char *config_str,
 
 void do_info_usernet(Monitor *mon)
 {
-    SlirpState *s = slirp_state;
+    SlirpState *s;
 
-    if (!s) {
-        return;
+    TAILQ_FOREACH(s, &slirp_stacks, entry) {
+        monitor_printf(mon, "VLAN %d (%s):\n", s->vc->vlan->id, s->vc->name);
+        slirp_connection_info(s->slirp, mon);
     }
-    monitor_printf(mon, "VLAN %d (%s):\n", s->vc->vlan->id, s->vc->name);
-    slirp_connection_info(s->slirp, mon);
 }
 
 #endif /* CONFIG_SLIRP */
@@ -2499,7 +2500,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
         qemu_free(smb_export);
         qemu_free(vsmbsrv);
     } else if (!strcmp(device, "channel")) {
-        if (!slirp_state) {
+        if (TAILQ_EMPTY(&slirp_stacks)) {
             struct slirp_config_str *config;
 
             config = qemu_malloc(sizeof(*config));
@@ -2508,7 +2509,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
             config->next = slirp_configs;
             slirp_configs = config;
         } else {
-            slirp_guestfwd(slirp_state, mon, p, 1);
+            slirp_guestfwd(TAILQ_FIRST(&slirp_stacks), mon, p, 1);
         }
         ret = 0;
     } else
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 43aba3d..fb666e6 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -47,7 +47,8 @@ u_int curtime;
 static u_int time_fasttimo, last_slowtimo;
 static int do_slowtimo;
 
-Slirp *slirp_instance;
+TAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
+    TAILQ_HEAD_INITIALIZER(slirp_instances);
 
 #ifdef _WIN32
 
@@ -223,20 +224,20 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
 
-    slirp_instance = slirp;
+    TAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
 
     return slirp;
 }
 
 void slirp_cleanup(Slirp *slirp)
 {
+    TAILQ_REMOVE(&slirp_instances, slirp, entry);
+
     unregister_savevm("slirp", slirp);
 
     qemu_free(slirp->tftp_prefix);
     qemu_free(slirp->bootp_filename);
     qemu_free(slirp);
-
-    slirp_instance = NULL;
 }
 
 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -269,11 +270,11 @@ static void updtime(void)
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds)
 {
-    Slirp *slirp = slirp_instance;
+    Slirp *slirp;
     struct socket *so, *so_next;
     int nfds;
 
-    if (!slirp_instance) {
+    if (TAILQ_EMPTY(&slirp_instances)) {
         return;
     }
 
@@ -288,11 +289,12 @@ void slirp_select_fill(int *pnfds,
 	 */
 	do_slowtimo = 0;
 
+	TAILQ_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) ||
+		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;
@@ -383,6 +385,7 @@ void slirp_select_fill(int *pnfds,
 				UPD_NFDS(so->s);
 			}
 		}
+	}
 
         *pnfds = nfds;
 }
@@ -390,11 +393,11 @@ void slirp_select_fill(int *pnfds,
 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                        int select_error)
 {
-    Slirp *slirp = slirp_instance;
+    Slirp *slirp;
     struct socket *so, *so_next;
     int ret;
 
-    if (!slirp_instance) {
+    if (TAILQ_EMPTY(&slirp_instances)) {
         return;
     }
 
@@ -405,6 +408,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 	/* Update time */
 	updtime();
 
+    TAILQ_FOREACH(slirp, &slirp_instances, entry) {
 	/*
 	 * See if anything has timed out
 	 */
@@ -559,6 +563,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
 	if (slirp->if_queued) {
 	    if_start(slirp);
 	}
+    }
 
 	/* clear global file descriptor sets.
 	 * these reside on the stack in vl.c
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 5d8861c..920d7a6 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -185,6 +185,8 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 
 #include "debug.h"
 
+#include "sys-queue.h"
+
 #include "libslirp.h"
 #include "ip.h"
 #include "tcp.h"
@@ -207,6 +209,8 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
 #include "tftp.h"
 
 struct Slirp {
+    TAILQ_ENTRY(Slirp) entry;
+
     /* virtual network configuration */
     struct in_addr vnetwork_addr;
     struct in_addr vnetwork_mask;

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 39/41] net: Provide VLAN client lookup helper
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (33 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 36/41] slirp: Use shell to erase smb directory Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 32/41] slirp: Use internal state in interface Jan Kiszka
                   ` (6 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Introduce qemu_find_vlan_client_by_name for VLANClientState lookup based
on VLAN ID and client name. This is useful for monitor commands.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 hw/xen_nic.c |    2 +-
 net.c        |   44 ++++++++++++++++++++++++++++++++------------
 net.h        |    2 +-
 3 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/hw/xen_nic.c b/hw/xen_nic.c
index e4f71f7..4377ed1 100644
--- a/hw/xen_nic.c
+++ b/hw/xen_nic.c
@@ -301,7 +301,7 @@ static int net_init(struct XenDevice *xendev)
     if (netdev->mac == NULL)
 	return -1;
 
-    vlan = qemu_find_vlan(netdev->xendev.dev);
+    vlan = qemu_find_vlan(netdev->xendev.dev, 1);
     netdev->vs = qemu_new_vlan_client(vlan, "xen", NULL,
                                       net_rx_ok, net_rx_packet, NULL,
                                       NULL, netdev);
diff --git a/net.c b/net.c
index 917f72f..030c29b 100644
--- a/net.c
+++ b/net.c
@@ -389,6 +389,32 @@ VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque)
     return NULL;
 }
 
+static VLANClientState *
+qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
+                              const char *client_str)
+{
+    VLANState *vlan;
+    VLANClientState *vc;
+
+    vlan = qemu_find_vlan(vlan_id, 0);
+    if (!vlan) {
+        monitor_printf(mon, "unknown VLAN %d\n", vlan_id);
+        return NULL;
+    }
+
+    for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
+        if (!strcmp(vc->name, client_str)) {
+            break;
+        }
+    }
+    if (!vc) {
+        monitor_printf(mon, "can't find device %s on VLAN %d\n",
+                       client_str, vlan_id);
+    }
+
+    return vc;
+}
+
 int qemu_can_send_packet(VLANClientState *sender)
 {
     VLANState *vlan = sender->vlan;
@@ -2255,13 +2281,16 @@ static int net_dump_init(Monitor *mon, VLANState *vlan, const char *device,
 }
 
 /* find or alloc a new VLAN */
-VLANState *qemu_find_vlan(int id)
+VLANState *qemu_find_vlan(int id, int allocate)
 {
     VLANState **pvlan, *vlan;
     for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
         if (vlan->id == id)
             return vlan;
     }
+    if (!allocate) {
+        return NULL;
+    }
     vlan = qemu_mallocz(sizeof(VLANState));
     vlan->id = id;
     vlan->next = NULL;
@@ -2327,7 +2356,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
     if (get_param_value(buf, sizeof(buf), "vlan", p)) {
         vlan_id = strtol(buf, NULL, 0);
     }
-    vlan = qemu_find_vlan(vlan_id);
+    vlan = qemu_find_vlan(vlan_id, 1);
 
     if (get_param_value(buf, sizeof(buf), "name", p)) {
         name = qemu_strdup(buf);
@@ -2724,19 +2753,10 @@ void net_host_device_add(Monitor *mon, const char *device, const char *opts)
 
 void net_host_device_remove(Monitor *mon, int vlan_id, const char *device)
 {
-    VLANState *vlan;
     VLANClientState *vc;
 
-    vlan = qemu_find_vlan(vlan_id);
-
-    for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
-        if (!strcmp(vc->name, device)) {
-            break;
-        }
-    }
-
+    vc = qemu_find_vlan_client_by_name(mon, vlan_id, device);
     if (!vc) {
-        monitor_printf(mon, "can't find device %s\n", device);
         return;
     }
     if (!net_host_check_device(vc->model)) {
diff --git a/net.h b/net.h
index 7fcb49d..9fba4c6 100644
--- a/net.h
+++ b/net.h
@@ -51,7 +51,7 @@ struct VLANState {
     int delivering;
 };
 
-VLANState *qemu_find_vlan(int id);
+VLANState *qemu_find_vlan(int id, int allocate);
 VLANClientState *qemu_new_vlan_client(VLANState *vlan,
                                       const char *model,
                                       const char *name,

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 37/41] slirp: Improve error handling in slirp_smb
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (31 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 34/41] slirp: Enable multiple instances Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 36/41] slirp: Use shell to erase smb directory Jan Kiszka
                   ` (8 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Make sure for invocations from the monitor that slirp_smb properly
reports errors and doesn't terminate qemu.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   22 ++++++++++++----------
 1 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/net.c b/net.c
index edf7ca6..22b7080 100644
--- a/net.c
+++ b/net.c
@@ -697,7 +697,7 @@ static void slirp_guestfwd(SlirpState *s, Monitor *mon, const char *config_str,
 #ifndef _WIN32
 static const char *legacy_smb_export;
 
-static void slirp_smb(SlirpState *s, const char *exported_dir,
+static void slirp_smb(SlirpState *s, Monitor *mon, const char *exported_dir,
                       struct in_addr vserver_addr);
 #endif
 
@@ -864,7 +864,7 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
         smb_export = legacy_smb_export;
     }
     if (smb_export) {
-        slirp_smb(s, smb_export, smbsrv);
+        slirp_smb(s, mon, smb_export, smbsrv);
     }
 #endif
 
@@ -1023,7 +1023,7 @@ static void smb_exit(void)
     system(cmd);
 }
 
-static void slirp_smb(SlirpState* s, const char *exported_dir,
+static void slirp_smb(SlirpState* s, Monitor *mon, const char *exported_dir,
                       struct in_addr vserver_addr)
 {
     char smb_conf[1024];
@@ -1033,15 +1033,17 @@ static void slirp_smb(SlirpState* s, const char *exported_dir,
     /* XXX: better tmp dir construction */
     snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%ld", (long)getpid());
     if (mkdir(smb_dir, 0700) < 0) {
-        fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
-        exit(1);
+        config_error(mon, "could not create samba server dir '%s'\n", smb_dir);
+        return;
     }
     snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
 
     f = fopen(smb_conf, "w");
     if (!f) {
-        fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf);
-        exit(1);
+        smb_exit();
+        config_error(mon, "could not create samba server "
+                     "configuration file '%s'\n", smb_conf);
+        return;
     }
     fprintf(f,
             "[global]\n"
@@ -1071,8 +1073,7 @@ static void slirp_smb(SlirpState* s, const char *exported_dir,
              SMBD_COMMAND, smb_conf);
 
     if (slirp_add_exec(s->slirp, 0, smb_cmdline, vserver_addr, 139) < 0) {
-        fprintf(stderr, "conflicting/invalid smbserver address\n");
-        exit(1);
+        config_error(mon, "conflicting/invalid smbserver address\n");
     }
 }
 
@@ -1087,7 +1088,8 @@ void net_slirp_smb(const char *exported_dir)
     }
     legacy_smb_export = exported_dir;
     if (!TAILQ_EMPTY(&slirp_stacks)) {
-        slirp_smb(TAILQ_FIRST(&slirp_stacks), exported_dir, vserver_addr);
+        slirp_smb(TAILQ_FIRST(&slirp_stacks), NULL, exported_dir,
+                  vserver_addr);
     }
 }
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 38/41] slirp: Enable multi-instance support for the smb service
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (36 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 35/41] slirp: Save/restore bootp client states Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 31/41] slirp: Factor out internal state structure Jan Kiszka
                   ` (3 subsequent siblings)
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Push the smb state, smb_dir, into SlirpState and construct it in a way
that allows multiple smb instances (one per slirp stack). Remove the smb
directory on slirp cleanup instead of qemu termination. As VLAN clients
are also cleaned up on process termination, no feature is lost.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   50 ++++++++++++++++++++++++++++++--------------------
 1 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/net.c b/net.c
index 22b7080..917f72f 100644
--- a/net.c
+++ b/net.c
@@ -681,6 +681,9 @@ typedef struct SlirpState {
     TAILQ_ENTRY(SlirpState) entry;
     VLANClientState *vc;
     Slirp *slirp;
+#ifndef _WIN32
+    char smb_dir[128];
+#endif
 } SlirpState;
 
 static struct slirp_config_str *slirp_configs;
@@ -699,6 +702,9 @@ static const char *legacy_smb_export;
 
 static void slirp_smb(SlirpState *s, Monitor *mon, const char *exported_dir,
                       struct in_addr vserver_addr);
+static void slirp_smb_cleanup(SlirpState *s);
+#else
+static inline void slirp_smb_cleanup(SlirpState *s) { }
 #endif
 
 int slirp_can_output(void *opaque)
@@ -736,6 +742,7 @@ static void net_slirp_cleanup(VLANClientState *vc)
     SlirpState *s = vc->opaque;
 
     slirp_cleanup(s->slirp);
+    slirp_smb_cleanup(s);
     TAILQ_REMOVE(&slirp_stacks, s, entry);
     qemu_free(s);
 }
@@ -1012,35 +1019,38 @@ void net_slirp_redir(const char *redir_str)
 
 #ifndef _WIN32
 
-static char smb_dir[1024];
-
 /* automatic user mode samba server configuration */
-static void smb_exit(void)
+static void slirp_smb_cleanup(SlirpState *s)
 {
-    char cmd[1024];
+    char cmd[128];
 
-    snprintf(cmd, sizeof(cmd), "rm -rf %s", smb_dir);
-    system(cmd);
+    if (s->smb_dir[0] != '\0') {
+        snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir);
+        system(cmd);
+        s->smb_dir[0] = '\0';
+    }
 }
 
 static void slirp_smb(SlirpState* s, Monitor *mon, const char *exported_dir,
                       struct in_addr vserver_addr)
 {
-    char smb_conf[1024];
-    char smb_cmdline[1024];
+    static int instance;
+    char smb_conf[128];
+    char smb_cmdline[128];
     FILE *f;
 
-    /* XXX: better tmp dir construction */
-    snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%ld", (long)getpid());
-    if (mkdir(smb_dir, 0700) < 0) {
-        config_error(mon, "could not create samba server dir '%s'\n", smb_dir);
+    snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d",
+             (long)getpid(), instance++);
+    if (mkdir(s->smb_dir, 0700) < 0) {
+        config_error(mon, "could not create samba server dir '%s'\n",
+                     s->smb_dir);
         return;
     }
-    snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
+    snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf");
 
     f = fopen(smb_conf, "w");
     if (!f) {
-        smb_exit();
+        slirp_smb_cleanup(s);
         config_error(mon, "could not create samba server "
                      "configuration file '%s'\n", smb_conf);
         return;
@@ -1059,20 +1069,20 @@ static void slirp_smb(SlirpState* s, Monitor *mon, const char *exported_dir,
             "path=%s\n"
             "read only=no\n"
             "guest ok=yes\n",
-            smb_dir,
-            smb_dir,
-            smb_dir,
-            smb_dir,
-            smb_dir,
+            s->smb_dir,
+            s->smb_dir,
+            s->smb_dir,
+            s->smb_dir,
+            s->smb_dir,
             exported_dir
             );
     fclose(f);
-    atexit(smb_exit);
 
     snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
              SMBD_COMMAND, smb_conf);
 
     if (slirp_add_exec(s->slirp, 0, smb_cmdline, vserver_addr, 139) < 0) {
+        slirp_smb_cleanup(s);
         config_error(mon, "conflicting/invalid smbserver address\n");
     }
 }

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 41/41] slirp: Basic VLAN client info_str
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (39 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 40/41] slirp: Make hostfwd_add/remove multi-instance-aware Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:49 ` [Qemu-devel] Re: [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Anthony Liguori
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index 573179e..fb5fc24 100644
--- a/net.c
+++ b/net.c
@@ -903,7 +903,8 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
 
     s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL,
                                  net_slirp_cleanup, s);
-    s->vc->info_str[0] = '\0';
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+             "net=%s, restricted=%c", inet_ntoa(net), restricted ? 'y' : 'n');
     return 0;
 }
 

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] [PATCH 40/41] slirp: Make hostfwd_add/remove multi-instance-aware
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (38 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 31/41] slirp: Factor out internal state structure Jan Kiszka
@ 2009-06-24 12:42 ` Jan Kiszka
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 41/41] slirp: Basic VLAN client info_str Jan Kiszka
  2009-06-24 12:49 ` [Qemu-devel] Re: [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Anthony Liguori
  41 siblings, 0 replies; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 12:42 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel

Extend the syntax of hostfwd_add/remove to optionally take a tuple of
VLAN ID and slirp stack name. If those are omitted, the commands will
continue to work on the first registered slirp stack.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c           |   62 ++++++++++++++++++++++++++++++++++++++++++++++---------
 net.h           |    6 ++++-
 qemu-monitor.hx |    8 ++++---
 3 files changed, 60 insertions(+), 16 deletions(-)

diff --git a/net.c b/net.c
index 030c29b..573179e 100644
--- a/net.c
+++ b/net.c
@@ -907,23 +907,56 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
     return 0;
 }
 
-void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str)
+static SlirpState *slirp_lookup(Monitor *mon, const char *vlan,
+                                const char *stack)
+{
+    VLANClientState *vc;
+
+    if (vlan) {
+        vc = qemu_find_vlan_client_by_name(mon, strtol(vlan, NULL, 0), stack);
+        if (!vc) {
+            return NULL;
+        }
+        if (strcmp(vc->model, "user")) {
+            monitor_printf(mon, "invalid device specified\n");
+            return NULL;
+        }
+        return vc->opaque;
+    } else {
+        if (TAILQ_EMPTY(&slirp_stacks)) {
+            monitor_printf(mon, "user mode network stack not in use\n");
+            return NULL;
+        }
+        return TAILQ_FIRST(&slirp_stacks);
+    }
+}
+
+void net_slirp_hostfwd_remove(Monitor *mon, const char *arg1,
+                              const char *arg2, const char *arg3)
 {
     struct in_addr host_addr = { .s_addr = INADDR_ANY };
     int host_port;
     char buf[256] = "";
-    const char *p = src_str;
+    const char *src_str, *p;
+    SlirpState *s;
     int is_udp = 0;
     int err;
 
-    if (TAILQ_EMPTY(&slirp_stacks)) {
-        monitor_printf(mon, "user mode network stack not in use\n");
+    if (arg2) {
+        s = slirp_lookup(mon, arg1, arg2);
+        src_str = arg3;
+    } else {
+        s = slirp_lookup(mon, NULL, NULL);
+        src_str = arg1;
+    }
+    if (!s) {
         return;
     }
 
     if (!src_str || !src_str[0])
         goto fail_syntax;
 
+    p = src_str;
     get_str_sep(buf, sizeof(buf), &p, ':');
 
     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
@@ -966,7 +999,7 @@ static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str,
     char *end;
 
     p = redir_str;
-    if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+    if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
         goto fail_syntax;
     }
     if (!strcmp(buf, "tcp") || buf[0] == '\0') {
@@ -1017,14 +1050,23 @@ static void slirp_hostfwd(SlirpState *s, Monitor *mon, const char *redir_str,
     config_error(mon, "invalid host forwarding rule '%s'\n", redir_str);
 }
 
-void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str)
+void net_slirp_hostfwd_add(Monitor *mon, const char *arg1,
+                           const char *arg2, const char *arg3)
 {
-    if (TAILQ_EMPTY(&slirp_stacks)) {
-        monitor_printf(mon, "user mode network stack not in use\n");
-        return;
+    const char *redir_str;
+    SlirpState *s;
+
+    if (arg2) {
+        s = slirp_lookup(mon, arg1, arg2);
+        redir_str = arg3;
+    } else {
+        s = slirp_lookup(mon, NULL, NULL);
+        redir_str = arg1;
+    }
+    if (s) {
+        slirp_hostfwd(s, mon, redir_str, 0);
     }
 
-    slirp_hostfwd(TAILQ_FIRST(&slirp_stacks), mon, redir_str, 0);
 }
 
 void net_slirp_redir(const char *redir_str)
diff --git a/net.h b/net.h
index 9fba4c6..4dad82d 100644
--- a/net.h
+++ b/net.h
@@ -130,8 +130,10 @@ int net_client_init(Monitor *mon, const char *device, const char *p);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
 void net_slirp_smb(const char *exported_dir);
-void net_slirp_hostfwd_add(Monitor *mon, const char *redir_str);
-void net_slirp_hostfwd_remove(Monitor *mon, const char *src_str);
+void net_slirp_hostfwd_add(Monitor *mon, const char *arg1,
+                           const char *arg2, const char *arg3);
+void net_slirp_hostfwd_remove(Monitor *mon, const char *arg1,
+                              const char *arg2, const char *arg3);
 void net_slirp_redir(const char *redir_str);
 void net_cleanup(void);
 void net_client_check(void);
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index e320f9f..66c6ad9 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -536,11 +536,11 @@ Remove host VLAN client.
 ETEXI
 
 #ifdef CONFIG_SLIRP
-    { "hostfwd_add", "s", net_slirp_hostfwd_add,
-      "[tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
+    { "hostfwd_add", "ss?s?", net_slirp_hostfwd_add,
+      "[vlan_id name] [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport",
       "redirect TCP or UDP connections from host to guest (requires -net user)" },
-    { "hostfwd_remove", "s", net_slirp_hostfwd_remove,
-      "[tcp|udp]:[hostaddr]:hostport",
+    { "hostfwd_remove", "ss?s?", net_slirp_hostfwd_remove,
+      "[vlan_id name] [tcp|udp]:[hostaddr]:hostport",
       "remove host-to-guest TCP or UDP redirection" },
 #endif
 STEXI

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [Qemu-devel] Re: [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded
  2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
                   ` (40 preceding siblings ...)
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 41/41] slirp: Basic VLAN client info_str Jan Kiszka
@ 2009-06-24 12:49 ` Anthony Liguori
  41 siblings, 0 replies; 46+ messages in thread
From: Anthony Liguori @ 2009-06-24 12:49 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Mark McLoughlin, qemu-devel

Jan Kiszka wrote:
> The foundation of this series are the patches from my previous posting
> that didn't make it into upstream. But while reworking them, the series
> grow far beyond the previous approach, adding lots of fixes and cleanups
> to the slirp stack and its interfaces.
>
> One major contribution is that the virtual IP addresses used inside
> slirp VLANs are now (almost) freely configurable. This enables
> sophisticated virtual network setups, specifically with guests that
> depends on specific addresses.
>
> In this second step, the series also comes with support for multiple
> slirp instances per VM. Further contributions are
>  - proper dynamic slirp cleanup during runtime
>  - 'info usernet' command to dump slirp connection states
>  - reworked monitor commands hostfwd_add/remove (formerly known as
>    host_net_redir)
>  - save/restore fixes for slirp
>  - first larger code cleanup (more work required...)
>  - various small fixes
>
> The patches have been successfully tested against basic use cases:
> connections to/from the guests, redirections, tftp, multi-instance,
> save/restore. Moreover, they also passed successfull build tests
> against mingw32.
>
> Regarding the preferred flow: Mark, will you let this go through your
> network tree first? Currently the series is based on upstream/master,
> but I can rebase if required.
>   

I don't want to do this through a git pull.  I'd rather take this into 
my queue.

-- 
Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent
  2009-06-24 12:42 ` [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent Jan Kiszka
@ 2009-06-24 14:34   ` Filip Navara
  2009-06-24 14:48     ` Jan Kiszka
  0 siblings, 1 reply; 46+ messages in thread
From: Filip Navara @ 2009-06-24 14:34 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Mark McLoughlin, Anthony Liguori, qemu-devel

On Wed, Jun 24, 2009 at 2:42 PM, Jan Kiszka<jan.kiszka@siemens.com> wrote:
> Currently, ip_id is always initialized to 0 on slirp startup (despite
> the broken attempt to derive it from the clock). This is good for
> reproducibility. But it is not preserved across save/restore. This patch
> therefore drops the dead initialization code from ip_init and introduces
> ip_id to the persistent slirp state.
>
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>
>  slirp/ip_input.c |    1 -
>  slirp/slirp.c    |    8 +++++++-
>  2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/slirp/ip_input.c b/slirp/ip_input.c
> index 0356eb5..b07d3d5 100644
> --- a/slirp/ip_input.c
> +++ b/slirp/ip_input.c
> @@ -59,7 +59,6 @@ void
>  ip_init(void)
>  {
>        ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
> -       ip_id = tt.tv_sec & 0xffff;

You removed the ip_id initialization and now it's never initialized in
the code. That sounds wrong.

Best regards,
Filip Navara

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent
  2009-06-24 14:34   ` Filip Navara
@ 2009-06-24 14:48     ` Jan Kiszka
  2009-06-24 15:04       ` Filip Navara
  0 siblings, 1 reply; 46+ messages in thread
From: Jan Kiszka @ 2009-06-24 14:48 UTC (permalink / raw)
  To: Filip Navara; +Cc: Mark McLoughlin, Anthony Liguori, qemu-devel

Filip Navara wrote:
> On Wed, Jun 24, 2009 at 2:42 PM, Jan Kiszka<jan.kiszka@siemens.com> wrote:
>> Currently, ip_id is always initialized to 0 on slirp startup (despite
>> the broken attempt to derive it from the clock). This is good for
>> reproducibility. But it is not preserved across save/restore. This patch
>> therefore drops the dead initialization code from ip_init and introduces
>> ip_id to the persistent slirp state.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>
>>  slirp/ip_input.c |    1 -
>>  slirp/slirp.c    |    8 +++++++-
>>  2 files changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/slirp/ip_input.c b/slirp/ip_input.c
>> index 0356eb5..b07d3d5 100644
>> --- a/slirp/ip_input.c
>> +++ b/slirp/ip_input.c
>> @@ -59,7 +59,6 @@ void
>>  ip_init(void)
>>  {
>>        ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
>> -       ip_id = tt.tv_sec & 0xffff;
> 
> You removed the ip_id initialization and now it's never initialized in
> the code. That sounds wrong.

Thanks for having a look! All this slirp code is really hairy and no fun
to dig through.

But now to your remark: That removal is in fact not changing the
behavior. ip_id is also initialized to 0 afterwards. To understand this
one has to track the messy use of 'tt' across slirp. It is in fact
carrying the time at some point (when select_fill is invoked), but not
yet on ip_init.

I was thinking about fixing the above initialization to actually take
the current time and derive ip_id, but then I thought it might be better
to keep this for network traffic reproducibility across qemu starts.

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent
  2009-06-24 14:48     ` Jan Kiszka
@ 2009-06-24 15:04       ` Filip Navara
  0 siblings, 0 replies; 46+ messages in thread
From: Filip Navara @ 2009-06-24 15:04 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Mark McLoughlin, Anthony Liguori, qemu-devel

On Wed, Jun 24, 2009 at 4:48 PM, Jan Kiszka<jan.kiszka@siemens.com> wrote:
> Filip Navara wrote:
>> On Wed, Jun 24, 2009 at 2:42 PM, Jan Kiszka<jan.kiszka@siemens.com> wrote:
>>> Currently, ip_id is always initialized to 0 on slirp startup (despite
>>> the broken attempt to derive it from the clock). This is good for
>>> reproducibility. But it is not preserved across save/restore. This patch
>>> therefore drops the dead initialization code from ip_init and introduces
>>> ip_id to the persistent slirp state.
>>>
>>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>>> ---
>>>
>>>  slirp/ip_input.c |    1 -
>>>  slirp/slirp.c    |    8 +++++++-
>>>  2 files changed, 7 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/slirp/ip_input.c b/slirp/ip_input.c
>>> index 0356eb5..b07d3d5 100644
>>> --- a/slirp/ip_input.c
>>> +++ b/slirp/ip_input.c
>>> @@ -59,7 +59,6 @@ void
>>>  ip_init(void)
>>>  {
>>>        ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
>>> -       ip_id = tt.tv_sec & 0xffff;
>>
>> You removed the ip_id initialization and now it's never initialized in
>> the code. That sounds wrong.
>
> Thanks for having a look! All this slirp code is really hairy and no fun
> to dig through.

Totally agreed. At one point I was considering to replace it with
lwip, but I don't have the time necessary for that and it would be
hard to keep all the existing services (TFTP, DHCP, SMB) working.

> But now to your remark: That removal is in fact not changing the
> behavior. ip_id is also initialized to 0 afterwards. To understand this
> one has to track the messy use of 'tt' across slirp. It is in fact
> carrying the time at some point (when select_fill is invoked), but not
> yet on ip_init.

Ah, I didn't see that, makes sense. It actually explains what I saw
last week in the packet dump.

> I was thinking about fixing the above initialization to actually take
> the current time and derive ip_id, but then I thought it might be better
> to keep this for network traffic reproducibility across qemu starts.

Agreed.

Best regards,
Filip Navara

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2009-06-24 15:05 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-24 12:42 [Qemu-devel] [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 01/41] slirp: Drop redundant lines from udp_input Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 08/41] slirp: Fix port comparision in slirp_remove_hostfwd Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 02/41] slirp: Refactor tcp_ctl Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 04/41] Introduce get_next_param_value Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 03/41] Revert "User networking: Show active connections" Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 10/41] slirp: Bind support for host forwarding rules Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 09/41] slirp: Rework monitor commands for host forwarding Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 05/41] slirp: Move smb, redir, tftp and bootp parameters and -net channel Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 07/41] slirp: Rework external configuration interface Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 06/41] slirp: Rework internal configuration Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 16/41] slirp: Drop dead code Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 12/41] slirp: Explicitely mark host-forwarding sockets Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 19/41] slirp: Drop unused icmp_var.h Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 15/41] slirp: Add info usernet for dumping connection states Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 18/41] slirp: Cleanup and basic reanimation of debug code Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 13/41] slirp: Do not allow to remove non-hostfwd sockets Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 14/41] slirp: Mark sockets of incoming TCP connections Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 20/41] slirp: tftp: Cleanup tftp_prefix check Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 11/41] slirp: Prepare for persistent socket state flags Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 17/41] slirp: Drop statistic code Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 23/41] slirp: tftp: Rework filename handling Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 30/41] slirp: Drop link_up checks from if_output and slirp_socket_can_recv Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 22/41] slirp: tftp: Refactor tftp_handle_rrq Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 25/41] slirp: Make IP packet ID consistent Jan Kiszka
2009-06-24 14:34   ` Filip Navara
2009-06-24 14:48     ` Jan Kiszka
2009-06-24 15:04       ` Filip Navara
2009-06-24 12:42 ` [Qemu-devel] [PATCH 27/41] slirp: Kill slirp_is_inited Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 29/41] slirp: Clean up timeout handling around slirp_select_fill/poll Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 28/41] slirp: Drop redundant checks from slirp_output Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 24/41] slirp: Factor out one-time initialization Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 21/41] slirp: tftp: Clean up tftp_send_error Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 26/41] slirp: Clean up updtime Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 33/41] slirp: Allocate/free stack instance dynamically Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 34/41] slirp: Enable multiple instances Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 37/41] slirp: Improve error handling in slirp_smb Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 36/41] slirp: Use shell to erase smb directory Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 39/41] net: Provide VLAN client lookup helper Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 32/41] slirp: Use internal state in interface Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 35/41] slirp: Save/restore bootp client states Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 38/41] slirp: Enable multi-instance support for the smb service Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 31/41] slirp: Factor out internal state structure Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 40/41] slirp: Make hostfwd_add/remove multi-instance-aware Jan Kiszka
2009-06-24 12:42 ` [Qemu-devel] [PATCH 41/41] slirp: Basic VLAN client info_str Jan Kiszka
2009-06-24 12:49 ` [Qemu-devel] Re: [PATCH 00/41] Slirp Fixes and Enhancements - Reloaded Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).