qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] PATCH, RFC: Slirp improvements
@ 2007-10-20 18:42 Blue Swirl
  2007-10-23 17:42 ` [Qemu-devel] " Blue Swirl
  0 siblings, 1 reply; 2+ messages in thread
From: Blue Swirl @ 2007-10-20 18:42 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 525 bytes --]

Hi,

This patch makes the SLIRP library able to handle more than one
instance of itself by putting all globals inside a structure. Qemu
needs some rearrangement to make the VLANs separate. The patch is
loosely based on VirtualBox SLIRP changes but without the aHungarian
nNotation ugliness. There are some other changes too, for example
addition of "info slirp" monitor command. I tried to change the
mbuf/packet chaining to support 64-bit pointers on x86-64 but the
linking code is pretty hard to understand.

Any comments?

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: slirp.diff --]
[-- Type: text/x-diff; name=slirp.diff, Size: 183501 bytes --]

Index: qemu/slirp/bootp.c
===================================================================
--- qemu.orig/slirp/bootp.c	2007-10-20 07:33:35.000000000 +0000
+++ qemu/slirp/bootp.c	2007-10-20 13:10:08.000000000 +0000
@@ -25,20 +25,6 @@
 
 /* XXX: only DHCP is supported */
 
-#define NB_ADDR 16
-
-#define START_ADDR 15
-
-#define LEASE_TIME (24 * 3600)
-
-typedef struct {
-    uint8_t allocated;
-    uint8_t macaddr[6];
-} BOOTPClient;
-
-BOOTPClient bootp_clients[NB_ADDR];
-
-const char *bootp_filename;
 
 static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
 
@@ -49,37 +35,49 @@
 #define dprintf(fmt, args...)
 #endif
 
-static BOOTPClient *get_new_addr(struct in_addr *paddr)
+static BOOTPClient *get_new_addr(slirp_state_t *s, struct in_addr *paddr)
 {
     BOOTPClient *bc;
     int i;
 
     for(i = 0; i < NB_ADDR; i++) {
-        if (!bootp_clients[i].allocated)
+        if (!s->bootp_clients[i].allocated)
             goto found;
     }
     return NULL;
  found:
-    bc = &bootp_clients[i];
+    bc = &s->bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+    paddr->s_addr = htonl(ntohl(s->special_addr.s_addr) | (i + START_ADDR));
     return bc;
 }
 
-static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
+static void release_addr(slirp_state_t *s, struct in_addr *paddr)
+{
+    int i;
+
+    i = ntohl(paddr->s_addr) - START_ADDR - ntohl(s->special_addr.s_addr);
+    if (i >= NB_ADDR)
+        return;
+    memset(s->bootp_clients[i].macaddr, '\0', 6);
+    s->bootp_clients[i].allocated = 0;
+}
+
+static BOOTPClient *find_addr(slirp_state_t *s, 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))
+        if (!memcmp(macaddr, s->bootp_clients[i].macaddr, 6))
             goto found;
     }
     return NULL;
  found:
-    bc = &bootp_clients[i];
+    bc = &s->bootp_clients[i];
     bc->allocated = 1;
-    paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
+    paddr->s_addr = htonl(ntohl(s->special_addr.s_addr) | (i + START_ADDR));
     return bc;
 }
 
@@ -124,7 +122,7 @@
     }
 }
 
-static void bootp_reply(struct bootp_t *bp)
+static void bootp_reply(slirp_state_t *s, struct bootp_t *bp)
 {
     BOOTPClient *bc;
     struct mbuf *m;
@@ -141,29 +139,39 @@
     if (dhcp_msg_type == 0)
         dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
 
+    if (dhcp_msg_type == DHCPRELEASE) {
+        release_addr(s, &bp->bp_ciaddr);
+        dprintf("released addr=%08x\n", ntohl(bp->bp_ciaddr.s_addr));
+        /* This message is not to be answered in any way. */
+        return;
+    }
     if (dhcp_msg_type != DHCPDISCOVER &&
         dhcp_msg_type != DHCPREQUEST)
         return;
     /* XXX: this is a hack to get the client mac address */
-    memcpy(client_ethaddr, bp->bp_hwaddr, 6);
+    memcpy(s->client_ethaddr, bp->bp_hwaddr, 6);
 
-    if ((m = m_get()) == NULL)
+    if ((m = m_get(s)) == NULL)
         return;
-    m->m_data += if_maxlinkhdr;
+    m->m_data += s->if_maxlinkhdr;
     rbp = (struct bootp_t *)m->m_data;
     m->m_data += sizeof(struct udpiphdr);
     memset(rbp, 0, sizeof(struct bootp_t));
 
     if (dhcp_msg_type == DHCPDISCOVER) {
-    new_addr:
-        bc = get_new_addr(&daddr.sin_addr);
+        /* Do not allocate a new lease for clients that forgot that they had a lease. */
+        bc = find_addr(s, &daddr.sin_addr, bp->bp_hwaddr);
         if (!bc) {
-            dprintf("no address left\n");
-            return;
+    new_addr:
+            bc = get_new_addr(s, &daddr.sin_addr);
+            if (!bc) {
+                dprintf("no address left\n");
+                return;
+            }
+            memcpy(bc->macaddr, s->client_ethaddr, 6);
         }
-        memcpy(bc->macaddr, client_ethaddr, 6);
     } else {
-        bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
+        bc = find_addr(s, &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) */
@@ -171,12 +179,12 @@
         }
     }
 
-    if (bootp_filename)
-        snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename);
+    if (s->bootp_filename)
+        snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", s->bootp_filename);
 
     dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
 
-    saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
+    saddr.sin_addr.s_addr = htonl(ntohl(s->special_addr.s_addr) | CTL_ALIAS);
     saddr.sin_port = htons(BOOTP_SERVER);
 
     daddr.sin_port = htons(BOOTP_CLIENT);
@@ -225,7 +233,7 @@
 
         *q++ = RFC1533_DNS;
         *q++ = 4;
-        dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
+        dns_addr.s_addr = htonl(ntohl(s->special_addr.s_addr) | CTL_DNS);
         memcpy(q, &dns_addr, 4);
         q += 4;
 
@@ -235,11 +243,11 @@
         memcpy(q, &val, 4);
         q += 4;
 
-        if (*slirp_hostname) {
-            val = strlen(slirp_hostname);
+        if (*s->slirp_hostname) {
+            val = strlen(s->slirp_hostname);
             *q++ = RFC1533_HOSTNAME;
             *q++ = val;
-            memcpy(q, slirp_hostname, val);
+            memcpy(q, s->slirp_hostname, val);
             q += val;
         }
     }
@@ -247,14 +255,16 @@
 
     m->m_len = sizeof(struct bootp_t) -
         sizeof(struct ip) - sizeof(struct udphdr);
-    udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+    /* Reply to the broadcast address, as some clients perform paranoid checks. */
+    daddr.sin_addr.s_addr = INADDR_BROADCAST;
+    udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 }
 
-void bootp_input(struct mbuf *m)
+void bootp_input(slirp_state_t *s, struct mbuf *m)
 {
     struct bootp_t *bp = mtod(m, struct bootp_t *);
 
     if (bp->bp_op == BOOTP_REQUEST) {
-        bootp_reply(bp);
+        bootp_reply(s, bp);
     }
 }
Index: qemu/slirp/bootp.h
===================================================================
--- qemu.orig/slirp/bootp.h	2007-10-20 07:33:35.000000000 +0000
+++ qemu/slirp/bootp.h	2007-10-20 08:17:51.000000000 +0000
@@ -71,6 +71,7 @@
 #define DHCPOFFER		2
 #define DHCPREQUEST		3
 #define DHCPACK			5
+#define DHCPRELEASE		7
 
 #define RFC1533_VENDOR_MAJOR	0
 #define RFC1533_VENDOR_MINOR	0
@@ -110,4 +111,4 @@
     uint8_t bp_vend[DHCP_OPT_LEN];
 };
 
-void bootp_input(struct mbuf *m);
+void bootp_input(slirp_state_t *s, struct mbuf *m);
Index: qemu/slirp/ctl.h
===================================================================
--- qemu.orig/slirp/ctl.h	2007-10-20 07:33:35.000000000 +0000
+++ qemu/slirp/ctl.h	2007-10-20 11:46:46.000000000 +0000
@@ -2,6 +2,4 @@
 #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"
+#define CTL_BROADCAST   255
Index: qemu/slirp/if.c
===================================================================
--- qemu.orig/slirp/if.c	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/if.c	2007-10-20 12:47:04.000000000 +0000
@@ -7,22 +7,10 @@
 
 #include <slirp.h>
 
-int if_mtu, if_mru;
-int if_comp;
-int if_maxlinkhdr;
-int     if_queued = 0;                  /* Number of packets queued so far */
-int     if_thresh = 10;                 /* Number of packets queued before we start sending
-					 * (to prevent allocing too many mbufs) */
-
-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))
 
-void
-ifs_insque(ifm, ifmhead)
-	struct mbuf *ifm, *ifmhead;
+static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
 {
 	ifm->ifs_next = ifmhead->ifs_next;
 	ifmhead->ifs_next = ifm;
@@ -30,16 +18,14 @@
 	ifm->ifs_next->ifs_prev = ifm;
 }
 
-void
-ifs_remque(ifm)
-	struct mbuf *ifm;
+static void ifs_remque(struct mbuf *ifm)
 {
 	ifm->ifs_prev->ifs_next = ifm->ifs_next;
 	ifm->ifs_next->ifs_prev = ifm->ifs_prev;
 }
 
 void
-if_init()
+if_init(slirp_state_t *s)
 {
 #if 0
 	/*
@@ -47,21 +33,23 @@
 	 * and 8 bytes for PPP, but need to have it on an 8byte boundary
 	 */
 #ifdef USE_PPP
-	if_maxlinkhdr = 48;
+	s->if_maxlinkhdr = 48;
 #else
-	if_maxlinkhdr = 40;
+	s->if_maxlinkhdr = 40;
 #endif
 #else
         /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
-        if_maxlinkhdr = 2 + 14 + 40;
+        s->if_maxlinkhdr = 2 + 14 + 40;
 #endif
-	if_mtu = 1500;
-	if_mru = 1500;
-	if_comp = IF_AUTOCOMP;
-	if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
-	if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
+        s->if_queued = 0;
+        s->if_thresh = 10;
+	s->if_mtu = 1500;
+	s->if_mru = 1500;
+	s->if_comp = IF_AUTOCOMP;
+	s->if_fastq.ifq_next = s->if_fastq.ifq_prev = &s->if_fastq;
+	s->if_batchq.ifq_next = s->if_batchq.ifq_prev = &s->if_batchq;
         //	sl_compress_init(&comp_s);
-	next_m = &if_batchq;
+	s->next_m = &s->if_batchq;
 }
 
 #if 0
@@ -118,7 +106,7 @@
 	if (if_n <= 0) {
 		if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
 			if (ttyp->up)
-			   link_up--;
+			   s->link_up--;
 			tty_detached(ttyp, 0);
 		}
 		return;
@@ -157,9 +145,7 @@
  * it'll temporarily get downgraded to the batchq)
  */
 void
-if_output(so, ifm)
-	struct socket *so;
-	struct mbuf *ifm;
+if_output(slirp_state_t *s, struct socket *so, struct mbuf *ifm)
 {
 	struct mbuf *ifq;
 	int on_fastq = 1;
@@ -174,7 +160,7 @@
 	 * XXX Shouldn't need this, gotta change dtom() etc.
 	 */
 	if (ifm->m_flags & M_USEDLIST) {
-		remque(ifm);
+		remque(s, ifm);
 		ifm->m_flags &= ~M_USEDLIST;
 	}
 
@@ -185,7 +171,7 @@
 	 * 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 = s->if_batchq.ifq_prev; ifq != &s->if_batchq; ifq = ifq->ifq_prev) {
 		if (so == ifq->ifq_so) {
 			/* A match! */
 			ifm->ifq_so = so;
@@ -196,7 +182,7 @@
 
 	/* No match, check which queue to put it on */
 	if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
-		ifq = if_fastq.ifq_prev;
+		ifq = s->if_fastq.ifq_prev;
 		on_fastq = 1;
 		/*
 		 * Check if this packet is a part of the last
@@ -208,15 +194,15 @@
 			goto diddit;
 		}
 	} else
-		ifq = if_batchq.ifq_prev;
+		ifq = s->if_batchq.ifq_prev;
 
 	/* Create a new doubly linked list for this session */
 	ifm->ifq_so = so;
 	ifs_init(ifm);
-	insque(ifm, ifq);
+	insque(s, ifm, ifq);
 
 diddit:
-	++if_queued;
+	++s->if_queued;
 
 	if (so) {
 		/* Update *_queued */
@@ -233,10 +219,10 @@
 				 (so->so_nqueued - so->so_queued) >= 3)) {
 
 			/* Remove from current queue... */
-			remque(ifm->ifs_next);
+			remque(s, ifm->ifs_next);
 
 			/* ...And insert in the new.  That'll teach ya! */
-			insque(ifm->ifs_next, &if_batchq);
+			insque(s, ifm->ifs_next, &s->if_batchq);
 		}
 	}
 
@@ -244,9 +230,9 @@
 	/*
 	 * This prevents us from malloc()ing too many mbufs
 	 */
-	if (link_up) {
+	if (s->link_up) {
 		/* if_start will check towrite */
-		if_start();
+		if_start(s);
 	}
 #endif
 }
@@ -264,44 +250,44 @@
  * to the first, etc. etc.
  */
 void
-if_start(void)
+if_start(slirp_state_t *s)
 {
 	struct mbuf *ifm, *ifqt;
 
 	DEBUG_CALL("if_start");
 
-	if (if_queued == 0)
+	if (s->if_queued == 0)
 	   return; /* Nothing to do */
 
  again:
         /* check if we can really output */
-        if (!slirp_can_output())
+        if (!slirp_can_output(s->user))
             return;
 
 	/*
 	 * 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 (s->if_fastq.ifq_next != &s->if_fastq) {
+		ifm = s->if_fastq.ifq_next;
 	} else {
 		/* Nothing on fastq, see if next_m is valid */
-		if (next_m != &if_batchq)
-		   ifm = next_m;
+		if (s->next_m != &s->if_batchq)
+		   ifm = s->next_m;
 		else
-		   ifm = if_batchq.ifq_next;
+		   ifm = s->if_batchq.ifq_next;
 
 		/* Set which packet to send on next iteration */
-		next_m = ifm->ifq_next;
+		s->next_m = ifm->ifq_next;
 	}
 	/* Remove it from the queue */
 	ifqt = ifm->ifq_prev;
-	remque(ifm);
-	--if_queued;
+	remque(s, ifm);
+	--s->if_queued;
 
 	/* If there are more packets for this session, re-queue them */
 	if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
-		insque(ifm->ifs_next, ifqt);
+		insque(s, ifm->ifs_next, ifqt);
 		ifs_remque(ifm);
 	}
 
@@ -313,10 +299,10 @@
 	}
 
 	/* Encapsulate the packet for sending */
-        if_encap(ifm->m_data, ifm->m_len);
+        if_encap(s, (const uint8_t *)ifm->m_data, ifm->m_len);
 
-        m_free(ifm);
+        m_free(s, ifm);
 
-	if (if_queued)
+	if (s->if_queued)
 	   goto again;
 }
Index: qemu/slirp/ip.h
===================================================================
--- qemu.orig/slirp/ip.h	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/ip.h	2007-10-20 08:17:51.000000000 +0000
@@ -305,9 +305,5 @@
 	u_long	ips_unaligned;		/* times the ip packet was not aligned */
 };
 
-extern struct	ipstat	ipstat;
-extern struct	ipq	ipq;			/* ip reass. queue */
-extern u_int16_t	ip_id;				/* ip packet ctr, for ids */
-extern int	ip_defttl;			/* default IP ttl */
 
 #endif
Index: qemu/slirp/ip_icmp.c
===================================================================
--- qemu.orig/slirp/ip_icmp.c	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/ip_icmp.c	2007-10-20 13:14:00.000000000 +0000
@@ -37,14 +37,13 @@
 #include "slirp.h"
 #include "ip_icmp.h"
 
-struct icmpstat icmpstat;
 
 /* The message sent when emulating PING */
-/* Be nice and tell them it's just a psuedo-ping packet */
-char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
+/* 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";
 
 /* list of actions for icmp_error() on RX of an icmp message */
-static int icmp_flush[19] = {
+static const int icmp_flush[19] = {
 /*  ECHO REPLY (0)  */   0,
 		         1,
 		         1,
@@ -70,9 +69,7 @@
  * Process a received ICMP message.
  */
 void
-icmp_input(m, hlen)
-     struct mbuf *m;
-     int hlen;
+icmp_input(slirp_state_t *s, struct mbuf *m, int hlen)
 {
   register struct icmp *icp;
   register struct ip *ip=mtod(m, struct ip *);
@@ -83,16 +80,16 @@
   DEBUG_ARG("m = %lx", (long )m);
   DEBUG_ARG("m_len = %d", m->m_len);
 
-  icmpstat.icps_received++;
+  s->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 */
-    icmpstat.icps_tooshort++;
+    s->icmpstat.icps_tooshort++;
   freeit:
-    m_freem(m);
+    m_freem(s, m);
     goto end_error;
   }
 
@@ -100,7 +97,7 @@
   m->m_data += hlen;
   icp = mtod(m, struct icmp *);
   if (cksum(m, icmplen)) {
-    icmpstat.icps_checksum++;
+    s->icmpstat.icps_checksum++;
     goto freeit;
   }
   m->m_len += hlen;
@@ -114,17 +111,17 @@
   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) {
-      icmp_reflect(m);
+    if (ip->ip_dst.s_addr == s->alias_addr.s_addr) {
+      icmp_reflect(s, m);
     } else {
       struct socket *so;
       struct sockaddr_in addr;
       if ((so = socreate()) == NULL) goto freeit;
-      if(udp_attach(so) == -1) {
+      if(udp_attach(s, so) == -1) {
 	DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
 		    errno,strerror(errno)));
-	sofree(so);
-	m_free(m);
+	sofree(s, so);
+	m_free(s, m);
 	goto end_error;
       }
       so->so_m = m;
@@ -138,15 +135,15 @@
 
       /* 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 & htonl(0xffffff00)) == s->special_addr.s_addr) {
 	/* It's an alias */
 	switch(ntohl(so->so_faddr.s_addr) & 0xff) {
 	case CTL_DNS:
-	  addr.sin_addr = dns_addr;
+	  addr.sin_addr = s->dns_addr;
 	  break;
 	case CTL_ALIAS:
 	default:
-	  addr.sin_addr = loopback_addr;
+	  addr.sin_addr = s->loopback_addr;
 	  break;
 	}
       } else {
@@ -157,8 +154,8 @@
 		(struct sockaddr *)&addr, sizeof(addr)) == -1) {
 	DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
 		    errno,strerror(errno)));
-	icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
-	udp_detach(so);
+	icmp_error(s, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
+	udp_detach(s, so);
       }
     } /* if ip->ip_dst.s_addr == alias_addr.s_addr */
     break;
@@ -170,13 +167,13 @@
   case ICMP_TSTAMP:
   case ICMP_MASKREQ:
   case ICMP_REDIRECT:
-    icmpstat.icps_notsupp++;
-    m_freem(m);
+    s->icmpstat.icps_notsupp++;
+    m_freem(s, m);
     break;
 
   default:
-    icmpstat.icps_badtype++;
-    m_freem(m);
+    s->icmpstat.icps_badtype++;
+    m_freem(s, m);
   } /* swith */
 
 end_error:
@@ -204,13 +201,8 @@
  */
 
 #define ICMP_MAXDATALEN (IP_MSS-28)
-void
-icmp_error(msrc, type, code, minsize, message)
-     struct mbuf *msrc;
-     u_char type;
-     u_char code;
-     int minsize;
-     char *message;
+void icmp_error(slirp_state_t *s, struct mbuf *msrc, u_char type, u_char code,
+                int minsize, const char *message)
 {
   unsigned hlen, shlen, s_ip_len;
   register struct ip *ip;
@@ -247,10 +239,13 @@
   }
 
   /* make a copy */
-  if(!(m=m_get())) goto end_error;               /* get mbuf */
+  if (!(m = m_get(s)))
+      goto end_error;               /* get mbuf */
+
   { 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);
+    if (new_m_size > m->m_size)
+        m_inc(m, new_m_size);
   }
   memcpy(m->m_data, msrc->m_data, msrc->m_len);
   m->m_len = msrc->m_len;                        /* copy msrc to m */
@@ -310,11 +305,11 @@
   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 = s->alias_addr;
 
-  (void ) ip_output((struct socket *)NULL, m);
+  (void ) ip_output(s, (struct socket *)NULL, m);
 
-  icmpstat.icps_reflect++;
+  s->icmpstat.icps_reflect++;
 
 end_error:
   return;
@@ -325,8 +320,7 @@
  * Reflect the ip packet back to the source
  */
 void
-icmp_reflect(m)
-     struct mbuf *m;
+icmp_reflect(slirp_state_t *s, struct mbuf *m)
 {
   register struct ip *ip = mtod(m, struct ip *);
   int hlen = ip->ip_hl << 2;
@@ -369,7 +363,7 @@
     ip->ip_src = icmp_dst;
   }
 
-  (void ) ip_output((struct socket *)NULL, m);
+  (void ) ip_output(s, (struct socket *)NULL, m);
 
-  icmpstat.icps_reflect++;
+  s->icmpstat.icps_reflect++;
 }
Index: qemu/slirp/ip_icmp.h
===================================================================
--- qemu.orig/slirp/ip_icmp.h	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/ip_icmp.h	2007-10-20 13:15:27.000000000 +0000
@@ -157,8 +157,9 @@
 	(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
 	(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
 
-void icmp_input _P((struct mbuf *, int));
-void icmp_error _P((struct mbuf *, u_char, u_char, int, char *));
-void icmp_reflect _P((struct mbuf *));
+void icmp_input(slirp_state_t *s, struct mbuf *m, int hlen);
+void icmp_error(slirp_state_t *s, struct mbuf *msrc, u_char type, u_char code,
+                int minsize, const char *message);
+void icmp_reflect(slirp_state_t *s, struct mbuf *m);
 
 #endif
Index: qemu/slirp/ip_input.c
===================================================================
--- qemu.orig/slirp/ip_input.c	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/ip_input.c	2007-10-20 13:18:38.000000000 +0000
@@ -45,22 +45,25 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
-int ip_defttl;
-struct ipstat ipstat;
-struct ipq ipq;
+
+static struct ip *ip_reass(slirp_state_t *s, register struct ipasfrag *ip,
+                           register struct ipq *fp);
+static void ip_freef(slirp_state_t *s, struct ipq *fp);
+static void ip_enq(slirp_state_t *s, register struct ipasfrag *p,
+                   register struct ipasfrag *prev);
+static void ip_deq(slirp_state_t *s, register struct ipasfrag *p);
 
 /*
  * IP initialization: fill in IP protocol switch table.
  * All protocols not implemented in kernel go to raw IP protocol handler.
  */
 void
-ip_init()
+ip_init(slirp_state_t *s)
 {
-	ipq.next = ipq.prev = (ipqp_32)&ipq;
-	ip_id = tt.tv_sec & 0xffff;
-	udp_init();
-	tcp_init();
-	ip_defttl = IPDEFTTL;
+	s->ipq.next = s->ipq.prev = (ipqp_32)&(s->ipq);
+	s->ip_id = s->tt.tv_sec & 0xffff;
+	udp_init(s);
+	tcp_init(s);
 }
 
 /*
@@ -68,8 +71,7 @@
  * try to reassemble.  Process options.  Pass to next level.
  */
 void
-ip_input(m)
-	struct mbuf *m;
+ip_input(slirp_state_t *s, struct mbuf *m)
 {
 	register struct ip *ip;
 	int hlen;
@@ -78,23 +80,23 @@
 	DEBUG_ARG("m = %lx", (long)m);
 	DEBUG_ARG("m_len = %d", m->m_len);
 
-	ipstat.ips_total++;
+	s->ipstat.ips_total++;
 
 	if (m->m_len < sizeof (struct ip)) {
-		ipstat.ips_toosmall++;
+		s->ipstat.ips_toosmall++;
 		return;
 	}
 
 	ip = mtod(m, struct ip *);
 
 	if (ip->ip_v != IPVERSION) {
-		ipstat.ips_badvers++;
+		s->ipstat.ips_badvers++;
 		goto bad;
 	}
 
 	hlen = ip->ip_hl << 2;
 	if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
-	  ipstat.ips_badhlen++;                     /* or packet too short */
+	  s->ipstat.ips_badhlen++;                     /* or packet too short */
 	  goto bad;
 	}
 
@@ -103,7 +105,7 @@
 	 * if (ip->ip_sum) {
 	 */
 	if(cksum(m,hlen)) {
-	  ipstat.ips_badsum++;
+	  s->ipstat.ips_badsum++;
 	  goto bad;
 	}
 
@@ -112,7 +114,7 @@
 	 */
 	NTOHS(ip->ip_len);
 	if (ip->ip_len < hlen) {
-		ipstat.ips_badlen++;
+		s->ipstat.ips_badlen++;
 		goto bad;
 	}
 	NTOHS(ip->ip_id);
@@ -125,7 +127,7 @@
 	 * Drop packet if shorter than we expect.
 	 */
 	if (m->m_len < ip->ip_len) {
-		ipstat.ips_tooshort++;
+		s->ipstat.ips_tooshort++;
 		goto bad;
 	}
 	/* Should drop packet if mbuf too long? hmmm... */
@@ -134,7 +136,7 @@
 
 	/* check ip_ttl for a correct ICMP reply */
 	if(ip->ip_ttl==0 || ip->ip_ttl==1) {
-	  icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
+	  icmp_error(s, m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
 	  goto bad;
 	}
 
@@ -163,7 +165,7 @@
 		 * Look for queue of fragments
 		 * of this datagram.
 		 */
-		for (fp = (struct ipq *) ipq.next; fp != &ipq;
+		for (fp = (struct ipq *) s->ipq.next; fp != &s->ipq;
 		     fp = (struct ipq *) fp->next)
 		  if (ip->ip_id == fp->ipq_id &&
 		      ip->ip_src.s_addr == fp->ipq_src.s_addr &&
@@ -192,15 +194,15 @@
 		 * attempt reassembly; if it succeeds, proceed.
 		 */
 		if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
-			ipstat.ips_fragments++;
-			ip = ip_reass((struct ipasfrag *)ip, fp);
+			s->ipstat.ips_fragments++;
+			ip = ip_reass(s, (struct ipasfrag *)ip, fp);
 			if (ip == 0)
 				return;
-			ipstat.ips_reassembled++;
-			m = dtom(ip);
+			s->ipstat.ips_reassembled++;
+			m = dtom(s, ip);
 		} else
 			if (fp)
-		   	   ip_freef(fp);
+		   	   ip_freef(s, fp);
 
 	} else
 		ip->ip_len -= hlen;
@@ -208,24 +210,24 @@
 	/*
 	 * Switch out to protocol's input routine.
 	 */
-	ipstat.ips_delivered++;
+	s->ipstat.ips_delivered++;
 	switch (ip->ip_p) {
 	 case IPPROTO_TCP:
-		tcp_input(m, hlen, (struct socket *)NULL);
+		tcp_input(s, m, hlen, (struct socket *)NULL);
 		break;
 	 case IPPROTO_UDP:
-		udp_input(m, hlen);
+		udp_input(s, m, hlen);
 		break;
 	 case IPPROTO_ICMP:
-		icmp_input(m, hlen);
+		icmp_input(s, m, hlen);
 		break;
 	 default:
-		ipstat.ips_noproto++;
-		m_free(m);
+		s->ipstat.ips_noproto++;
+		m_free(s, m);
 	}
 	return;
 bad:
-	m_freem(m);
+	m_freem(s, m);
 	return;
 }
 
@@ -235,12 +237,11 @@
  * reassembly of this datagram already exists, then it
  * is given as fp; otherwise have to make a chain.
  */
-struct ip *
-ip_reass(ip, fp)
-	register struct ipasfrag *ip;
-	register struct ipq *fp;
+static struct ip *
+ip_reass(slirp_state_t *s, register struct ipasfrag *ip,
+         register struct ipq *fp)
 {
-	register struct mbuf *m = dtom(ip);
+	register struct mbuf *m = dtom(s, ip);
 	register struct ipasfrag *q;
 	int hlen = ip->ip_hl << 2;
 	int i, next;
@@ -263,9 +264,10 @@
 	 */
 	if (fp == 0) {
 	  struct mbuf *t;
-	  if ((t = m_get()) == NULL) goto dropfrag;
+	  if ((t = m_get(s)) == NULL)
+              goto dropfrag;
 	  fp = mtod(t, struct ipq *);
-	  insque_32(fp, &ipq);
+	  insque_32(s, fp, &s->ipq);
 	  fp->ipq_ttl = IPFRAGTTL;
 	  fp->ipq_p = ip->ip_p;
 	  fp->ipq_id = ip->ip_id;
@@ -295,7 +297,7 @@
 		if (i > 0) {
 			if (i >= ip->ip_len)
 				goto dropfrag;
-			m_adj(dtom(ip), i);
+			m_adj(dtom(s, ip), i);
 			ip->ip_off += i;
 			ip->ip_len -= i;
 		}
@@ -310,12 +312,12 @@
 		if (i < q->ip_len) {
 			q->ip_len -= i;
 			q->ip_off += i;
-			m_adj(dtom(q), i);
+			m_adj(dtom(s, q), i);
 			break;
 		}
 		q = (struct ipasfrag *) q->ipf_next;
-		m_freem(dtom((struct ipasfrag *) q->ipf_prev));
-		ip_deq((struct ipasfrag *) q->ipf_prev);
+		m_freem(s, dtom(s, (struct ipasfrag *) q->ipf_prev));
+		ip_deq(s, (struct ipasfrag *) q->ipf_prev);
 	}
 
 insert:
@@ -323,7 +325,7 @@
 	 * Stick new segment in its place;
 	 * check for complete reassembly.
 	 */
-	ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
+	ip_enq(s, ip, (struct ipasfrag *) q->ipf_prev);
 	next = 0;
 	for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
 	     q = (struct ipasfrag *) q->ipf_next) {
@@ -338,14 +340,14 @@
 	 * Reassembly is complete; concatenate fragments.
 	 */
 	q = (struct ipasfrag *) fp->ipq_next;
-	m = dtom(q);
+	m = dtom(s, q);
 
 	q = (struct ipasfrag *) q->ipf_next;
 	while (q != (struct ipasfrag *)fp) {
 	  struct mbuf *t;
-	  t = dtom(q);
+	  t = dtom(s, q);
 	  q = (struct ipasfrag *) q->ipf_next;
-	  m_cat(m, t);
+	  m_cat(s, m, t);
 	}
 
 	/*
@@ -376,17 +378,17 @@
 	ip->ipf_mff &= ~1;
 	((struct ip *)ip)->ip_src = fp->ipq_src;
 	((struct ip *)ip)->ip_dst = fp->ipq_dst;
-	remque_32(fp);
-	(void) m_free(dtom(fp));
-	m = dtom(ip);
+	remque_32(s, fp);
+	(void) m_free(s, dtom(s, fp));
+	m = dtom(s, ip);
 	m->m_len += (ip->ip_hl << 2);
 	m->m_data -= (ip->ip_hl << 2);
 
 	return ((struct ip *)ip);
 
 dropfrag:
-	ipstat.ips_fragdropped++;
-	m_freem(m);
+	s->ipstat.ips_fragdropped++;
+	m_freem(s, m);
 	return (0);
 }
 
@@ -394,29 +396,28 @@
  * Free a fragment reassembly header and all
  * associated datagrams.
  */
-void
-ip_freef(fp)
-	struct ipq *fp;
+static void
+ip_freef(slirp_state_t *s, struct ipq *fp)
 {
 	register struct ipasfrag *q, *p;
 
 	for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
 	    q = p) {
 		p = (struct ipasfrag *) q->ipf_next;
-		ip_deq(q);
-		m_freem(dtom(q));
+		ip_deq(s, q);
+		m_freem(s, dtom(s, q));
 	}
-	remque_32(fp);
-	(void) m_free(dtom(fp));
+	remque_32(s, fp);
+	(void) m_free(s, dtom(s, fp));
 }
 
 /*
  * Put an ip fragment on a reassembly chain.
  * Like insque, but pointers in middle of structure.
  */
-void
-ip_enq(p, prev)
-	register struct ipasfrag *p, *prev;
+static void
+ip_enq(slirp_state_t *s, register struct ipasfrag *p,
+       register struct ipasfrag *prev)
 {
 	DEBUG_CALL("ip_enq");
 	DEBUG_ARG("prev = %lx", (long)prev);
@@ -429,9 +430,8 @@
 /*
  * To ip_enq as remque is to insque.
  */
-void
-ip_deq(p)
-	register struct ipasfrag *p;
+static void
+ip_deq(slirp_state_t *s, register struct ipasfrag *p)
 {
 	((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
 	((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
@@ -443,22 +443,22 @@
  * queue, discard it.
  */
 void
-ip_slowtimo()
+ip_slowtimo(slirp_state_t *s)
 {
 	register struct ipq *fp;
 
 	DEBUG_CALL("ip_slowtimo");
 
-	fp = (struct ipq *) ipq.next;
+	fp = (struct ipq *) s->ipq.next;
 	if (fp == 0)
 	   return;
 
-	while (fp != &ipq) {
+	while (fp != &s->ipq) {
 		--fp->ipq_ttl;
 		fp = (struct ipq *) fp->next;
 		if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
-			ipstat.ips_fragtimeout++;
-			ip_freef((struct ipq *) fp->prev);
+			s->ipstat.ips_fragtimeout++;
+			ip_freef(s, (struct ipq *) fp->prev);
 		}
 	}
 }
@@ -664,7 +664,7 @@
 /* Not yet */
  	icmp_error(m, type, code, 0, 0);
 
-	ipstat.ips_badoptions++;
+	s->ipstat.ips_badoptions++;
 	return (1);
 }
 
Index: qemu/slirp/ip_output.c
===================================================================
--- qemu.orig/slirp/ip_output.c	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/ip_output.c	2007-10-20 08:17:52.000000000 +0000
@@ -44,7 +44,6 @@
 
 #include <slirp.h>
 
-u_int16_t ip_id;
 
 /*
  * IP output.  The packet in mbuf chain m contains a skeletal IP
@@ -53,9 +52,7 @@
  * The mbuf opt, if present, will not be freed.
  */
 int
-ip_output(so, m0)
-	struct socket *so;
-	struct mbuf *m0;
+ip_output(slirp_state_t *s, struct socket *so, struct mbuf *m0)
 {
 	register struct ip *ip;
 	register struct mbuf *m = m0;
@@ -78,16 +75,16 @@
 	 */
 	ip->ip_v = IPVERSION;
 	ip->ip_off &= IP_DF;
-	ip->ip_id = htons(ip_id++);
+	ip->ip_id = htons(s->ip_id++);
 	ip->ip_hl = hlen >> 2;
-	ipstat.ips_localout++;
+	s->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) {
+/*	if (s->if_queued > s->if_thresh && towrite <= 0) {
  *		error = ENOBUFS;
  *		goto bad;
  *	}
@@ -96,13 +93,13 @@
 	/*
 	 * If small enough for interface, can just send directly.
 	 */
-	if ((u_int16_t)ip->ip_len <= if_mtu) {
+	if ((u_int16_t)ip->ip_len <= s->if_mtu) {
 		ip->ip_len = htons((u_int16_t)ip->ip_len);
 		ip->ip_off = htons((u_int16_t)ip->ip_off);
 		ip->ip_sum = 0;
 		ip->ip_sum = cksum(m, hlen);
 
-		if_output(so, m);
+		if_output(s, so, m);
 		goto done;
 	}
 
@@ -112,11 +109,11 @@
 	 */
 	if (ip->ip_off & IP_DF) {
 		error = -1;
-		ipstat.ips_cantfrag++;
+		s->ipstat.ips_cantfrag++;
 		goto bad;
 	}
 
-	len = (if_mtu - hlen) &~ 7;       /* ip databytes per packet */
+	len = (s->if_mtu - hlen) &~ 7;       /* ip databytes per packet */
 	if (len < 8) {
 		error = -1;
 		goto bad;
@@ -134,13 +131,13 @@
 	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(s);
 	  if (m == 0) {
 	    error = -1;
-	    ipstat.ips_odropped++;
+	    s->ipstat.ips_odropped++;
 	    goto sendorfree;
 	  }
-	  m->m_data += if_maxlinkhdr;
+	  m->m_data += s->if_maxlinkhdr;
 	  mhip = mtod(m, struct ip *);
 	  *mhip = *ip;
 
@@ -170,7 +167,7 @@
 	  mhip->ip_sum = cksum(m, mhlen);
 	  *mnext = m;
 	  mnext = &m->m_nextpkt;
-	  ipstat.ips_ofragments++;
+	  s->ipstat.ips_ofragments++;
 	}
 	/*
 	 * Update first fragment by trimming what's been copied out
@@ -187,19 +184,19 @@
 		m0 = m->m_nextpkt;
 		m->m_nextpkt = 0;
 		if (error == 0)
-			if_output(so, m);
+			if_output(s, so, m);
 		else
-			m_freem(m);
+			m_freem(s, m);
 	}
 
 	if (error == 0)
-		ipstat.ips_fragmented++;
+		s->ipstat.ips_fragmented++;
     }
 
 done:
 	return (error);
 
 bad:
-	m_freem(m0);
+	m_freem(s, m0);
 	goto done;
 }
Index: qemu/slirp/libslirp.h
===================================================================
--- qemu.orig/slirp/libslirp.h	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/libslirp.h	2007-10-20 11:50:05.000000000 +0000
@@ -5,26 +5,32 @@
 extern "C" {
 #endif
 
-void slirp_init(void);
+typedef struct slirp_state_t slirp_state_t;
 
-void slirp_select_fill(int *pnfds,
+slirp_state_t *slirp_init(void *user, const char *slirp_hostname,
+                          const char *tftp_prefix, const char *network);
+void slirp_term(slirp_state_t *s);
+void slirp_link_up(slirp_state_t *s);
+void slirp_link_down(slirp_state_t *s);
+
+void slirp_select_fill(slirp_state_t *s, 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(slirp_state_t *s, fd_set *readfds, fd_set *writefds,
+                       fd_set *xfds);
 
-void slirp_input(const uint8_t *pkt, int pkt_len);
+void slirp_input(slirp_state_t *s, 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 *user);
+void slirp_output(void *user, const uint8_t *pkt, int pkt_len);
 
-int slirp_redir(int is_udp, int host_port,
+int slirp_redir(slirp_state_t *s, int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port);
-int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
-                   int guest_port);
+int slirp_add_exec(slirp_state_t *s, int do_pty, const char *args,
+                   int addr_low_byte, int guest_port);
 
-extern const char *tftp_prefix;
-extern char slirp_hostname[33];
+void slirp_stats(slirp_state_t *s);
 
 #ifdef __cplusplus
 }
Index: qemu/slirp/main.h
===================================================================
--- qemu.orig/slirp/main.h	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/main.h	2007-10-20 08:17:52.000000000 +0000
@@ -11,14 +11,6 @@
 
 #define TOWRITEMAX 512
 
-extern struct timeval tt;
-extern int link_up;
-extern int slirp_socket;
-extern int slirp_socket_unit;
-extern int slirp_socket_port;
-extern u_int32_t slirp_socket_addr;
-extern char *slirp_socket_passwd;
-extern int ctty_closed;
 
 /*
  * Get the difference in 2 times from updtim()
@@ -28,27 +20,10 @@
  */
 #define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y)
 
-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 our_addr;
-extern struct in_addr loopback_addr;
-extern struct in_addr dns_addr;
-extern char *username;
-extern char *socket_path;
-extern int towrite_max;
-extern int ppp_exit;
-extern int so_options;
-extern int tcp_keepintvl;
-extern uint8_t client_ethaddr[6];
 
 #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_state_t *s, const uint8_t *ip_data, int ip_data_len);
Index: qemu/slirp/mbuf.c
===================================================================
--- qemu.orig/slirp/mbuf.c	2007-10-20 07:33:36.000000000 +0000
+++ qemu/slirp/mbuf.c	2007-10-20 17:30:44.000000000 +0000
@@ -17,31 +17,20 @@
 
 #include <slirp.h>
 
-struct	mbuf *mbutl;
-char	*mclrefcnt;
-int mbuf_alloced = 0;
-struct mbuf m_freelist, m_usedlist;
-int mbuf_thresh = 30;
-int mbuf_max = 0;
-int msize;
 
 void
-m_init()
+m_init(slirp_state_t *s)
 {
-	m_freelist.m_next = m_freelist.m_prev = &m_freelist;
-	m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
-	msize_init();
-}
+	s->m_freelist.m_next = s->m_freelist.m_prev = &s->m_freelist;
+	s->m_usedlist.m_next = s->m_usedlist.m_prev = &s->m_usedlist;
+        s->mbuf_alloced = 0;
 
-void
-msize_init()
-{
 	/*
 	 * Find a nice value for msize
 	 * XXX if_maxlinkhdr already in mtu
 	 */
-	msize = (if_mtu>if_mru?if_mtu:if_mru) +
-			if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
+	s->msize = (s->if_mtu > s->if_mru? s->if_mtu : s->if_mru) +
+            s->if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
 }
 
 /*
@@ -53,32 +42,33 @@
  * which tells m_free to actually free() it
  */
 struct mbuf *
-m_get()
+m_get(slirp_state_t *s)
 {
 	register struct mbuf *m;
 	int flags = 0;
 
 	DEBUG_CALL("m_get");
 
-	if (m_freelist.m_next == &m_freelist) {
-		m = (struct mbuf *)malloc(msize);
-		if (m == NULL) goto end_error;
-		mbuf_alloced++;
-		if (mbuf_alloced > mbuf_thresh)
+	if (s->m_freelist.m_next == &s->m_freelist) {
+		m = (struct mbuf *)malloc(s->msize);
+		if (m == NULL)
+                    goto end_error;
+		s->mbuf_alloced++;
+		if (s->mbuf_alloced > MBUF_THRESH)
 			flags = M_DOFREE;
-		if (mbuf_alloced > mbuf_max)
-			mbuf_max = mbuf_alloced;
+		if (s->mbuf_alloced > s->mbuf_max)
+			s->mbuf_max = s->mbuf_alloced;
 	} else {
-		m = m_freelist.m_next;
-		remque(m);
+		m = s->m_freelist.m_next;
+		remque(s, m);
 	}
 
 	/* Insert it in the used list */
-	insque(m,&m_usedlist);
+	insque(s, m, &s->m_usedlist);
 	m->m_flags = (flags | M_USEDLIST);
 
 	/* Initialise it */
-	m->m_size = msize - sizeof(struct m_hdr);
+	m->m_size = s->msize - sizeof(struct m_hdr);
 	m->m_data = m->m_dat;
 	m->m_len = 0;
 	m->m_nextpkt = 0;
@@ -89,8 +79,7 @@
 }
 
 void
-m_free(m)
-	struct mbuf *m;
+m_free(slirp_state_t *s, struct mbuf *m)
 {
 
   DEBUG_CALL("m_free");
@@ -99,7 +88,7 @@
   if(m) {
 	/* Remove from m_usedlist */
 	if (m->m_flags & M_USEDLIST)
-	   remque(m);
+	   remque(s, m);
 
 	/* If it's M_EXT, free() it */
 	if (m->m_flags & M_EXT)
@@ -110,9 +99,9 @@
 	 */
 	if (m->m_flags & M_DOFREE) {
 		free(m);
-		mbuf_alloced--;
+		s->mbuf_alloced--;
 	} else if ((m->m_flags & M_FREELIST) == 0) {
-		insque(m,&m_freelist);
+		insque(s, m, &s->m_freelist);
 		m->m_flags = M_FREELIST; /* Clobber other flags */
 	}
   } /* if(m) */
@@ -124,8 +113,7 @@
  * an M_EXT data segment
  */
 void
-m_cat(m, n)
-	register struct mbuf *m, *n;
+m_cat(slirp_state_t *s, register struct mbuf *m, register struct mbuf *n)
 {
 	/*
 	 * If there's no room, realloc
@@ -136,7 +124,7 @@
 	memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
 	m->m_len += n->m_len;
 
-	m_free(n);
+	m_free(s, n);
 }
 
 
@@ -220,8 +208,7 @@
  * Fortunately, it's not used often
  */
 struct mbuf *
-dtom(dat)
-	void *dat;
+dtom(slirp_state_t *s, void *dat)
 {
 	struct mbuf *m;
 
@@ -229,7 +216,7 @@
 	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 = s->m_usedlist.m_next; m != &s->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;
Index: qemu/slirp/mbuf.h
===================================================================
--- qemu.orig/slirp/mbuf.h	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/mbuf.h	2007-10-20 17:47:12.000000000 +0000
@@ -120,28 +120,13 @@
 #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));
-void msize_init _P((void));
-struct mbuf * m_get _P((void));
-void m_free _P((struct mbuf *));
-void m_cat _P((register struct mbuf *, register struct mbuf *));
+void m_init(slirp_state_t *s);
+struct mbuf *m_get(slirp_state_t *s);
+void m_free(slirp_state_t *s, struct mbuf *m);
+void m_cat(slirp_state_t *s, register struct mbuf *m, register struct mbuf *n);
 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(slirp_state_t *s, void *dat);
 
 #endif
Index: qemu/slirp/misc.c
===================================================================
--- qemu.orig/slirp/misc.c	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/misc.c	2007-10-20 18:18:49.000000000 +0000
@@ -8,8 +8,6 @@
 #define WANT_SYS_IOCTL_H
 #include <slirp.h>
 
-u_int curtime, time_fasttimo, last_slowtimo, detach_time;
-u_int detach_wait = 600000;	/* 10 minutes */
 
 #if 0
 int x_port = -1;
@@ -25,9 +23,9 @@
 		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);
+		      inet_ntoa(s->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);
+		      inet_ntoa(s->our_addr), x_port, x_screen);
 		if (x_display)
 		   lprint("X Redir: Redirecting to display %d\r\n", x_display);
 	}
@@ -85,7 +83,7 @@
  * Get our IP address and put it in our_addr
  */
 void
-getouraddr()
+getouraddr(slirp_state_t *s)
 {
 	char buff[256];
 	struct hostent *he = NULL;
@@ -93,9 +91,9 @@
 	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;
+            s->our_addr = *(struct in_addr *)he->h_addr;
+        if (s->our_addr.s_addr == 0)
+            s->our_addr.s_addr = s->loopback_addr.s_addr;
 }
 
 #if SIZEOF_CHAR_P == 8
@@ -105,10 +103,8 @@
 	u_int32_t qh_rlink;
 };
 
-inline void
-insque_32(a, b)
-	void *a;
-	void *b;
+void
+insque_32(slirp_state_t *s, void *a, void *b)
 {
 	register struct quehead_32 *element = (struct quehead_32 *) a;
 	register struct quehead_32 *head = (struct quehead_32 *) b;
@@ -119,9 +115,8 @@
 	= (u_int32_t)element;
 }
 
-inline void
-remque_32(a)
-	void *a;
+void
+remque_32(slirp_state_t *s, void *a)
 {
 	register struct quehead_32 *element = (struct quehead_32 *) a;
 	((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
@@ -136,9 +131,8 @@
 	struct quehead *qh_rlink;
 };
 
-inline void
-insque(a, b)
-	void *a, *b;
+void
+insque(slirp_state_t *s, void *a, void *b)
 {
 	register struct quehead *element = (struct quehead *) a;
 	register struct quehead *head = (struct quehead *) b;
@@ -149,9 +143,8 @@
 	= (struct quehead *)element;
 }
 
-inline void
-remque(a)
-     void *a;
+void
+remque(slirp_state_t *s, void *a)
 {
   register struct quehead *element = (struct quehead *) a;
   ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
@@ -214,10 +207,7 @@
 #ifdef _WIN32
 
 int
-fork_exec(so, ex, do_pty)
-	struct socket *so;
-	char *ex;
-	int do_pty;
+fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty)
 {
     /* not implemented */
     return 0;
@@ -225,6 +215,7 @@
 
 #else
 
+#if 0
 int
 slirp_openpty(amaster, aslave)
      int *amaster, *aslave;
@@ -289,6 +280,7 @@
 	return (-1);
 #endif
 }
+#endif
 
 /*
  * XXX This is ugly
@@ -302,23 +294,20 @@
  * do_ptr = 2   Fork/exec using pty
  */
 int
-fork_exec(so, ex, do_pty)
-	struct socket *so;
-	char *ex;
-	int do_pty;
+fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty)
 {
-	int s;
+	int fd = -1;
 	struct sockaddr_in addr;
 	int addrlen = sizeof(addr);
 	int opt;
-        int master;
+        int master = -1;
 	char *argv[256];
 #if 0
 	char buff[256];
 #endif
 	/* don't want to clobber the original */
 	char *bptr;
-	char *curarg;
+	const char *curarg;
 	int c, i, ret;
 
 	DEBUG_CALL("fork_exec");
@@ -327,20 +316,22 @@
 	DEBUG_ARG("do_pty = %lx", (long)do_pty);
 
 	if (do_pty == 2) {
-		if (slirp_openpty(&master, &s) == -1) {
+#if 0
+		if (slirp_openpty(&master, &fd) == -1) {
 			lprint("Error: openpty failed: %s\n", strerror(errno));
 			return 0;
 		}
+#endif
 	} else {
 		addr.sin_family = AF_INET;
 		addr.sin_port = 0;
 		addr.sin_addr.s_addr = INADDR_ANY;
 
-		if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
-		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
-		    listen(s, 1) < 0) {
+		if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
+		    bind(fd, (struct sockaddr *)&addr, addrlen) < 0 ||
+		    listen(fd, 1) < 0) {
 			lprint("Error: inet socket: %s\n", strerror(errno));
-			closesocket(s);
+			closesocket(fd);
 
 			return 0;
 		}
@@ -349,7 +340,7 @@
 	switch(fork()) {
 	 case -1:
 		lprint("Error: fork failed: %s\n", strerror(errno));
-		close(s);
+		close(fd);
 		if (do_pty == 2)
 		   close(master);
 		return 0;
@@ -360,38 +351,38 @@
 			(void) close(master);
 #ifdef TIOCSCTTY /* XXXXX */
 			(void) setsid();
-			ioctl(s, TIOCSCTTY, (char *)NULL);
+			ioctl(fd, TIOCSCTTY, (char *)NULL);
 #endif
 		} else {
-			getsockname(s, (struct sockaddr *)&addr, &addrlen);
-			close(s);
+			getsockname(fd, (struct sockaddr *)&addr, &addrlen);
+			close(fd);
 			/*
 			 * Connect to the socket
 			 * XXX If any of these fail, we're in trouble!
 	 		 */
-			s = socket(AF_INET, SOCK_STREAM, 0);
-			addr.sin_addr = loopback_addr;
+			fd = socket(AF_INET, SOCK_STREAM, 0);
+			addr.sin_addr = s->loopback_addr;
                         do {
-                            ret = connect(s, (struct sockaddr *)&addr, addrlen);
+                            ret = connect(fd, (struct sockaddr *)&addr, addrlen);
                         } 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);
+			sprintf(buff, "%s:%d.%d", inet_ntoa(s->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);
+			sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen);
 			putenv(buff);
 #endif
 		}
 #endif
-		dup2(s, 0);
-		dup2(s, 1);
-		dup2(s, 2);
-		for (s = 3; s <= 255; s++)
-		   close(s);
+		dup2(fd, 0);
+		dup2(fd, 1);
+		dup2(fd, 2);
+		for (fd = getdtablesize() - 1; fd >= 3; fd--)
+		   close(fd);
 
 		i = 0;
 		bptr = strdup(ex); /* No need to free() this */
@@ -427,7 +418,7 @@
 
 	 default:
 		if (do_pty == 2) {
-			close(s);
+			close(fd);
 			so->s = master;
 		} else {
 			/*
@@ -438,9 +429,9 @@
 		 	 * of connect() fail in the child process
 		 	 */
                         do {
-                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
+                            so->s = accept(fd, (struct sockaddr *)&addr, &addrlen);
                         } while (so->s < 0 && errno == EINTR);
-                        closesocket(s);
+                        closesocket(fd);
 			opt = 1;
 			setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
 			opt = 1;
@@ -450,7 +441,7 @@
 
 		/* Append the telnet options now */
 		if (so->so_m != 0 && do_pty == 1)  {
-			sbappend(so, so->so_m);
+			sbappend(s, so, so->so_m);
 			so->so_m = 0;
 		}
 
@@ -603,6 +594,7 @@
 }
 #endif
 
+#if 0
 int (*lprint_print) _P((void *, const char *, va_list));
 char *lprint_ptr, *lprint_ptr2, **lprint_arg;
 
@@ -754,6 +746,7 @@
 
 	lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
 }
+#endif
 
 #ifdef BAD_SPRINTF
 
@@ -908,10 +901,10 @@
 		/* Set the DISPLAY */
            if (x_port >= 0) {
 #ifdef HAVE_SETENV
-             sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
+             sprintf(buff, "%s:%d.%d", inet_ntoa(s->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);
+             sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(s->our_addr), x_port, x_screen);
              putenv(buff);
 #endif
            }
Index: qemu/slirp/misc.h
===================================================================
--- qemu.orig/slirp/misc.h	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/misc.h	2007-10-20 13:28:51.000000000 +0000
@@ -16,13 +16,6 @@
 	struct ex_list *ex_next;
 };
 
-extern struct ex_list *exec_list;
-extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
-
-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
@@ -69,12 +62,12 @@
 
 int show_x _P((char *, struct socket *));
 void redir_x _P((u_int32_t, int, int, int));
-void getouraddr _P((void));
-inline  void slirp_insque  _P((void *, void *));
-inline  void slirp_remque  _P((void *));
+void getouraddr(slirp_state_t *s);
+void slirp_insque(slirp_state_t *s, void *a, void *b);
+void slirp_remque(slirp_state_t *s, void *a);
 int add_exec _P((struct ex_list **, int, char *, int, int));
 int slirp_openpty _P((int *, int *));
-int fork_exec _P((struct socket *, char *, int));
+int fork_exec(slirp_state_t *s, struct socket *so, const char *ex, int do_pty);
 void snooze_hup _P((int));
 void snooze _P((void));
 void relay _P((int));
Index: qemu/slirp/sbuf.c
===================================================================
--- qemu.orig/slirp/sbuf.c	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/sbuf.c	2007-10-20 12:36:48.000000000 +0000
@@ -7,6 +7,8 @@
 
 #include <slirp.h>
 
+static void sbappendsb(struct sbuf *sb, struct mbuf *m);
+
 /* Done as a macro in socket.h */
 /* int
  * sbspace(struct sockbuff *sb)
@@ -72,9 +74,7 @@
  * (the socket is non-blocking, so we won't hang)
  */
 void
-sbappend(so, m)
-	struct socket *so;
-	struct mbuf *m;
+sbappend(slirp_state_t *s, struct socket *so, struct mbuf *m)
 {
 	int ret = 0;
 
@@ -85,7 +85,7 @@
 
 	/* Shouldn't happen, but...  e.g. foreign host closes connection */
 	if (m->m_len <= 0) {
-		m_free(m);
+		m_free(s, m);
 		return;
 	}
 
@@ -96,7 +96,7 @@
 	 */
 	if (so->so_urgc) {
 		sbappendsb(&so->so_rcv, m);
-		m_free(m);
+		m_free(s, m);
 		sosendoob(so);
 		return;
 	}
@@ -126,17 +126,15 @@
 		sbappendsb(&so->so_rcv, m);
 	} /* else */
 	/* Whatever happened, we free the mbuf */
-	m_free(m);
+	m_free(s, m);
 }
 
 /*
  * Copy the data from m into sb
  * The caller is responsible to make sure there's enough room
  */
-void
-sbappendsb(sb, m)
-	 struct sbuf *sb;
-	 struct mbuf *m;
+static void
+sbappendsb(struct sbuf *sb, struct mbuf *m)
 {
 	int len, n,  nn;
 
Index: qemu/slirp/sbuf.h
===================================================================
--- qemu.orig/slirp/sbuf.h	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/sbuf.h	2007-10-20 14:46:56.000000000 +0000
@@ -24,8 +24,7 @@
 void sbfree _P((struct sbuf *));
 void sbdrop _P((struct sbuf *, int));
 void sbreserve _P((struct sbuf *, int));
-void sbappend _P((struct socket *, struct mbuf *));
-void sbappendsb _P((struct sbuf *, struct mbuf *));
+void sbappend(slirp_state_t *s, struct socket *so, struct mbuf *m);
 void sbcopy _P((struct sbuf *, int, int, char *));
 
 #endif
Index: qemu/slirp/slirp.c
===================================================================
--- qemu.orig/slirp/slirp.c	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/slirp.c	2007-10-20 12:34:47.000000000 +0000
@@ -1,38 +1,14 @@
 #include "slirp.h"
 
-/* host address */
-struct in_addr our_addr;
-/* host dns address */
-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;
-
-const uint8_t special_ethaddr[6] = {
+static const uint8_t special_ethaddr[6] = {
     0x52, 0x54, 0x00, 0x12, 0x35, 0x00
 };
 
-uint8_t client_ethaddr[6];
-
-int do_slowtimo;
-int link_up;
-struct timeval tt;
-FILE *lfd;
-struct ex_list *exec_list;
-
-/* XXX: suppress those select globals */
-fd_set *global_readfds, *global_writefds, *global_xfds;
-
-char slirp_hostname[33];
-
 #ifdef _WIN32
 
-static int get_dns_addr(struct in_addr *pdns_addr)
+static int get_dns_addr(slirp_state_t *s, struct in_addr *pdns_addr)
 {
+    int rc = 0;
     FIXED_INFO *FixedInfo=NULL;
     ULONG    BufLen;
     DWORD    ret;
@@ -81,7 +57,7 @@
 
 #else
 
-static int get_dns_addr(struct in_addr *pdns_addr)
+static int get_dns_addr(slirp_state_t *s, struct in_addr *pdns_addr)
 {
     char buff[512];
     char buff2[256];
@@ -98,8 +74,8 @@
         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
             if (!inet_aton(buff2, &tmp_addr))
                 continue;
-            if (tmp_addr.s_addr == loopback_addr.s_addr)
-                tmp_addr = our_addr;
+            if (tmp_addr.s_addr == s->loopback_addr.s_addr)
+                tmp_addr = s->our_addr;
             /* If it's the first one, set it to dns_addr */
             if (!found)
                 *pdns_addr = tmp_addr;
@@ -121,15 +97,24 @@
 #endif
 
 #ifdef _WIN32
-void slirp_cleanup(void)
+static void slirp_cleanup(void)
 {
     WSACleanup();
 }
 #endif
 
-void slirp_init(void)
+slirp_state_t *slirp_init(void *user, const char *slirp_hostname,
+                          const char *tftp_prefix, const char *network)
 {
-    //    debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
+    slirp_state_t *s;
+
+    s = malloc(sizeof(slirp_state_t));
+    if (!s)
+        return s;
+    memset(s, 0, sizeof(slirp_state_t));
+    s->user = user;
+    s->slirp_hostname = slirp_hostname;
+    s->tftp_prefix = tftp_prefix;
 
 #ifdef _WIN32
     {
@@ -139,27 +124,79 @@
     }
 #endif
 
-    link_up = 1;
+    s->link_up = 1;
 
-    if_init();
-    ip_init();
+    if_init(s);
+    ip_init(s);
 
     /* Initialise mbufs *after* setting the MTU */
-    m_init();
+    m_init(s);
 
     /* set default addresses */
-    inet_aton("127.0.0.1", &loopback_addr);
+    inet_aton("127.0.0.1", &s->loopback_addr);
+    inet_aton("127.0.0.1", &s->dns_addr);
 
-    if (get_dns_addr(&dns_addr) < 0) {
-        dns_addr = loopback_addr;
+    if (get_dns_addr(s, &s->dns_addr) < 0) {
         fprintf (stderr, "Warning: No DNS servers found\n");
     }
 
-    inet_aton(CTL_SPECIAL, &special_addr);
-    alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
-    getouraddr();
+    inet_aton(network, &s->special_addr);
+    s->alias_addr.s_addr = s->special_addr.s_addr | htonl(CTL_ALIAS);
+    getouraddr(s);
+
+    return s;
 }
 
+/**
+ * Marks the link as up, making it possible to establish new connections.
+ */
+void slirp_link_up(slirp_state_t *s)
+{
+    s->link_up = 1;
+}
+
+/**
+ * Marks the link as down and cleans up the current connections.
+ */
+void slirp_link_down(slirp_state_t *s)
+{
+    struct socket *so;
+
+    while ((so = s->tcb.so_next) != &s->tcb)
+    {
+        if (so->so_state & SS_NOFDREF || so->s == -1)
+            sofree(s, so);
+        else
+            tcp_drop(s, sototcpcb(so), 0);
+    }
+
+    while ((so = s->udb.so_next) != &s->udb)
+        udp_detach(s, so);
+
+    s->link_up = 0;
+}
+
+/**
+ * Terminates the slirp component.
+ */
+void slirp_term(slirp_state_t *s)
+{
+    slirp_link_down(s);
+#ifdef WIN32
+    WSACleanup();
+#endif
+#ifdef LOG_ENABLED
+    ipstats(s);
+    tcpstats(s);
+    udpstats(s);
+    icmpstats(s);
+    mbufstats(s);
+    sockstats(s);
+#endif
+    free(s);
+}
+
+
 #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)
@@ -168,28 +205,28 @@
  * curtime kept to an accuracy of 1ms
  */
 #ifdef _WIN32
-static void updtime(void)
+static void updtime(slirp_state_t *s)
 {
     struct _timeb tb;
 
     _ftime(&tb);
-    curtime = (u_int)tb.time * (u_int)1000;
-    curtime += (u_int)tb.millitm;
+    s->curtime = (u_int)tb.time * (u_int)1000;
+    s->curtime += (u_int)tb.millitm;
 }
 #else
-static void updtime(void)
+static void updtime(slirp_state_t *s)
 {
-	gettimeofday(&tt, 0);
+	gettimeofday(&s->tt, 0);
 
-	curtime = (u_int)tt.tv_sec * (u_int)1000;
-	curtime += (u_int)tt.tv_usec / (u_int)1000;
+	s->curtime = (u_int)s->tt.tv_sec * (u_int)1000;
+	s->curtime += (u_int)s->tt.tv_usec / (u_int)1000;
 
-	if ((tt.tv_usec % 1000) >= 500)
-	   curtime++;
+	if ((s->tt.tv_usec % 1000) >= 500)
+	   s->curtime++;
 }
 #endif
 
-void slirp_select_fill(int *pnfds,
+void slirp_select_fill(slirp_state_t *s, int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds)
 {
     struct socket *so, *so_next;
@@ -198,31 +235,31 @@
     int tmp_time;
 
     /* fail safe */
-    global_readfds = NULL;
-    global_writefds = NULL;
-    global_xfds = NULL;
+    s->readfds = NULL;
+    s->writefds = NULL;
+    s->xfds = NULL;
 
     nfds = *pnfds;
 	/*
 	 * First, TCP sockets
 	 */
-	do_slowtimo = 0;
-	if (link_up) {
+	s->do_slowtimo = 0;
+	if (s->link_up) {
 		/*
 		 * *_slowtimo needs calling if there are IP fragments
 		 * in the fragment queue, or there are TCP connections active
 		 */
-		do_slowtimo = ((tcb.so_next != &tcb) ||
-			       ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
+		s->do_slowtimo = ((s->tcb.so_next != &s->tcb) ||
+                                  ((struct ipasfrag *)&s->ipq != (struct ipasfrag *)s->ipq.next));
 
-		for (so = tcb.so_next; so != &tcb; so = so_next) {
+		for (so = s->tcb.so_next; so != &s->tcb; so = so_next) {
 			so_next = so->so_next;
 
 			/*
 			 * See if we need a tcp_fasttimo
 			 */
-			if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
-			   time_fasttimo = curtime; /* Flag when we want a fasttimo */
+			if (s->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
+                            s->time_fasttimo = s->curtime; /* Flag when we want a fasttimo */
 
 			/*
 			 * NOFDREF can include still connecting to local-host,
@@ -272,18 +309,18 @@
 		/*
 		 * UDP sockets
 		 */
-		for (so = udb.so_next; so != &udb; so = so_next) {
+		for (so = s->udb.so_next; so != &s->udb; so = so_next) {
 			so_next = so->so_next;
 
 			/*
 			 * See if it's timed out
 			 */
 			if (so->so_expire) {
-				if (so->so_expire <= curtime) {
-					udp_detach(so);
+				if (so->so_expire <= s->curtime) {
+					udp_detach(s, so);
 					continue;
 				} else
-					do_slowtimo = 1; /* Let socket expire */
+					s->do_slowtimo = 1; /* Let socket expire */
 			}
 
 			/*
@@ -317,17 +354,17 @@
 	 * slow timeout. If a fast timeout is needed, set timeout within
 	 * 200ms of when it was requested.
 	 */
-	if (do_slowtimo) {
+	if (s->do_slowtimo) {
 		/* XXX + 10000 because some select()'s aren't that accurate */
-		timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
+		timeout.tv_usec = ((500 - (s->curtime - s->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 (s->time_fasttimo) {
+			tmp_time = (200 - (s->curtime - s->time_fasttimo)) * 1000;
 			if (tmp_time < 0)
 			   tmp_time = 0;
 
@@ -339,41 +376,41 @@
         *pnfds = nfds;
 }
 
-void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
+void slirp_select_poll(slirp_state_t *s, fd_set *readfds, fd_set *writefds, fd_set *xfds)
 {
     struct socket *so, *so_next;
     int ret;
 
-    global_readfds = readfds;
-    global_writefds = writefds;
-    global_xfds = xfds;
+    s->readfds = readfds;
+    s->writefds = writefds;
+    s->xfds = xfds;
 
 	/* Update time */
-	updtime();
+	updtime(s);
 
 	/*
 	 * See if anything has timed out
 	 */
-	if (link_up) {
-		if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
-			tcp_fasttimo();
-			time_fasttimo = 0;
+	if (s->link_up) {
+		if (s->time_fasttimo && ((s->curtime - s->time_fasttimo) >= 2)) {
+			tcp_fasttimo(s);
+			s->time_fasttimo = 0;
 		}
-		if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
-			ip_slowtimo();
-			tcp_slowtimo();
-			last_slowtimo = curtime;
+		if (s->do_slowtimo && ((s->curtime - s->last_slowtimo) >= 499)) {
+			ip_slowtimo(s);
+			tcp_slowtimo(s);
+			s->last_slowtimo = s->curtime;
 		}
 	}
 
 	/*
 	 * Check sockets
 	 */
-	if (link_up) {
+	if (s->link_up) {
 		/*
 		 * Check TCP sockets
 		 */
-		for (so = tcb.so_next; so != &tcb; so = so_next) {
+		for (so = s->tcb.so_next; so != &s->tcb; so = so_next) {
 			so_next = so->so_next;
 
 			/*
@@ -389,7 +426,7 @@
 			 * test for readfds below if this succeeds
 			 */
 			if (FD_ISSET(so->s, xfds))
-			   sorecvoob(so);
+			   sorecvoob(s, so);
 			/*
 			 * Check sockets for reading
 			 */
@@ -398,14 +435,14 @@
 				 * Check for incoming connections
 				 */
 				if (so->so_state & SS_FACCEPTCONN) {
-					tcp_connect(so);
+					tcp_connect(s, so);
 					continue;
 				} /* else */
-				ret = soread(so);
+				ret = soread(s, so);
 
 				/* Output it if we read something */
 				if (ret > 0)
-				   tcp_output(sototcpcb(so));
+				   tcp_output(s, sototcpcb(so));
 			}
 
 			/*
@@ -434,10 +471,10 @@
 			    /*
 			     * Continue tcp_input
 			     */
-			    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+			    tcp_input(s, (struct mbuf *)NULL, sizeof(struct ip), so);
 			    /* continue; */
 			  } else
-			    ret = sowrite(so);
+			    ret = sowrite(s, so);
 			  /*
 			   * XXXXX If we wrote something (a lot), there
 			   * could be a need for a window update.
@@ -487,11 +524,11 @@
 		 * 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 = s->udb.so_next; so != &s->udb; so = so_next) {
 			so_next = so->so_next;
 
 			if (so->s != -1 && FD_ISSET(so->s, readfds)) {
-                            sorecvfrom(so);
+                            sorecvfrom(s, so);
                         }
 		}
 	}
@@ -499,17 +536,17 @@
 	/*
 	 * See if we can start outputting
 	 */
-	if (if_queued && link_up)
-	   if_start();
+	if (s->if_queued && s->link_up)
+	   if_start(s);
 
 	/* clear global file descriptor sets.
 	 * these reside on the stack in vl.c
 	 * so they're unusable if we're not in
 	 * slirp_select_fill or slirp_select_poll.
 	 */
-	 global_readfds = NULL;
-	 global_writefds = NULL;
-	 global_xfds = NULL;
+	 s->readfds = NULL;
+	 s->writefds = NULL;
+	 s->xfds = NULL;
 }
 
 #define ETH_ALEN 6
@@ -545,7 +582,8 @@
 	unsigned char		ar_tip[4];		/* target IP address		*/
 };
 
-void arp_input(const uint8_t *pkt, int pkt_len)
+static
+void arp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len)
 {
     struct ethhdr *eh = (struct ethhdr *)pkt;
     struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
@@ -558,17 +596,17 @@
     ar_op = ntohs(ah->ar_op);
     switch(ar_op) {
     case ARPOP_REQUEST:
-        if (!memcmp(ah->ar_tip, &special_addr, 3)) {
+        if (!memcmp(ah->ar_tip, &s->special_addr, 3)) {
             if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
                 goto arp_ok;
-            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+            for (ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
                 if (ex_ptr->ex_addr == ah->ar_tip[3])
                     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(s->client_ethaddr, eh->h_source, ETH_ALEN);
 
             /* ARP request for alias/dns mac address */
             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
@@ -585,7 +623,7 @@
             memcpy(rah->ar_sip, ah->ar_tip, 4);
             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
             memcpy(rah->ar_tip, ah->ar_sip, 4);
-            slirp_output(arp_reply, sizeof(arp_reply));
+            slirp_output(s->user, arp_reply, sizeof(arp_reply));
         }
         break;
     default:
@@ -593,7 +631,7 @@
     }
 }
 
-void slirp_input(const uint8_t *pkt, int pkt_len)
+void slirp_input(slirp_state_t *s, const uint8_t *pkt, int pkt_len)
 {
     struct mbuf *m;
     int proto;
@@ -604,10 +642,14 @@
     proto = ntohs(*(uint16_t *)(pkt + 12));
     switch(proto) {
     case ETH_P_ARP:
-        arp_input(pkt, pkt_len);
+        arp_input(s, pkt, pkt_len);
         break;
     case ETH_P_IP:
-        m = m_get();
+	/* Update time. Important if the network is very quiet, as otherwise
+         * the first outgoing connection gets an incorrect timestamp. */
+	updtime(s);
+
+        m = m_get(s);
         if (!m)
             return;
         /* Note: we add to align the IP header */
@@ -617,7 +659,7 @@
         m->m_data += 2 + ETH_HLEN;
         m->m_len -= 2 + ETH_HLEN;
 
-        ip_input(m);
+        ip_input(s, m);
         break;
     default:
         break;
@@ -625,7 +667,7 @@
 }
 
 /* output the IP packet to the ethernet device */
-void if_encap(const uint8_t *ip_data, int ip_data_len)
+void if_encap(slirp_state_t *s, const uint8_t *ip_data, int ip_data_len)
 {
     uint8_t buf[1600];
     struct ethhdr *eh = (struct ethhdr *)buf;
@@ -633,33 +675,33 @@
     if (ip_data_len + ETH_HLEN > sizeof(buf))
         return;
 
-    memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
+    memcpy(eh->h_dest, s->client_ethaddr, ETH_ALEN);
     memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
     /* XXX: not correct */
     eh->h_source[5] = CTL_ALIAS;
     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(s->user, buf, ip_data_len + ETH_HLEN);
 }
 
-int slirp_redir(int is_udp, int host_port,
+int slirp_redir(slirp_state_t *s, int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port)
 {
     if (is_udp) {
-        if (!udp_listen(htons(host_port), guest_addr.s_addr,
+        if (!udp_listen(s, htons(host_port), guest_addr.s_addr,
                         htons(guest_port), 0))
             return -1;
     } else {
-        if (!solisten(htons(host_port), guest_addr.s_addr,
+        if (!solisten(s, htons(host_port), guest_addr.s_addr,
                       htons(guest_port), 0))
             return -1;
     }
     return 0;
 }
 
-int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
+int slirp_add_exec(slirp_state_t *s, int do_pty, const char *args, int addr_low_byte,
                   int guest_port)
 {
-    return add_exec(&exec_list, do_pty, (char *)args,
+    return add_exec(&s->exec_list, do_pty, (char *)args,
                     addr_low_byte, htons(guest_port));
 }
Index: qemu/slirp/slirp.h
===================================================================
--- qemu.orig/slirp/slirp.h	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/slirp.h	2007-10-20 14:58:01.000000000 +0000
@@ -5,6 +5,9 @@
 
 #define DEBUG 1
 
+// Uncomment the following line to enable SLIRP statistics printing in Qemu
+//#define LOG_ENABLED
+
 #ifndef CONFIG_QEMU
 #include "version.h"
 #endif
@@ -190,6 +193,8 @@
 #include <sys/stropts.h>
 #endif
 
+#include "libslirp.h"
+
 #include "debug.h"
 
 #include "ip.h"
@@ -213,19 +218,113 @@
 
 #include "bootp.h"
 #include "tftp.h"
-#include "libslirp.h"
 
-extern struct ttys *ttys_unit[MAX_INTERFACES];
+/** Number of DHCP clients supported by NAT. */
+#define NB_ADDR     16
+
+/** Where to start DHCP IP number allocation. */
+#define START_ADDR  15
+
+/** DHCP Lease time. */
+#define LEASE_TIME (24 * 3600)
+
+/** Entry in the table of known DHCP clients. */
+typedef struct {
+    int allocated;
+    uint8_t macaddr[6];
+} BOOTPClient;
+
+
+/** TFTP session entry. */
+struct tftp_session {
+    int in_use;
+    unsigned char filename[TFTP_FILENAME_MAX];
+
+    struct in_addr client_ip;
+    u_int16_t client_port;
+
+    int timestamp;
+};
+
+
+/** Main state/configuration structure for slirp. */
+struct slirp_state_t
+{
+    /* Stuff from boot.c */
+    BOOTPClient bootp_clients[NB_ADDR];
+    const char *bootp_filename;
+    /* Stuff from if.c */
+    int if_mtu, if_mru;
+    int if_comp;
+    int if_maxlinkhdr;
+    int if_queued;
+    int if_thresh;
+    struct mbuf if_fastq;
+    struct mbuf if_batchq;
+    struct mbuf *next_m;
+    /* Stuff from icmp.c */
+    struct icmpstat icmpstat;
+    /* Stuff from ip_input.c */
+    struct ipstat ipstat;
+    struct ipq ipq;
+    uint16_t ip_id;
+    /* Stuff from mbuf.c */
+    int mbuf_alloced, mbuf_max;
+    int msize;
+    struct mbuf m_freelist, m_usedlist;
+    /* Stuff from slirp.c */
+    fd_set *readfds, *writefds, *xfds;
+    const char *slirp_hostname;
+    void *user;
+    uint32_t curtime;
+    uint32_t time_fasttimo;
+    uint32_t last_slowtimo;
+    int do_slowtimo;
+    int link_up;
+    struct timeval tt;
+    struct in_addr our_addr;
+    struct in_addr alias_addr;
+    struct in_addr special_addr;
+    struct in_addr dns_addr;
+    struct in_addr loopback_addr;
+    uint8_t client_ethaddr[6];
+    struct ex_list *exec_list;
+    /* Stuff from tcp_input.c */
+    struct socket tcb;
+    struct socket *tcp_last_so;
+    tcp_seq tcp_iss;
+    /* Stuff from tcp_timer.c */
+    struct tcpstat tcpstat;
+    uint32_t tcp_now;
+    /* Stuff from tftp.c */
+    struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
+    const char *tftp_prefix;
+    /* Stuff from udp.c */
+    struct udpstat udpstat;
+    struct socket udb;
+    struct socket *udp_last_so;
+    // tcp_subr.c
+    int do_echo;
+};
+
+/** Number of permanent buffers in mbuf. */
+#define MBUF_THRESH 30
+
+/** Default TCP socket options. */
+#define SO_OPTIONS DO_KEEPALIVE
+
+/** Enable RFC1323 performance enhancements.
+ * @todo check if it really works, it was turned off before. */
+#define TCP_DO_RFC1323 1
+
+/* TCP duplicate ACK retransmit threshold. */
+#define TCPREXMTTHRESH 3
 
 #ifndef NULL
 #define NULL (void *)0
 #endif
 
-#ifndef FULL_BOLT
-void if_start _P((void));
-#else
-void if_start _P((struct ttys *));
-#endif
+void if_start(slirp_state_t *s);
 
 #ifdef BAD_SPRINTF
 # define vsprintf vsprintf_len
@@ -253,16 +352,22 @@
  long gethostid _P((void));
 #endif
 
-void lprint _P((const char *, ...));
-
-extern int do_echo;
+static inline void lprint(const char *format, ...)
+{
+#ifdef LOG_ENABLED
+    va_list args;
+    va_start(args, format);
+    term_vprintf(format, args);
+    va_end(args);
+#endif
+}
 
 #if SIZEOF_CHAR_P == 4
 # define insque_32 insque
 # define remque_32 remque
 #else
- inline void insque_32 _P((void *, void *));
- inline void remque_32 _P((void *));
+void insque_32(slirp_state_t *s, void *a, void *b);
+void remque_32(slirp_state_t *s, void *a);
 #endif
 
 #ifndef _WIN32
@@ -275,48 +380,41 @@
 int cksum(struct mbuf *m, int len);
 
 /* if.c */
-void if_init _P((void));
-void if_output _P((struct socket *, struct mbuf *));
+void if_init(slirp_state_t *s);
+void if_output(slirp_state_t *s, struct socket *so, struct mbuf *ifm);
 
 /* ip_input.c */
-void ip_init _P((void));
-void ip_input _P((struct mbuf *));
-struct ip * ip_reass _P((register struct ipasfrag *, register struct ipq *));
-void ip_freef _P((struct ipq *));
-void ip_enq _P((register struct ipasfrag *, register struct ipasfrag *));
-void ip_deq _P((register struct ipasfrag *));
-void ip_slowtimo _P((void));
+void ip_init(slirp_state_t *s);
+void ip_input(slirp_state_t *s, struct mbuf *m);
+void ip_slowtimo(slirp_state_t *s);
 void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
 
 /* ip_output.c */
-int ip_output _P((struct socket *, struct mbuf *));
+int ip_output(slirp_state_t *s, struct socket *so, struct mbuf *m0);
 
 /* tcp_input.c */
-int tcp_reass _P((register struct tcpcb *, register struct tcpiphdr *, struct mbuf *));
-void tcp_input _P((register struct mbuf *, int, struct socket *));
-void tcp_dooptions _P((struct tcpcb *, u_char *, int, struct tcpiphdr *));
-void tcp_xmit_timer _P((register struct tcpcb *, int));
-int tcp_mss _P((register struct tcpcb *, u_int));
+void tcp_input(slirp_state_t *s, register struct mbuf *m, int iphlen, struct socket *inso);
+int tcp_mss(slirp_state_t *s, register struct tcpcb *tp, u_int offer);
 
 /* tcp_output.c */
-int tcp_output _P((register struct tcpcb *));
+int tcp_output(slirp_state_t *s, register struct tcpcb *tp);
 void tcp_setpersist _P((register struct tcpcb *));
 
 /* tcp_subr.c */
-void tcp_init _P((void));
+void tcp_init(slirp_state_t *s);
 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 *));
-struct tcpcb * tcp_close _P((register struct tcpcb *));
-void tcp_drain _P((void));
-void tcp_sockclosed _P((struct tcpcb *));
-int tcp_fconnect _P((struct socket *));
-void tcp_connect _P((struct socket *));
-int tcp_attach _P((struct socket *));
+void tcp_respond(slirp_state_t *s, struct tcpcb *tp, struct tcpiphdr *ti,
+                 struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags);
+struct tcpcb *tcp_newtcpcb(slirp_state_t *s, struct socket *so);
+struct tcpcb *tcp_close(slirp_state_t *s, register struct tcpcb *tp);
+void tcp_sockclosed(slirp_state_t *s, struct tcpcb *tp);
+int tcp_fconnect(slirp_state_t *s, struct socket *so);
+void tcp_connect(slirp_state_t *s, struct socket *inso);
+int tcp_attach(slirp_state_t *s, struct socket *so);
 u_int8_t tcp_tos _P((struct socket *));
-int tcp_emu _P((struct socket *, struct mbuf *));
-int tcp_ctl _P((struct socket *));
-struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
+int tcp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m);
+int tcp_ctl(slirp_state_t *s, struct socket *so);
+struct tcpcb *tcp_drop(slirp_state_t *s, struct tcpcb *tp, int err);
 
 #ifdef USE_PPP
 #define MIN_MRU MINMRU
Index: qemu/slirp/socket.c
===================================================================
--- qemu.orig/slirp/socket.c	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/socket.c	2007-10-20 12:33:06.000000000 +0000
@@ -13,12 +13,16 @@
 #include <sys/filio.h>
 #endif
 
-void
+static void sofcantrcvmore(slirp_state_t *s, struct  socket *so);
+static void sofcantsendmore(slirp_state_t *s, struct socket *so);
+
+#if 0
+static void
 so_init()
 {
 	/* Nothing yet */
 }
-
+#endif
 
 struct socket *
 solookup(head, laddr, lport, faddr, fport)
@@ -67,22 +71,21 @@
  * remque and free a socket, clobber cache
  */
 void
-sofree(so)
-	struct socket *so;
+sofree(slirp_state_t *s, struct socket *so)
 {
   if (so->so_emu==EMU_RSH && so->extra) {
-	sofree(so->extra);
+	sofree(s, 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 == s->tcp_last_so)
+    s->tcp_last_so = &s->tcb;
+  else if (so == s->udp_last_so)
+    s->udp_last_so = &s->udb;
 
-  m_free(so->so_m);
+  m_free(s, so->so_m);
 
   if(so->so_next && so->so_prev)
-    remque(so);  /* crashes if so is not in a queue */
+    remque(s, so);  /* crashes if so is not in a queue */
 
   free(so);
 }
@@ -93,8 +96,7 @@
  * a read() of 0 (or less) means it's disconnected
  */
 int
-soread(so)
-	struct socket *so;
+soread(slirp_state_t *s, struct socket *so)
 {
 	int n, nn, lss, total;
 	struct sbuf *sb = &so->so_snd;
@@ -113,6 +115,8 @@
 	len = sb->sb_datalen - sb->sb_cc;
 
 	iov[0].iov_base = sb->sb_wptr;
+        iov[1].iov_base = 0;
+        iov[1].iov_len  = 0;
 	if (sb->sb_wptr < sb->sb_rptr) {
 		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
 		/* Should never succeed, but... */
@@ -162,8 +166,8 @@
 			return 0;
 		else {
 			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
-			sofcantrcvmore(so);
-			tcp_sockclosed(sototcpcb(so));
+			sofcantrcvmore(s, so);
+			tcp_sockclosed(s, sototcpcb(so));
 			return -1;
 		}
 	}
@@ -204,8 +208,7 @@
  * in the send buffer is sent as urgent data
  */
 void
-sorecvoob(so)
-	struct socket *so;
+sorecvoob(slirp_state_t *s, struct socket *so)
 {
 	struct tcpcb *tp = sototcpcb(so);
 
@@ -220,10 +223,10 @@
 	 * urgent data, or the read() doesn't return all the
 	 * urgent data.
 	 */
-	soread(so);
+	soread(s, so);
 	tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
 	tp->t_force = 1;
-	tcp_output(tp);
+	tcp_output(s, tp);
 	tp->t_force = 0;
 }
 
@@ -291,8 +294,7 @@
  * updating all sbuf field as necessary
  */
 int
-sowrite(so)
-	struct socket *so;
+sowrite(slirp_state_t *s, struct socket *so)
 {
 	int  n,nn;
 	struct sbuf *sb = &so->so_rcv;
@@ -316,6 +318,8 @@
         len = sb->sb_cc;
 
 	iov[0].iov_base = sb->sb_rptr;
+        iov[1].iov_base = 0;
+        iov[1].iov_len  = 0;
 	if (sb->sb_rptr < sb->sb_wptr) {
 		iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
 		/* Should never succeed, but... */
@@ -349,8 +353,8 @@
 	if (nn <= 0) {
 		DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
 			so->so_state, errno));
-		sofcantsendmore(so);
-		tcp_sockclosed(sototcpcb(so));
+		sofcantsendmore(s, so);
+		tcp_sockclosed(s, sototcpcb(so));
 		return -1;
 	}
 
@@ -375,7 +379,7 @@
 	 * it CANTSENDMORE
 	 */
 	if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
-		sofcantsendmore(so);
+		sofcantsendmore(s,so);
 
 	return nn;
 }
@@ -384,8 +388,7 @@
  * recvfrom() a UDP socket
  */
 void
-sorecvfrom(so)
-	struct socket *so;
+sorecvfrom(slirp_state_t *s, struct socket *so)
 {
 	struct sockaddr_in addr;
 	int addrlen = sizeof(struct sockaddr_in);
@@ -409,19 +412,19 @@
 
 	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
 			errno,strerror(errno)));
-	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+	    icmp_error(s, so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
 	  } else {
-	    icmp_reflect(so->so_m);
+	    icmp_reflect(s, so->so_m);
 	    so->so_m = 0; /* Don't m_free() it again! */
 	  }
 	  /* No need for this socket anymore, udp_detach it */
-	  udp_detach(so);
+	  udp_detach(s, so);
 	} else {                            	/* A "normal" UDP packet */
 	  struct mbuf *m;
 	  int len, n;
 
-	  if (!(m = m_get())) return;
-	  m->m_data += if_maxlinkhdr;
+	  if (!(m = m_get(s))) return;
+	  m->m_data += s->if_maxlinkhdr;
 
 	  /*
 	   * XXX Shouldn't FIONREAD packets destined for port 53,
@@ -449,8 +452,8 @@
 	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
 
 	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
-	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
-	    m_free(m);
+	    icmp_error(s, so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+	    m_free(s, m);
 	  } else {
 	  /*
 	   * Hack: domain name lookup will be used the most for UDP,
@@ -460,9 +463,9 @@
 	   */
 	    if (so->so_expire) {
 	      if (so->so_fport == htons(53))
-		so->so_expire = curtime + SO_EXPIREFAST;
+		so->so_expire = s->curtime + SO_EXPIREFAST;
 	      else
-		so->so_expire = curtime + SO_EXPIRE;
+		so->so_expire = s->curtime + SO_EXPIRE;
 	    }
 
 	    /*		if (m->m_len == len) {
@@ -475,7 +478,7 @@
 	     * If this packet was destined for CTL_ADDR,
 	     * make it look like that's where it came from, done by udp_output
 	     */
-	    udp_output(so, m, &addr);
+	    udp_output(s, so, m, &addr);
 	  } /* rx error */
 	} /* if ping packet */
 }
@@ -484,9 +487,7 @@
  * sendto() a socket
  */
 int
-sosendto(so, m)
-	struct socket *so;
-	struct mbuf *m;
+sosendto(slirp_state_t *s, struct socket *so, struct mbuf *m)
 {
 	int ret;
 	struct sockaddr_in addr;
@@ -496,15 +497,30 @@
 	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 & htonl(0xffffff00)) == s->special_addr.s_addr) {
 	  /* It's an alias */
 	  switch(ntohl(so->so_faddr.s_addr) & 0xff) {
+          case CTL_BROADCAST:
+            addr.sin_addr.s_addr = INADDR_BROADCAST;
+#if 0
+            /* Send the packet to host to fully emulate broadcast */
+            /** @todo r=klaus: on Linux host this causes the host to receive
+             * the packet twice for some reason. And I cannot find any place
+             * in the man pages which states that sending a broadcast does not
+             * reach the host itself. */
+            host_addr.sin_family = AF_INET;
+            host_addr.sin_port = so->so_fport;
+            host_addr.sin_addr = s->our_addr;
+            sendto(so->s, m->m_data, m->m_len, 0,
+                  (struct sockaddr *)&host_addr, sizeof (struct sockaddr));
+#endif
+            break;
 	  case CTL_DNS:
-	    addr.sin_addr = dns_addr;
+	    addr.sin_addr = s->dns_addr;
 	    break;
 	  case CTL_ALIAS:
 	  default:
-	    addr.sin_addr = loopback_addr;
+	    addr.sin_addr = s->loopback_addr;
 	    break;
 	  }
 	} else
@@ -524,7 +540,7 @@
 	 * but only if it's an expirable socket
 	 */
 	if (so->so_expire)
-		so->so_expire = curtime + SO_EXPIRE;
+		so->so_expire = s->curtime + SO_EXPIRE;
 	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
 	return 0;
 }
@@ -533,15 +549,11 @@
  * XXX This should really be tcp_listen
  */
 struct socket *
-solisten(port, laddr, lport, flags)
-	u_int port;
-	u_int32_t laddr;
-	u_int lport;
-	int flags;
+solisten(slirp_state_t *s, u_int port, u_int32_t laddr, u_int lport, int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
-	int s, addrlen = sizeof(addr), opt = 1;
+	int fd, addrlen = sizeof(addr), opt = 1;
 
 	DEBUG_CALL("solisten");
 	DEBUG_ARG("port = %d", port);
@@ -555,11 +567,11 @@
 	}
 
 	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
-	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
+	if ((so->so_tcpcb = tcp_newtcpcb(s, so)) == NULL) {
 		free(so);
 		return NULL;
 	}
-	insque(so,&tcb);
+	insque(s, so, &s->tcb);
 
 	/*
 	 * SS_FACCEPTONCE sockets must time out.
@@ -575,14 +587,14 @@
 	addr.sin_addr.s_addr = INADDR_ANY;
 	addr.sin_port = port;
 
-	if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
-	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
-	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
-	    (listen(s,1) < 0)) {
+	if (((fd = socket(AF_INET,SOCK_STREAM, 0)) < 0) ||
+	    (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)) < 0) ||
+	    (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) ||
+	    (listen(fd ,1) < 0)) {
 		int tmperrno = errno; /* Don't clobber the real reason we failed */
 
-		close(s);
-		sofree(so);
+		close(fd);
+		sofree(s, so);
 		/* Restore the real errno */
 #ifdef _WIN32
 		WSASetLastError(tmperrno);
@@ -591,25 +603,26 @@
 #endif
 		return NULL;
 	}
-	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
+	setsockopt(fd, SOL_SOCKET,SO_OOBINLINE, (char *)&opt, sizeof(int));
 
-	getsockname(s,(struct sockaddr *)&addr,&addrlen);
+	getsockname(fd, (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;
+	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == s->loopback_addr.s_addr)
+	   so->so_faddr = s->alias_addr;
 	else
 	   so->so_faddr = addr.sin_addr;
 
-	so->s = s;
+	so->s = fd;
 	return so;
 }
 
+#if 0
 /*
  * Data is available in so_rcv
  * Just write() the data to the socket
  * XXX not yet...
  */
-void
+static void
 sorwakeup(so)
 	struct socket *so;
 {
@@ -622,12 +635,13 @@
  * We have room for a read() if we want to
  * For now, don't read, it'll be done in the main loop
  */
-void
+static void
 sowwakeup(so)
 	struct socket *so;
 {
 	/* Nothing, yet */
 }
+#endif
 
 /*
  * Various session state calls
@@ -652,14 +666,13 @@
 	so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
 }
 
-void
-sofcantrcvmore(so)
-	struct  socket *so;
+static void
+sofcantrcvmore(slirp_state_t *s, struct  socket *so)
 {
 	if ((so->so_state & SS_NOFDREF) == 0) {
 		shutdown(so->s,0);
-		if(global_writefds) {
-		  FD_CLR(so->s,global_writefds);
+		if (s->writefds) {
+                    FD_CLR(so->s, s->writefds);
 		}
 	}
 	so->so_state &= ~(SS_ISFCONNECTING);
@@ -669,17 +682,16 @@
 	   so->so_state |= SS_FCANTRCVMORE;
 }
 
-void
-sofcantsendmore(so)
-	struct socket *so;
+static void
+sofcantsendmore(slirp_state_t *s, struct socket *so)
 {
 	if ((so->so_state & SS_NOFDREF) == 0) {
             shutdown(so->s,1);           /* send FIN to fhost */
-            if (global_readfds) {
-                FD_CLR(so->s,global_readfds);
+            if (s->readfds) {
+                FD_CLR(so->s, s->readfds);
             }
-            if (global_xfds) {
-                FD_CLR(so->s,global_xfds);
+            if (s->xfds) {
+                FD_CLR(so->s, s->xfds);
             }
 	}
 	so->so_state &= ~(SS_ISFCONNECTING);
@@ -706,12 +718,11 @@
  * Set CANTSENDMORE once all data has been write()n
  */
 void
-sofwdrain(so)
-	struct socket *so;
+sofwdrain(slirp_state_t *s, struct socket *so)
 {
 	if (so->so_rcv.sb_cc)
 		so->so_state |= SS_FWDRAIN;
 	else
-		sofcantsendmore(so);
+		sofcantsendmore(s, so);
 }
 
Index: qemu/slirp/socket.h
===================================================================
--- qemu.orig/slirp/socket.h	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/socket.h	2007-10-20 14:55:25.000000000 +0000
@@ -71,9 +71,6 @@
 #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 */
 
-extern struct socket tcb;
-
-
 #if defined(DECLARE_IOVEC) && !defined(HAVE_READV)
 struct iovec {
 	char *iov_base;
@@ -81,24 +78,20 @@
 };
 #endif
 
-void so_init _P((void));
 struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
 struct socket * socreate _P((void));
-void sofree _P((struct socket *));
-int soread _P((struct socket *));
-void sorecvoob _P((struct socket *));
+void sofree(slirp_state_t *s, struct socket *so);
+int soread(slirp_state_t *s, struct socket *so);
+void sorecvoob(slirp_state_t *s, struct socket *so);
 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));
-void sorwakeup _P((struct socket *));
-void sowwakeup _P((struct socket *));
+int sowrite(slirp_state_t *s, struct socket *so);
+void sorecvfrom(slirp_state_t *s, struct socket *so);
+int sosendto(slirp_state_t *s, struct socket *so, struct mbuf *m);
+struct socket *solisten(slirp_state_t *s, u_int port, u_int32_t laddr,
+                        u_int lport, int flags);
 void soisfconnecting _P((register struct socket *));
 void soisfconnected _P((register struct socket *));
-void sofcantrcvmore _P((struct  socket *));
-void sofcantsendmore _P((struct socket *));
 void soisfdisconnected _P((struct socket *));
-void sofwdrain _P((struct socket *));
+void sofwdrain(slirp_state_t *s, struct socket *so);
 
 #endif /* _SOCKET_H_ */
Index: qemu/slirp/tcp.h
===================================================================
--- qemu.orig/slirp/tcp.h	2007-10-20 07:33:37.000000000 +0000
+++ qemu/slirp/tcp.h	2007-10-20 09:42:26.000000000 +0000
@@ -42,10 +42,6 @@
 #define      PR_SLOWHZ       2               /* 2 slow timeouts per second (approx) */
 #define      PR_FASTHZ       5               /* 5 fast timeouts per second (not important) */
 
-extern int tcp_rcvspace;
-extern int tcp_sndspace;
-extern struct socket *tcp_last_so;
-
 #define TCP_SNDSPACE 8192
 #define TCP_RCVSPACE 8192
 
@@ -170,8 +166,6 @@
 
 #define TCP_ISSINCR     (125*1024)      /* increment for tcp_iss each second */
 
-extern tcp_seq tcp_iss;                /* tcp initial send seq # */
-
-extern char *tcpstates[];
+extern const char * const tcpstates[];
 
 #endif
Index: qemu/slirp/tcp_input.c
===================================================================
--- qemu.orig/slirp/tcp_input.c	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tcp_input.c	2007-10-20 17:08:59.000000000 +0000
@@ -45,12 +45,6 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
-struct socket tcb;
-
-int	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)
 
@@ -69,7 +63,7 @@
  * when segments are out of order (so fast retransmit can work).
  */
 #ifdef TCP_ACK_HACK
-#define TCP_REASS(tp, ti, m, so, flags) {\
+#define TCP_REASS(s, tp, ti, m, so, flags) {\
        if ((ti)->ti_seq == (tp)->rcv_nxt && \
            (tp)->seg_next == (tcpiphdrp_32)(tp) && \
            (tp)->t_state == TCPS_ESTABLISHED) {\
@@ -79,45 +73,49 @@
                        tp->t_flags |= TF_DELACK; \
                (tp)->rcv_nxt += (ti)->ti_len; \
                flags = (ti)->ti_flags & TH_FIN; \
-               tcpstat.tcps_rcvpack++;\
-               tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+               s->tcpstat.tcps_rcvpack++;\
+               s->tcpstat.tcps_rcvbyte += (ti)->ti_len;\
                if (so->so_emu) { \
-		       if (tcp_emu((so),(m))) sbappend((so), (m)); \
+		       if (tcp_emu((s), (so), (m)))     \
+                           sbappend((s), (so), (m));    \
 	       } else \
-	       	       sbappend((so), (m)); \
+	       	       sbappend((s), (so), (m)); \
 /*               sorwakeup(so); */ \
 	} else {\
-               (flags) = tcp_reass((tp), (ti), (m)); \
+               (flags) = tcp_reass((s), (tp), (ti), (m)); \
                tp->t_flags |= TF_ACKNOW; \
        } \
 }
 #else
-#define	TCP_REASS(tp, ti, m, so, flags) { \
+#define	TCP_REASS(s, tp, ti, m, so, flags) { \
 	if ((ti)->ti_seq == (tp)->rcv_nxt && \
 	    (tp)->seg_next == (tcpiphdrp_32)(tp) && \
 	    (tp)->t_state == TCPS_ESTABLISHED) { \
 		tp->t_flags |= TF_DELACK; \
 		(tp)->rcv_nxt += (ti)->ti_len; \
 		flags = (ti)->ti_flags & TH_FIN; \
-		tcpstat.tcps_rcvpack++;\
-		tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+		s->tcpstat.tcps_rcvpack++;\
+		s->tcpstat.tcps_rcvbyte += (ti)->ti_len;\
 		if (so->so_emu) { \
-			if (tcp_emu((so),(m))) sbappend(so, (m)); \
+		       if (tcp_emu((s), (so), (m)))     \
+                            sbappend((s), (so), (m));   \
 		} else \
-			sbappend((so), (m)); \
+			sbappend((s), (so), (m)); \
 /*		sorwakeup(so); */ \
 	} else { \
-		(flags) = tcp_reass((tp), (ti), (m)); \
+		(flags) = tcp_reass((s), (tp), (ti), (m)); \
 		tp->t_flags |= TF_ACKNOW; \
 	} \
 }
 #endif
-
-int
-tcp_reass(tp, ti, m)
-	register struct tcpcb *tp;
-	register struct tcpiphdr *ti;
-	struct mbuf *m;
+static void tcp_dooptions(slirp_state_t *s, struct tcpcb *tp, u_char *cp,
+                          int cnt, struct tcpiphdr *ti);
+static void tcp_xmit_timer(slirp_state_t *s, register struct tcpcb *tp,
+                           int rtt);
+
+static int
+tcp_reass(slirp_state_t *s, register struct tcpcb *tp,
+          register struct tcpiphdr *ti, struct mbuf *m)
 {
 	register struct tcpiphdr *q;
 	struct socket *so = tp->t_socket;
@@ -133,8 +131,7 @@
 	/*
 	 * Find a segment which begins after this one does.
 	 */
-	for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp;
-	    q = (struct tcpiphdr *)q->ti_next)
+	for (q = tp->seg_next; q != tp; q = q->ti_next)
 		if (SEQ_GT(q->ti_seq, ti->ti_seq))
 			break;
 
@@ -150,9 +147,9 @@
 		i = q->ti_seq + q->ti_len - ti->ti_seq;
 		if (i > 0) {
 			if (i >= ti->ti_len) {
-				tcpstat.tcps_rcvduppack++;
-				tcpstat.tcps_rcvdupbyte += ti->ti_len;
-				m_freem(m);
+				s->tcpstat.tcps_rcvduppack++;
+				s->tcpstat.tcps_rcvdupbyte += ti->ti_len;
+				m_freem(s, m);
 				/*
 				 * Try to present any queued data
 				 * at the left window edge to the user.
@@ -167,9 +164,9 @@
 		}
 		q = (struct tcpiphdr *)(q->ti_next);
 	}
-	tcpstat.tcps_rcvoopack++;
-	tcpstat.tcps_rcvoobyte += ti->ti_len;
-	REASS_MBUF(ti) = (mbufp_32) m;		/* XXX */
+	s->tcpstat.tcps_rcvoopack++;
+	s->tcpstat.tcps_rcvoobyte += ti->ti_len;
+	REASS_MBUF_SET(ti, m); /* XXX */
 
 	/*
 	 * While we overlap succeeding segments trim them or,
@@ -182,19 +179,19 @@
 		if (i < q->ti_len) {
 			q->ti_seq += i;
 			q->ti_len -= i;
-			m_adj((struct mbuf *) REASS_MBUF(q), i);
+			m_adj(REASS_MBUF_GET(q), i);
 			break;
 		}
 		q = (struct tcpiphdr *)q->ti_next;
-		m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev);
-		remque_32((void *)(q->ti_prev));
-		m_freem(m);
+		m = (struct mbuf *) REASS_MBUF_GET((struct tcpiphdr *)q->ti_prev);
+		remque_32(s, (void *)(q->ti_prev));
+		m_freem(s, m);
 	}
 
 	/*
 	 * Stick new segment in its place.
 	 */
-	insque_32(ti, (void *)(q->ti_prev));
+	insque_32(s, ti, (void *)(q->ti_prev));
 
 present:
 	/*
@@ -211,17 +208,18 @@
 	do {
 		tp->rcv_nxt += ti->ti_len;
 		flags = ti->ti_flags & TH_FIN;
-		remque_32(ti);
-		m = (struct mbuf *) REASS_MBUF(ti); /* XXX */
+		remque_32(s, ti);
+		m = REASS_MBUF_GET(ti); /* XXX */
 		ti = (struct tcpiphdr *)ti->ti_next;
 /*		if (so->so_state & SS_FCANTRCVMORE) */
 		if (so->so_state & SS_FCANTSENDMORE)
-			m_freem(m);
+                        m_freem(s, m);
 		else {
 			if (so->so_emu) {
-				if (tcp_emu(so,m)) sbappend(so, m);
+				if (tcp_emu(s, so,m))
+                                    sbappend(s, so, m);
 			} else
-				sbappend(so, m);
+				sbappend(s, so, m);
 		}
 	} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
 /*	sorwakeup(so); */
@@ -233,10 +231,7 @@
  * protocol specification dated September, 1981 very closely.
  */
 void
-tcp_input(m, iphlen, inso)
-	register struct mbuf *m;
-	int iphlen;
-	struct socket *inso;
+tcp_input(slirp_state_t *s, register struct mbuf *m, int iphlen, struct socket *inso)
 {
   	struct ip save_ip, *ip;
 	register struct tcpiphdr *ti;
@@ -252,6 +247,7 @@
 	u_long tiwin;
 	int ret;
 /*	int ts_present = 0; */
+	int mbuf_freed = 0;
 
 	DEBUG_CALL("tcp_input");
 	DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
@@ -275,7 +271,7 @@
 	}
 
 
-	tcpstat.tcps_rcvtotal++;
+	s->tcpstat.tcps_rcvtotal++;
 	/*
 	 * Get IP and TCP header together in first mbuf.
 	 * Note: IP leaves IP header in first mbuf.
@@ -308,7 +304,7 @@
 	 * ti->ti_sum = cksum(m, len);
 	 * if (ti->ti_sum) { */
 	if(cksum(m, len)) {
-	  tcpstat.tcps_rcvbadsum++;
+	  s->tcpstat.tcps_rcvbadsum++;
 	  goto drop;
 	}
 
@@ -318,7 +314,7 @@
 	 */
 	off = ti->ti_off << 2;
 	if (off < sizeof (struct tcphdr) || off > tlen) {
-	  tcpstat.tcps_rcvbadoff++;
+	  s->tcpstat.tcps_rcvbadoff++;
 	  goto drop;
 	}
 	tlen -= off;
@@ -366,16 +362,16 @@
 	 * Locate pcb for segment.
 	 */
 findso:
-	so = tcp_last_so;
+	so = s->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(&s->tcb, ti->ti_src, ti->ti_sport,
 			       ti->ti_dst, ti->ti_dport);
 		if (so)
-			tcp_last_so = so;
-		++tcpstat.tcps_socachemiss;
+			s->tcp_last_so = so;
+		++s->tcpstat.tcps_socachemiss;
 	}
 
 	/*
@@ -397,13 +393,13 @@
 
 	  if ((so = socreate()) == NULL)
 	    goto dropwithreset;
-	  if (tcp_attach(so) < 0) {
+	  if (tcp_attach(s, so) < 0) {
 	    free(so); /* Not sofree (if it failed, it's not insqued) */
 	    goto dropwithreset;
 	  }
 
-	  sbreserve(&so->so_snd, tcp_sndspace);
-	  sbreserve(&so->so_rcv, tcp_rcvspace);
+	  sbreserve(&so->so_snd, TCP_SNDSPACE);
+	  sbreserve(&so->so_rcv, TCP_RCVSPACE);
 
 	  /*		tcp_last_so = so; */  /* XXX ? */
 	  /*		tp = sototcpcb(so);    */
@@ -448,17 +444,17 @@
 	 * Reset idle time and keep-alive timer.
 	 */
 	tp->t_idle = 0;
-	if (so_options)
-	   tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+	if (SO_OPTIONS)
+	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 	else
-	   tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+	   tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
 
 	/*
 	 * Process options if not in LISTEN state,
 	 * else do it below (after getting remote address).
 	 */
 	if (optp && tp->t_state != TCPS_LISTEN)
-		tcp_dooptions(tp, (u_char *)optp, optlen, ti);
+		tcp_dooptions(s, tp, (u_char *)optp, optlen, ti);
 /* , */
 /*			&ts_present, &ts_val, &ts_ecr); */
 
@@ -503,19 +499,19 @@
 				/*
 				 * this is a pure ack for outstanding data.
 				 */
-				++tcpstat.tcps_predack;
+				++s->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))
-					tcp_xmit_timer(tp, tp->t_rtt);
+					tcp_xmit_timer(s, tp, tp->t_rtt);
 				acked = ti->ti_ack - tp->snd_una;
-				tcpstat.tcps_rcvackpack++;
-				tcpstat.tcps_rcvackbyte += acked;
+				s->tcpstat.tcps_rcvackpack++;
+				s->tcpstat.tcps_rcvackbyte += acked;
 				sbdrop(&so->so_snd, acked);
 				tp->snd_una = ti->ti_ack;
-				m_freem(m);
+				m_freem(s, m);
 
 				/*
 				 * If all outstanding data are acked, stop
@@ -544,7 +540,7 @@
 				 * we don't need this.. XXX???
 				 */
 				if (so->so_snd.sb_cc)
-					(void) tcp_output(tp);
+					(void) tcp_output(s, tp);
 
 				return;
 			}
@@ -556,17 +552,18 @@
 			 * with nothing on the reassembly queue and
 			 * we have enough buffer space to take it.
 			 */
-			++tcpstat.tcps_preddat;
+			++s->tcpstat.tcps_preddat;
 			tp->rcv_nxt += ti->ti_len;
-			tcpstat.tcps_rcvpack++;
-			tcpstat.tcps_rcvbyte += ti->ti_len;
+			s->tcpstat.tcps_rcvpack++;
+			s->tcpstat.tcps_rcvbyte += ti->ti_len;
 			/*
 			 * Add data to socket buffer.
 			 */
 			if (so->so_emu) {
-				if (tcp_emu(so,m)) sbappend(so, m);
+				if (tcp_emu(s, so,m))
+                                    sbappend(s, so, m);
 			} else
-				sbappend(so, m);
+				sbappend(s, so, m);
 
 			/*
 			 * XXX This is called when data arrives.  Later, check
@@ -584,7 +581,7 @@
 			 * TCP throughput.  See RFC 2581.
 			 */
 			tp->t_flags |= TF_ACKNOW;
-			tcp_output(tp);
+			tcp_output(s, tp);
 			return;
 		}
 	} /* header prediction */
@@ -634,7 +631,8 @@
 	   * 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) {
+	  if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
+              s->special_addr.s_addr) {
 	    int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;
 	    if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) {
 #if 0
@@ -646,7 +644,7 @@
               {
 		/* May be an add exec */
 		struct ex_list *ex_ptr;
-		for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+		for(ex_ptr = s->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_state |= SS_CTL;
@@ -664,13 +662,14 @@
 	    goto cont_input;
 	  }
 
-	  if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
+	  if ((tcp_fconnect(s, so) == -1) && (errno != EINPROGRESS)
+              && (errno != EWOULDBLOCK)) {
 	    u_char code=ICMP_UNREACH_NET;
 	    DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n",
 			errno,strerror(errno)));
 	    if(errno == ECONNREFUSED) {
 	      /* ACK the SYN, send RST to refuse the connection */
-	      tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
+	      tcp_respond(s, tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
 			  TH_RST|TH_ACK);
 	    } else {
 	      if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
@@ -681,10 +680,10 @@
 	      m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 	      m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 	      *ip=save_ip;
-	      icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));
+	      icmp_error(s, m, ICMP_UNREACH,code, 0,strerror(errno));
 	    }
-	    tp = tcp_close(tp);
-	    m_free(m);
+	    tp = tcp_close(s, tp);
+	    m_free(s, m);
 	  } else {
 	    /*
 	     * Haven't connected yet, save the current mbuf
@@ -704,29 +703,29 @@
 	   * Check if the connect succeeded
 	   */
 	  if (so->so_state & SS_NOFDREF) {
-	    tp = tcp_close(tp);
+	    tp = tcp_close(s, tp);
 	    goto dropwithreset;
 	  }
 	cont_input:
 	  tcp_template(tp);
 
 	  if (optp)
-	    tcp_dooptions(tp, (u_char *)optp, optlen, ti);
+	    tcp_dooptions(s, tp, (u_char *)optp, optlen, ti);
 	  /* , */
 	  /*				&ts_present, &ts_val, &ts_ecr); */
 
 	  if (iss)
 	    tp->iss = iss;
 	  else
-	    tp->iss = tcp_iss;
-	  tcp_iss += TCP_ISSINCR/2;
+	    tp->iss = s->tcp_iss;
+	  s->tcp_iss += TCP_ISSINCR / 2;
 	  tp->irs = ti->ti_seq;
 	  tcp_sendseqinit(tp);
 	  tcp_rcvseqinit(tp);
 	  tp->t_flags |= TF_ACKNOW;
 	  tp->t_state = TCPS_SYN_RECEIVED;
 	  tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
-	  tcpstat.tcps_accepts++;
+	  s->tcpstat.tcps_accepts++;
 	  goto trimthenstep6;
 	} /* case TCPS_LISTEN */
 
@@ -750,7 +749,7 @@
 
 		if (tiflags & TH_RST) {
 			if (tiflags & TH_ACK)
-				tp = tcp_drop(tp,0); /* XXX Check t_softerror! */
+				tp = tcp_drop(s, tp,0); /* XXX Check t_softerror! */
 			goto drop;
 		}
 
@@ -767,7 +766,7 @@
 		tcp_rcvseqinit(tp);
 		tp->t_flags |= TF_ACKNOW;
 		if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
-			tcpstat.tcps_connects++;
+			s->tcpstat.tcps_connects++;
 			soisfconnected(so);
 			tp->t_state = TCPS_ESTABLISHED;
 
@@ -778,14 +777,14 @@
  *				tp->rcv_scale = tp->request_r_scale;
  *			}
  */
-			(void) tcp_reass(tp, (struct tcpiphdr *)0,
+			(void) tcp_reass(s, tp, (struct tcpiphdr *)0,
 				(struct mbuf *)0);
 			/*
 			 * if we didn't have to retransmit the SYN,
 			 * use its rtt as our initial srtt & rtt var.
 			 */
 			if (tp->t_rtt)
-				tcp_xmit_timer(tp, tp->t_rtt);
+				tcp_xmit_timer(s, tp, tp->t_rtt);
 		} else
 			tp->t_state = TCPS_SYN_RECEIVED;
 
@@ -801,8 +800,8 @@
 			m_adj(m, -todrop);
 			ti->ti_len = tp->rcv_wnd;
 			tiflags &= ~TH_FIN;
-			tcpstat.tcps_rcvpackafterwin++;
-			tcpstat.tcps_rcvbyteafterwin += todrop;
+			s->tcpstat.tcps_rcvpackafterwin++;
+			s->tcpstat.tcps_rcvbyteafterwin += todrop;
 		}
 		tp->snd_wl1 = ti->ti_seq - 1;
 		tp->rcv_up = ti->ti_seq;
@@ -873,11 +872,11 @@
 			 */
 			tp->t_flags |= TF_ACKNOW;
 			todrop = ti->ti_len;
-			tcpstat.tcps_rcvduppack++;
-			tcpstat.tcps_rcvdupbyte += todrop;
+			s->tcpstat.tcps_rcvduppack++;
+			s->tcpstat.tcps_rcvdupbyte += todrop;
 		} else {
-			tcpstat.tcps_rcvpartduppack++;
-			tcpstat.tcps_rcvpartdupbyte += todrop;
+			s->tcpstat.tcps_rcvpartduppack++;
+			s->tcpstat.tcps_rcvpartdupbyte += todrop;
 		}
 		m_adj(m, todrop);
 		ti->ti_seq += todrop;
@@ -895,8 +894,8 @@
 	 */
 	if ((so->so_state & SS_NOFDREF) &&
 	    tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
-		tp = tcp_close(tp);
-		tcpstat.tcps_rcvafterclose++;
+		tp = tcp_close(s, tp);
+		s->tcpstat.tcps_rcvafterclose++;
 		goto dropwithreset;
 	}
 
@@ -906,9 +905,9 @@
 	 */
 	todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
 	if (todrop > 0) {
-		tcpstat.tcps_rcvpackafterwin++;
+		s->tcpstat.tcps_rcvpackafterwin++;
 		if (todrop >= ti->ti_len) {
-			tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
+			s->tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
 			/*
 			 * If a new connection request is received
 			 * while in TIME_WAIT, drop the old connection
@@ -919,7 +918,7 @@
 			    tp->t_state == TCPS_TIME_WAIT &&
 			    SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
 				iss = tp->rcv_nxt + TCP_ISSINCR;
-				tp = tcp_close(tp);
+				tp = tcp_close(s, tp);
 				goto findso;
 			}
 			/*
@@ -931,11 +930,11 @@
 			 */
 			if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
 				tp->t_flags |= TF_ACKNOW;
-				tcpstat.tcps_rcvwinprobe++;
+				s->tcpstat.tcps_rcvwinprobe++;
 			} else
 				goto dropafterack;
 		} else
-			tcpstat.tcps_rcvbyteafterwin += todrop;
+			s->tcpstat.tcps_rcvbyteafterwin += todrop;
 		m_adj(m, -todrop);
 		ti->ti_len -= todrop;
 		tiflags &= ~(TH_PUSH|TH_FIN);
@@ -976,14 +975,14 @@
 /*		so->so_error = ECONNRESET; */
 	close:
 		tp->t_state = TCPS_CLOSED;
-		tcpstat.tcps_drops++;
-		tp = tcp_close(tp);
+		s->tcpstat.tcps_drops++;
+		tp = tcp_close(s, tp);
 		goto drop;
 
 	case TCPS_CLOSING:
 	case TCPS_LAST_ACK:
 	case TCPS_TIME_WAIT:
-		tp = tcp_close(tp);
+		tp = tcp_close(s, tp);
 		goto drop;
 	}
 
@@ -992,7 +991,7 @@
 	 * error and we send an RST and drop the connection.
 	 */
 	if (tiflags & TH_SYN) {
-		tp = tcp_drop(tp,0);
+		tp = tcp_drop(s, tp,0);
 		goto dropwithreset;
 	}
 
@@ -1015,7 +1014,7 @@
 		if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
 		    SEQ_GT(ti->ti_ack, tp->snd_max))
 			goto dropwithreset;
-		tcpstat.tcps_connects++;
+		s->tcpstat.tcps_connects++;
 		tp->t_state = TCPS_ESTABLISHED;
 		/*
 		 * The sent SYN is ack'ed with our sequence number +1
@@ -1027,7 +1026,7 @@
 		tp->snd_una=ti->ti_ack;
 		if (so->so_state & SS_CTL) {
 		  /* So tcp_ctl reports the right state */
-		  ret = tcp_ctl(so);
+		  ret = tcp_ctl(s, so);
 		  if (ret == 1) {
 		    soisfconnected(so);
 		    so->so_state &= ~SS_CTL;   /* success XXX */
@@ -1048,7 +1047,7 @@
  *			tp->rcv_scale = tp->request_r_scale;
  *		}
  */
-		(void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);
+		(void) tcp_reass(s, tp, (struct tcpiphdr *)0, (struct mbuf *)0);
 		tp->snd_wl1 = ti->ti_seq - 1;
 		/* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
 		goto synrx_to_est;
@@ -1072,7 +1071,7 @@
 
 		if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
 			if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
-			  tcpstat.tcps_rcvdupack++;
+			  s->tcpstat.tcps_rcvdupack++;
 			  DEBUG_MISC((dfd," dup ack  m = %lx  so = %lx \n",
 				      (long )m, (long )so));
 				/*
@@ -1102,7 +1101,7 @@
 				if (tp->t_timer[TCPT_REXMT] == 0 ||
 				    ti->ti_ack != tp->snd_una)
 					tp->t_dupacks = 0;
-				else if (++tp->t_dupacks == tcprexmtthresh) {
+				else if (++tp->t_dupacks == TCPREXMTTHRESH) {
 					tcp_seq onxt = tp->snd_nxt;
 					u_int win =
 					    min(tp->snd_wnd, tp->snd_cwnd) / 2 /
@@ -1115,15 +1114,15 @@
 					tp->t_rtt = 0;
 					tp->snd_nxt = ti->ti_ack;
 					tp->snd_cwnd = tp->t_maxseg;
-					(void) tcp_output(tp);
+					(void) tcp_output(s, tp);
 					tp->snd_cwnd = tp->snd_ssthresh +
 					       tp->t_maxseg * tp->t_dupacks;
 					if (SEQ_GT(onxt, tp->snd_nxt))
 						tp->snd_nxt = onxt;
 					goto drop;
-				} else if (tp->t_dupacks > tcprexmtthresh) {
+				} else if (tp->t_dupacks > TCPREXMTTHRESH) {
 					tp->snd_cwnd += tp->t_maxseg;
-					(void) tcp_output(tp);
+					(void) tcp_output(s, tp);
 					goto drop;
 				}
 			} else
@@ -1135,17 +1134,17 @@
 		 * If the congestion window was inflated to account
 		 * for the other side's cached packets, retract it.
 		 */
-		if (tp->t_dupacks > tcprexmtthresh &&
+		if (tp->t_dupacks > TCPREXMTTHRESH &&
 		    tp->snd_cwnd > tp->snd_ssthresh)
 			tp->snd_cwnd = tp->snd_ssthresh;
 		tp->t_dupacks = 0;
 		if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
-			tcpstat.tcps_rcvacktoomuch++;
+			s->tcpstat.tcps_rcvacktoomuch++;
 			goto dropafterack;
 		}
 		acked = ti->ti_ack - tp->snd_una;
-		tcpstat.tcps_rcvackpack++;
-		tcpstat.tcps_rcvackbyte += acked;
+		s->tcpstat.tcps_rcvackpack++;
+		s->tcpstat.tcps_rcvackbyte += acked;
 
 		/*
 		 * If we have a timestamp reply, update smoothed
@@ -1161,7 +1160,7 @@
  *		else
  */
 		     if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
-			tcp_xmit_timer(tp,tp->t_rtt);
+			tcp_xmit_timer(s, tp,tp->t_rtt);
 
 		/*
 		 * If all outstanding data is acked, stop retransmit
@@ -1227,7 +1226,7 @@
 				 */
 				if (so->so_state & SS_FCANTRCVMORE) {
 					soisfdisconnected(so);
-					tp->t_timer[TCPT_2MSL] = tcp_maxidle;
+					tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;
 				}
 				tp->t_state = TCPS_FIN_WAIT_2;
 			}
@@ -1256,7 +1255,7 @@
 		 */
 		case TCPS_LAST_ACK:
 			if (ourfinisacked) {
-				tp = tcp_close(tp);
+				tp = tcp_close(s, tp);
 				goto drop;
 			}
 			break;
@@ -1284,7 +1283,7 @@
 		/* keep track of pure window updates */
 		if (ti->ti_len == 0 &&
 		    tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
-			tcpstat.tcps_rcvwinupd++;
+			s->tcpstat.tcps_rcvwinupd++;
 		tp->snd_wnd = tiwin;
 		tp->snd_wl1 = ti->ti_seq;
 		tp->snd_wl2 = ti->ti_ack;
@@ -1350,7 +1349,7 @@
 	 */
 	if ((ti->ti_len || (tiflags&TH_FIN)) &&
 	    TCPS_HAVERCVDFIN(tp->t_state) == 0) {
-		TCP_REASS(tp, ti, m, so, tiflags);
+		TCP_REASS(s, tp, ti, m, so, tiflags);
 		/*
 		 * Note the amount of data that peer has sent into
 		 * our window, in order to estimate the sender's
@@ -1358,7 +1357,7 @@
 		 */
 		len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt);
 	} else {
-		m_free(m);
+	        mbuf_freed = 1; /* The mbuf must be freed, but only when its content is not needed anymore. */
 		tiflags &= ~TH_FIN;
 	}
 
@@ -1378,7 +1377,7 @@
 			 * to send the FIN.
 			 */
 /*			sofcantrcvmore(so); */
-			sofwdrain(so);
+			sofwdrain(s, so);
 
 			tp->t_flags |= TF_ACKNOW;
 			tp->rcv_nxt++;
@@ -1445,11 +1444,14 @@
 		tp->t_flags |= TF_ACKNOW;
 	}
 
+	if (mbuf_freed) {
+		m_free(s, m);
+	}
 	/*
 	 * Return any desired output.
 	 */
 	if (needoutput || (tp->t_flags & TF_ACKNOW)) {
-		(void) tcp_output(tp);
+		(void) tcp_output(s, tp);
 	}
 	return;
 
@@ -1460,18 +1462,18 @@
 	 */
 	if (tiflags & TH_RST)
 		goto drop;
-	m_freem(m);
+	m_freem(s, m);
 	tp->t_flags |= TF_ACKNOW;
-	(void) tcp_output(tp);
+	(void) tcp_output(s, tp);
 	return;
 
 dropwithreset:
 	/* reuses m if m!=NULL, m_free() unnecessary */
 	if (tiflags & TH_ACK)
-		tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
+		tcp_respond(s, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
 	else {
 		if (tiflags & TH_SYN) ti->ti_len++;
-		tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
+		tcp_respond(s, tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
 		    TH_RST|TH_ACK);
 	}
 
@@ -1481,7 +1483,7 @@
 	/*
 	 * Drop space held by incoming segment and return.
 	 */
-	m_free(m);
+	m_free(s, m);
 
 	return;
 }
@@ -1490,12 +1492,9 @@
 /*	int *ts_present;
  *	u_int32_t *ts_val, *ts_ecr;
  */
-void
-tcp_dooptions(tp, cp, cnt, ti)
-	struct tcpcb *tp;
-	u_char *cp;
-	int cnt;
-	struct tcpiphdr *ti;
+static void
+tcp_dooptions(slirp_state_t *s, struct tcpcb *tp, u_char *cp, int cnt,
+              struct tcpiphdr *ti)
 {
 	u_int16_t mss;
 	int opt, optlen;
@@ -1526,7 +1525,7 @@
 				continue;
 			memcpy((char *) &mss, (char *) cp + 2, sizeof(mss));
 			NTOHS(mss);
-			(void) tcp_mss(tp, mss);	/* sets t_maxseg */
+			(void) tcp_mss(s, tp, mss);	/* sets t_maxseg */
 			break;
 
 /*		case TCPOPT_WINDOW:
@@ -1605,10 +1604,8 @@
  * and update averages and current timeout.
  */
 
-void
-tcp_xmit_timer(tp, rtt)
-	register struct tcpcb *tp;
-	int rtt;
+static void
+tcp_xmit_timer(slirp_state_t *s, register struct tcpcb *tp, int rtt)
 {
 	register short delta;
 
@@ -1616,7 +1613,7 @@
 	DEBUG_ARG("tp = %lx", (long)tp);
 	DEBUG_ARG("rtt = %d", rtt);
 
-	tcpstat.tcps_rttupdated++;
+	s->tcpstat.tcps_rttupdated++;
 	if (tp->t_srtt != 0) {
 		/*
 		 * srtt is stored as fixed point with 3 bits after the
@@ -1696,9 +1693,7 @@
  */
 
 int
-tcp_mss(tp, offer)
-        register struct tcpcb *tp;
-        u_int offer;
+tcp_mss(slirp_state_t *s, register struct tcpcb *tp, u_int offer)
 {
 	struct socket *so = tp->t_socket;
 	int mss;
@@ -1707,7 +1702,7 @@
 	DEBUG_ARG("tp = %lx", (long)tp);
 	DEBUG_ARG("offer = %d", offer);
 
-	mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr);
+	mss = min(s->if_mtu, s->if_mru) - sizeof(struct tcpiphdr);
 	if (offer)
 		mss = min(mss, offer);
 	mss = max(mss, 32);
@@ -1716,8 +1711,12 @@
 
 	tp->snd_cwnd = mss;
 
-	sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));
-	sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));
+	sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ?
+                                               (mss - (TCP_SNDSPACE % mss)) :
+                                               0));
+	sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ?
+                                               (mss - (TCP_RCVSPACE % mss)) :
+                                               0));
 
 	DEBUG_MISC((dfd, " returning mss = %d\n", mss));
 
Index: qemu/slirp/tcp_output.c
===================================================================
--- qemu.orig/slirp/tcp_output.c	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tcp_output.c	2007-10-20 13:49:13.000000000 +0000
@@ -48,14 +48,14 @@
  * Since this is only used in "stats socket", we give meaning
  * names instead of the REAL names
  */
-char *tcpstates[] = {
+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",
 };
 
-u_char  tcp_outflags[TCP_NSTATES] = {
+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,
 	TH_FIN|TH_ACK, TH_ACK, TH_ACK,
@@ -68,8 +68,7 @@
  * Tcp output routine: figure out what should be sent and send it.
  */
 int
-tcp_output(tp)
-	register struct tcpcb *tp;
+tcp_output(slirp_state_t *s, register struct tcpcb *tp)
 {
 	register struct socket *so = tp->t_socket;
 	register long len, win;
@@ -263,7 +262,7 @@
 	/*
 	 * No reason to send a segment, just return.
 	 */
-	tcpstat.tcps_didnuttin++;
+	s->tcpstat.tcps_didnuttin++;
 
 	return (0);
 
@@ -285,7 +284,7 @@
 
 			opt[0] = TCPOPT_MAXSEG;
 			opt[1] = 4;
-			mss = htons((u_int16_t) tcp_mss(tp, 0));
+			mss = htons((u_int16_t) tcp_mss(s, tp, 0));
 			memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
 			optlen = 4;
 
@@ -339,22 +338,22 @@
 	 */
 	if (len) {
 		if (tp->t_force && len == 1)
-			tcpstat.tcps_sndprobe++;
+			s->tcpstat.tcps_sndprobe++;
 		else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
-			tcpstat.tcps_sndrexmitpack++;
-			tcpstat.tcps_sndrexmitbyte += len;
+			s->tcpstat.tcps_sndrexmitpack++;
+			s->tcpstat.tcps_sndrexmitbyte += len;
 		} else {
-			tcpstat.tcps_sndpack++;
-			tcpstat.tcps_sndbyte += len;
+			s->tcpstat.tcps_sndpack++;
+			s->tcpstat.tcps_sndbyte += len;
 		}
 
-		m = m_get();
+		m = m_get(s);
 		if (m == NULL) {
 /*			error = ENOBUFS; */
 			error = 1;
 			goto out;
 		}
-		m->m_data += if_maxlinkhdr;
+		m->m_data += s->if_maxlinkhdr;
 		m->m_len = hdrlen;
 
 		/*
@@ -382,21 +381,21 @@
 			flags |= TH_PUSH;
 	} else {
 		if (tp->t_flags & TF_ACKNOW)
-			tcpstat.tcps_sndacks++;
+			s->tcpstat.tcps_sndacks++;
 		else if (flags & (TH_SYN|TH_FIN|TH_RST))
-			tcpstat.tcps_sndctrl++;
+			s->tcpstat.tcps_sndctrl++;
 		else if (SEQ_GT(tp->snd_up, tp->snd_una))
-			tcpstat.tcps_sndurg++;
+			s->tcpstat.tcps_sndurg++;
 		else
-			tcpstat.tcps_sndwinup++;
+			s->tcpstat.tcps_sndwinup++;
 
-		m = m_get();
+		m = m_get(s);
 		if (m == NULL) {
 /*			error = ENOBUFS; */
 			error = 1;
 			goto out;
 		}
-		m->m_data += if_maxlinkhdr;
+		m->m_data += s->if_maxlinkhdr;
 		m->m_len = hdrlen;
 	}
 
@@ -500,7 +499,7 @@
 			if (tp->t_rtt == 0) {
 				tp->t_rtt = 1;
 				tp->t_rtseq = startseq;
-				tcpstat.tcps_segstimed++;
+				s->tcpstat.tcps_segstimed++;
 			}
 		}
 
@@ -536,7 +535,7 @@
 
 	((struct ip *)ti)->ip_len = m->m_len;
 
-	((struct ip *)ti)->ip_ttl = ip_defttl;
+	((struct ip *)ti)->ip_ttl = IPDEFTTL;
 	((struct ip *)ti)->ip_tos = so->so_iptos;
 
 /* #if BSD >= 43 */
@@ -544,7 +543,7 @@
 /*	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);
+	error = ip_output(s, so, m);
 
 /* #else
  *	error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
@@ -567,7 +566,7 @@
  */
 		return (error);
 	}
-	tcpstat.tcps_sndtotal++;
+	s->tcpstat.tcps_sndtotal++;
 
 	/*
 	 * Data sent (as far as we can tell).
Index: qemu/slirp/tcp_subr.c
===================================================================
--- qemu.orig/slirp/tcp_subr.c	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tcp_subr.c	2007-10-20 16:46:29.000000000 +0000
@@ -45,29 +45,16 @@
 #define WANT_SYS_IOCTL_H
 #include <slirp.h>
 
-/* patchable/settable parameters for tcp */
-int 	tcp_mssdflt = TCP_MSS;
-int 	tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
-int	tcp_do_rfc1323 = 0;	/* Don't do rfc1323 performance enhancements */
-int	tcp_rcvspace;	/* You may want to change this */
-int	tcp_sndspace;	/* Keep small if you have an error prone link */
 
 /*
  * Tcp initialization
  */
 void
-tcp_init()
+tcp_init(slirp_state_t *s)
 {
-	tcp_iss = 1;		/* wrong */
-	tcb.so_next = tcb.so_prev = &tcb;
-
-	/* tcp_rcvspace = our Window we advertise to the remote */
-	tcp_rcvspace = TCP_RCVSPACE;
-	tcp_sndspace = TCP_SNDSPACE;
-
-	/* Make sure tcp_sndspace is at least 2*MSS */
-	if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)))
-		tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr));
+	s->tcp_iss = 1;		/* wrong */
+	s->tcb.so_next = s->tcb.so_prev = &s->tcb;
+        s->tcp_last_so = &s->tcb;
 }
 
 /*
@@ -117,12 +104,8 @@
  * segment are as specified by the parameters.
  */
 void
-tcp_respond(tp, ti, m, ack, seq, flags)
-	struct tcpcb *tp;
-	register struct tcpiphdr *ti;
-	register struct mbuf *m;
-	tcp_seq ack, seq;
-	int flags;
+tcp_respond(slirp_state_t *s, struct tcpcb *tp, struct tcpiphdr *ti,
+            struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags)
 {
 	register int tlen;
 	int win = 0;
@@ -138,14 +121,14 @@
 	if (tp)
 		win = sbspace(&tp->t_socket->so_rcv);
 	if (m == 0) {
-		if ((m = m_get()) == NULL)
+		if ((m = m_get(s)) == NULL)
 			return;
 #ifdef TCP_COMPAT_42
 		tlen = 1;
 #else
 		tlen = 0;
 #endif
-		m->m_data += if_maxlinkhdr;
+		m->m_data += s->if_maxlinkhdr;
 		*mtod(m, struct tcpiphdr *) = *ti;
 		ti = mtod(m, struct tcpiphdr *);
 		flags = TH_ACK;
@@ -186,9 +169,9 @@
 	if(flags & TH_RST)
 	  ((struct ip *)ti)->ip_ttl = MAXTTL;
 	else
-	  ((struct ip *)ti)->ip_ttl = ip_defttl;
+	  ((struct ip *)ti)->ip_ttl = IPDEFTTL;
 
-	(void) ip_output((struct socket *)0, m);
+	(void) ip_output(s, (struct socket *)0, m);
 }
 
 /*
@@ -197,8 +180,7 @@
  * protocol control block.
  */
 struct tcpcb *
-tcp_newtcpcb(so)
-	struct socket *so;
+tcp_newtcpcb(slirp_state_t *s, struct socket *so)
 {
 	register struct tcpcb *tp;
 
@@ -207,10 +189,10 @@
 		return ((struct tcpcb *)0);
 
 	memset((char *) tp, 0, sizeof(struct tcpcb));
-	tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
-	tp->t_maxseg = tcp_mssdflt;
+	tp->seg_next = tp->seg_prev = tp;
+	tp->t_maxseg = TCP_MSS;
 
-	tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
+	tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
 	tp->t_socket = so;
 
 	/*
@@ -219,7 +201,7 @@
 	 * reasonable initial retransmit time.
 	 */
 	tp->t_srtt = TCPTV_SRTTBASE;
-	tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
+	tp->t_rttvar = TCPTV_SRTTDFLT << 2;
 	tp->t_rttmin = TCPTV_MIN;
 
 	TCPT_RANGESET(tp->t_rxtcur,
@@ -240,7 +222,7 @@
  * the specified error.  If connection is synchronized,
  * then send a RST to peer.
  */
-struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
+struct tcpcb *tcp_drop(slirp_state_t *s, struct tcpcb *tp, int err)
 {
 /* tcp_drop(tp, errno)
 	register struct tcpcb *tp;
@@ -254,15 +236,15 @@
 
 	if (TCPS_HAVERCVDSYN(tp->t_state)) {
 		tp->t_state = TCPS_CLOSED;
-		(void) tcp_output(tp);
-		tcpstat.tcps_drops++;
+		(void) tcp_output(s, tp);
+		s->tcpstat.tcps_drops++;
 	} else
-		tcpstat.tcps_conndrops++;
+		s->tcpstat.tcps_conndrops++;
 /*	if (errno == ETIMEDOUT && tp->t_softerror)
  *		errno = tp->t_softerror;
  */
 /*	so->so_error = errno; */
-	return (tcp_close(tp));
+	return (tcp_close(s, tp));
 }
 
 /*
@@ -272,8 +254,7 @@
  *	wake up any sleepers
  */
 struct tcpcb *
-tcp_close(tp)
-	register struct tcpcb *tp;
+tcp_close(slirp_state_t *s, register struct tcpcb *tp)
 {
 	register struct tcpiphdr *t;
 	struct socket *so = tp->t_socket;
@@ -286,9 +267,9 @@
 	t = (struct tcpiphdr *) tp->seg_next;
 	while (t != (struct tcpiphdr *)tp) {
 		t = (struct tcpiphdr *)t->ti_next;
-		m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev);
-		remque_32((struct tcpiphdr *) t->ti_prev);
-		m_freem(m);
+		m = REASS_MBUF_GET((struct tcpiphdr *)t->ti_prev);
+		remque_32(s, (struct tcpiphdr *) t->ti_prev);
+		m_freem(s, m);
 	}
 	/* It's static */
 /*	if (tp->t_template)
@@ -299,16 +280,17 @@
 	so->so_tcpcb = 0;
 	soisfdisconnected(so);
 	/* clobber input socket cache if we're closing the cached connection */
-	if (so == tcp_last_so)
-		tcp_last_so = &tcb;
+	if (so == s->tcp_last_so)
+		s->tcp_last_so = &s->tcb;
 	closesocket(so->s);
 	sbfree(&so->so_rcv);
 	sbfree(&so->so_snd);
-	sofree(so);
-	tcpstat.tcps_closed++;
+	sofree(s, so);
+	s->tcpstat.tcps_closed++;
 	return ((struct tcpcb *)0);
 }
 
+#ifdef notdef
 void
 tcp_drain()
 {
@@ -319,9 +301,6 @@
  * When a source quench is received, close congestion window
  * to one segment.  We will gradually open it again as we proceed.
  */
-
-#ifdef notdef
-
 void
 tcp_quench(i, errno)
 
@@ -350,8 +329,7 @@
  * We can let the user exit from the close as soon as the FIN is acked.
  */
 void
-tcp_sockclosed(tp)
-	struct tcpcb *tp;
+tcp_sockclosed(slirp_state_t *s, struct tcpcb *tp)
 {
 
 	DEBUG_CALL("tcp_sockclosed");
@@ -363,7 +341,7 @@
 	case TCPS_LISTEN:
 	case TCPS_SYN_SENT:
 		tp->t_state = TCPS_CLOSED;
-		tp = tcp_close(tp);
+		tp = tcp_close(s, tp);
 		break;
 
 	case TCPS_SYN_RECEIVED:
@@ -379,7 +357,7 @@
 	if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
 		soisfdisconnected(tp->t_socket);
 	if (tp)
-		tcp_output(tp);
+		tcp_output(s, tp);
 }
 
 /*
@@ -392,8 +370,7 @@
  * nonblocking.  Connect returns after the SYN is sent, and does
  * not wait for ACK+SYN.
  */
-int tcp_fconnect(so)
-     struct socket *so;
+int tcp_fconnect(slirp_state_t *s, struct socket *so)
 {
   int ret=0;
 
@@ -401,25 +378,25 @@
   DEBUG_ARG("so = %lx", (long )so);
 
   if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) {
-    int opt, s=so->s;
+    int opt, fd = so->s;
     struct sockaddr_in addr;
 
-    fd_nonblock(s);
+    fd_nonblock(fd);
     opt = 1;
-    setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
+    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
     opt = 1;
-    setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
+    setsockopt(fd, 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 & htonl(0xffffff00)) == s->special_addr.s_addr) {
       /* It's an alias */
       switch(ntohl(so->so_faddr.s_addr) & 0xff) {
       case CTL_DNS:
-	addr.sin_addr = dns_addr;
+	addr.sin_addr = s->dns_addr;
 	break;
       case CTL_ALIAS:
       default:
-	addr.sin_addr = loopback_addr;
+	addr.sin_addr = s->loopback_addr;
 	break;
       }
     } else
@@ -430,7 +407,7 @@
 		"addr.sin_addr.s_addr=%.16s\n",
 		ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
     /* We don't care what port we get */
-    ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
+    ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
 
     /*
      * If it's not in progress, it failed, so we just return 0,
@@ -455,14 +432,13 @@
  * here and SYN the local-host.
  */
 void
-tcp_connect(inso)
-	struct socket *inso;
+tcp_connect(slirp_state_t *s, struct socket *inso)
 {
 	struct socket *so;
 	struct sockaddr_in addr;
 	int addrlen = sizeof(struct sockaddr_in);
 	struct tcpcb *tp;
-	int s, opt;
+	int fd, opt;
 
 	DEBUG_CALL("tcp_connect");
 	DEBUG_ARG("inso = %lx", (long)inso);
@@ -480,7 +456,7 @@
 			closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
 			return;
 		}
-		if (tcp_attach(so) < 0) {
+		if (tcp_attach(s, so) < 0) {
 			free(so); /* NOT sofree */
 			return;
 		}
@@ -488,25 +464,25 @@
 		so->so_lport = inso->so_lport;
 	}
 
-	(void) tcp_mss(sototcpcb(so), 0);
+	(void) tcp_mss(s, sototcpcb(so), 0);
 
-	if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
-		tcp_close(sototcpcb(so)); /* This will sofree() as well */
+	if ((fd = accept(inso->s, (struct sockaddr *)&addr, &addrlen)) < 0) {
+		tcp_close(s, sototcpcb(so)); /* This will sofree() as well */
 		return;
 	}
-	fd_nonblock(s);
+	fd_nonblock(fd);
 	opt = 1;
-	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
+	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
 	opt = 1;
-	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
+	setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
 	opt = 1;
-	setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
+	setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(int));
 
 	so->so_fport = addr.sin_port;
 	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;
+	if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == s->loopback_addr.s_addr)
+	   so->so_faddr = s->alias_addr;
 
 	/* Close the accept() socket, set right state */
 	if (inso->so_state & SS_FACCEPTONCE) {
@@ -514,7 +490,7 @@
 		so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
 					   /* if it's not FACCEPTONCE, it's already NOFDREF */
 	}
-	so->s = s;
+	so->s = fd;
 
 	so->so_iptos = tcp_tos(so);
 	tp = sototcpcb(so);
@@ -528,27 +504,26 @@
  */
 
 /*	soisconnecting(so); */ /* NOFDREF used instead */
-	tcpstat.tcps_connattempt++;
+	s->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;
+	tp->iss = s->tcp_iss;
+	s->tcp_iss += TCP_ISSINCR / 2;
 	tcp_sendseqinit(tp);
-	tcp_output(tp);
+	tcp_output(s, tp);
 }
 
 /*
  * Attach a TCPCB to a socket.
  */
 int
-tcp_attach(so)
-	struct socket *so;
+tcp_attach(slirp_state_t *s, struct socket *so)
 {
-	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
+	if ((so->so_tcpcb = tcp_newtcpcb(s, so)) == NULL)
 	   return -1;
 
-	insque(so, &tcb);
+	insque(s, so, &s->tcb);
 
 	return 0;
 }
@@ -556,7 +531,7 @@
 /*
  * Set the socket's type of service field
  */
-struct tos_t tcptos[] = {
+static const struct tos_t tcptos[] = {
 	  {0, 20, IPTOS_THROUGHPUT, 0},	/* ftp data */
 	  {21, 21, IPTOS_LOWDELAY,  EMU_FTP},	/* ftp control */
 	  {0, 23, IPTOS_LOWDELAY, 0},	/* telnet */
@@ -572,8 +547,6 @@
 	  {0, 0, 0, 0}
 };
 
-struct emu_t *tcpemu = 0;
-
 /*
  * Return TOS according to the above table
  */
@@ -582,7 +555,6 @@
 	struct socket *so;
 {
 	int i = 0;
-	struct emu_t *emup;
 
 	while(tcptos[i].tos) {
 		if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
@@ -593,20 +565,9 @@
 		i++;
 	}
 
-	/* Nope, lets see if there's a user-added one */
-	for (emup = tcpemu; emup; emup = emup->next) {
-		if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
-		    (emup->lport && (ntohs(so->so_lport) == emup->lport))) {
-			so->so_emu = emup->emu;
-			return emup->tos;
-		}
-	}
-
 	return 0;
 }
 
-int do_echo = -1;
-
 /*
  * Emulate programs that try and connect to us
  * This includes ftp (the data connection is
@@ -632,9 +593,7 @@
  * NOTE: if you return 0 you MUST m_free() the mbuf!
  */
 int
-tcp_emu(so, m)
-	struct socket *so;
-	struct mbuf *m;
+tcp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m)
 {
 	u_int n1, n2, n3, n4, n5, n6;
 	char buff[256];
@@ -665,11 +624,11 @@
 			so_rcv->sb_rptr += m->m_len;
 			m->m_data[m->m_len] = 0; /* NULL terminate */
 			if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
-				if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) {
+				if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
 					HTONS(n1);
 					HTONS(n2);
 					/* n2 is the one on our host */
-					for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
+					for (tmpso = s->tcb.so_next; tmpso != &s->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 &&
@@ -685,7 +644,7 @@
 				so_rcv->sb_rptr = so_rcv->sb_data;
 				so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
 			}
-			m_free(m);
+			m_free(s, m);
 			return 0;
 		}
 
@@ -841,8 +800,8 @@
 				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_faddr.s_addr == s->loopback_addr.s_addr)
+                  ns->so_faddr = s->alias_addr;
 
 				ns->so_iptos = tcp_tos(ns);
 				tp = sototcpcb(ns);
@@ -857,12 +816,12 @@
 
                 /*soisfconnecting(ns);*/
 
-				tcpstat.tcps_connattempt++;
+				s->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;
+				tp->iss = s->tcp_iss;
+				s->tcp_iss += TCP_ISSINCR / 2;
 				tcp_sendseqinit(tp);
 				tcp_output(tp);
 				so->extra=ns;
@@ -931,11 +890,13 @@
 			 * 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 (s->do_echo == -1) {
+				if (m->m_len == 1)
+                                    s->do_echo = 1;
+				else
+                                    s->do_echo = 0;
 			}
-			if (do_echo) {
+			if (s->do_echo) {
 			  sbappendsb(so_snd, m);
 			  m_free(m);
 			  tcp_output(sototcpcb(so)); /* XXX */
@@ -991,7 +952,7 @@
 			/*
 			 * Need to emulate the PORT command
 			 */
-			x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]",
+			x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
 				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
 			if (x < 6)
 			   return 1;
@@ -999,7 +960,7 @@
 			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 = solisten(s, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 			   return 1;
 
 			n6 = ntohs(so->so_fport);
@@ -1022,7 +983,7 @@
 			/*
 			 * Need to emulate the PASV response
 			 */
-			x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]",
+			x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
 				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
 			if (x < 6)
 			   return 1;
@@ -1030,7 +991,7 @@
 			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 = solisten(s, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 			   return 1;
 
 			n6 = ntohs(so->so_fport);
@@ -1069,7 +1030,7 @@
 			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 = solisten(s, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
 			m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
 		return 1;
 
@@ -1083,7 +1044,7 @@
 
 		/* 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 = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1091,7 +1052,7 @@
 			     (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 = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1099,7 +1060,7 @@
 			      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 = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
+			if ((so = solisten(s, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 				return 1;
 
 			m->m_len = bptr - m->m_data; /* Adjust length */
@@ -1109,6 +1070,11 @@
 		}
 		return 1;
 
+#if 1
+//def VBOX
+         /** @todo Disabled EMU_REALAUDIO, because it uses a static variable.
+          * This is not legal when more than one slirp instance is active. */
+#else /* !VBOX */
 	 case EMU_REALAUDIO:
                 /*
 		 * RealAudio emulation - JP. We must try to parse the incoming
@@ -1234,6 +1200,7 @@
 			ra++;
 		}
 		return 1;
+#endif /* !VBOX */
 
 	 default:
 		/* Ooops, not emulated, won't call tcp_emu again */
@@ -1248,8 +1215,7 @@
  * return 2 if this is a command-line connection
  */
 int
-tcp_ctl(so)
-	struct socket *so;
+tcp_ctl(slirp_state_t *s, struct socket *so)
 {
 	struct sbuf *sb = &so->so_snd;
 	int command;
@@ -1278,7 +1244,7 @@
 		/*
 		 * Check if it's pty_exec
 		 */
-		for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+		for (ex_ptr = s->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
 			if (ex_ptr->ex_fport == so->so_fport &&
 			    command == ex_ptr->ex_addr) {
 				do_pty = ex_ptr->ex_pty;
@@ -1300,11 +1266,11 @@
 
 	do_exec:
 		DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
-		return(fork_exec(so, ex_ptr->ex_exec, do_pty));
+		return(fork_exec(s, so, ex_ptr->ex_exec, do_pty));
 
 #if 0
 	case CTL_CMD:
-	   for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
+	   for (tmpso = s->tcb.so_next; tmpso != &s->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))
@@ -1319,7 +1285,7 @@
 	   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;
+	   s->do_echo = -1;
 	   return(2);
 #endif
 	}
Index: qemu/slirp/tcp_timer.c
===================================================================
--- qemu.orig/slirp/tcp_timer.c	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tcp_timer.c	2007-10-20 13:50:20.000000000 +0000
@@ -36,34 +36,29 @@
 
 #include <slirp.h>
 
-int	tcp_keepidle = TCPTV_KEEP_IDLE;
-int	tcp_keepintvl = TCPTV_KEEPINTVL;
-int	tcp_maxidle;
-int	so_options = DO_KEEPALIVE;
-
-struct   tcpstat tcpstat;        /* tcp statistics */
-u_int32_t        tcp_now;                /* for RFC 1323 timestamps */
+static struct tcpcb *tcp_timers(slirp_state_t *s, register struct tcpcb *tp,
+                                int timer);
 
 /*
  * Fast timeout routine for processing delayed acks
  */
 void
-tcp_fasttimo()
+tcp_fasttimo(slirp_state_t *s)
 {
 	register struct socket *so;
 	register struct tcpcb *tp;
 
 	DEBUG_CALL("tcp_fasttimo");
 
-	so = tcb.so_next;
+	so = s->tcb.so_next;
 	if (so)
-	for (; so != &tcb; so = so->so_next)
+	for (; so != &s->tcb; so = so->so_next)
 		if ((tp = (struct tcpcb *)so->so_tcpcb) &&
 		    (tp->t_flags & TF_DELACK)) {
 			tp->t_flags &= ~TF_DELACK;
 			tp->t_flags |= TF_ACKNOW;
-			tcpstat.tcps_delack++;
-			(void) tcp_output(tp);
+			s->tcpstat.tcps_delack++;
+			(void) tcp_output(s, tp);
 		}
 }
 
@@ -73,7 +68,7 @@
  * causes finite state machine actions if timers expire.
  */
 void
-tcp_slowtimo()
+tcp_slowtimo(slirp_state_t *s)
 {
 	register struct socket *ip, *ipnxt;
 	register struct tcpcb *tp;
@@ -81,21 +76,20 @@
 
 	DEBUG_CALL("tcp_slowtimo");
 
-	tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
 	/*
 	 * Search through tcb's and update active timers.
 	 */
-	ip = tcb.so_next;
+	ip = s->tcb.so_next;
 	if (ip == 0)
 	   return;
-	for (; ip != &tcb; ip = ipnxt) {
+	for (; ip != &s->tcb; ip = ipnxt) {
 		ipnxt = ip->so_next;
 		tp = sototcpcb(ip);
 		if (tp == 0)
 			continue;
 		for (i = 0; i < TCPT_NTIMERS; i++) {
 			if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
-				tcp_timers(tp,i);
+				tcp_timers(s, tp,i);
 				if (ipnxt->so_prev != ip)
 					goto tpgone;
 			}
@@ -106,20 +100,19 @@
 tpgone:
 		;
 	}
-	tcp_iss += TCP_ISSINCR/PR_SLOWHZ;		/* increment iss */
+	s->tcp_iss += TCP_ISSINCR / PR_SLOWHZ;		/* increment iss */
 #ifdef TCP_COMPAT_42
-	if ((int)tcp_iss < 0)
-		tcp_iss = 0;				/* XXX */
+	if ((int)s->tcp_iss < 0)
+		s->tcp_iss = 0;				/* XXX */
 #endif
-	tcp_now++;					/* for timestamps */
+	s->tcp_now++;					/* for timestamps */
 }
 
 /*
  * Cancel all timers for TCP tp.
  */
 void
-tcp_canceltimers(tp)
-	struct tcpcb *tp;
+tcp_canceltimers(struct tcpcb *tp)
 {
 	register int i;
 
@@ -127,16 +120,14 @@
 		tp->t_timer[i] = 0;
 }
 
-int	tcp_backoff[TCP_MAXRXTSHIFT + 1] =
+const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
    { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
 
 /*
  * TCP timer processing.
  */
-struct tcpcb *
-tcp_timers(tp, timer)
-	register struct tcpcb *tp;
-	int timer;
+static struct tcpcb *
+tcp_timers(slirp_state_t *s, register struct tcpcb *tp, int timer)
 {
 	register int rexmt;
 
@@ -152,10 +143,10 @@
 	 */
 	case TCPT_2MSL:
 		if (tp->t_state != TCPS_TIME_WAIT &&
-		    tp->t_idle <= tcp_maxidle)
-			tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
+		    tp->t_idle <= TCP_MAXIDLE)
+			tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
 		else
-			tp = tcp_close(tp);
+			tp = tcp_close(s, tp);
 		break;
 
 	/*
@@ -192,8 +183,8 @@
 				 * We tried our best, now the connection must die!
 				 */
 				tp->t_rxtshift = TCP_MAXRXTSHIFT;
-				tcpstat.tcps_timeoutdrop++;
-				tp = tcp_drop(tp, tp->t_softerror);
+				s->tcpstat.tcps_timeoutdrop++;
+				tp = tcp_drop(s, tp, tp->t_softerror);
 				/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
 				return (tp); /* XXX */
 			}
@@ -204,7 +195,7 @@
 			 */
 			tp->t_rxtshift = 6;
 		}
-		tcpstat.tcps_rexmttimeo++;
+		s->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 */
@@ -259,7 +250,7 @@
 		tp->snd_ssthresh = win * tp->t_maxseg;
 		tp->t_dupacks = 0;
 		}
-		(void) tcp_output(tp);
+		(void) tcp_output(s, tp);
 		break;
 
 	/*
@@ -267,10 +258,10 @@
 	 * Force a byte to be output, if possible.
 	 */
 	case TCPT_PERSIST:
-		tcpstat.tcps_persisttimeo++;
+		s->tcpstat.tcps_persisttimeo++;
 		tcp_setpersist(tp);
 		tp->t_force = 1;
-		(void) tcp_output(tp);
+		(void) tcp_output(s, tp);
 		tp->t_force = 0;
 		break;
 
@@ -279,13 +270,13 @@
 	 * or drop connection if idle for too long.
 	 */
 	case TCPT_KEEP:
-		tcpstat.tcps_keeptimeo++;
+		s->tcpstat.tcps_keeptimeo++;
 		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 >= tcp_keepidle + tcp_maxidle)
+		if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
+		    	if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
 				goto dropit;
 			/*
 			 * Send a packet designed to force a response
@@ -299,7 +290,7 @@
 			 * by the protocol spec, this requires the
 			 * correspondent TCP to respond.
 			 */
-			tcpstat.tcps_keepprobe++;
+			s->tcpstat.tcps_keepprobe++;
 #ifdef TCP_COMPAT_42
 			/*
 			 * The keepalive packet must have nonzero length
@@ -308,17 +299,17 @@
 			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,
+			tcp_respond(s, tp, &tp->t_template, (struct mbuf *)NULL,
 			    tp->rcv_nxt, tp->snd_una - 1, 0);
 #endif
-			tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+			tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 		} else
-			tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+			tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
 		break;
 
 	dropit:
-		tcpstat.tcps_keepdrops++;
-		tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
+		s->tcpstat.tcps_keepdrops++;
+		tp = tcp_drop(s, tp, 0); /* ETIMEDOUT); */
 		break;
 	}
 
Index: qemu/slirp/tcp_timer.h
===================================================================
--- qemu.orig/slirp/tcp_timer.h	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tcp_timer.h	2007-10-20 14:56:41.000000000 +0000
@@ -108,6 +108,9 @@
 #define	TCP_LINGERTIME	120			/* linger at most 2 minutes */
 
 #define TCP_MAXRXTSHIFT 12                      /* maximum retransmits */
+/** Maximum idle time before timing out a connection. */
+#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
+
 
 
 #ifdef	TCPTIMERS
@@ -126,17 +129,12 @@
 		(tv) = (tvmax); \
 }
 
-extern int tcp_keepidle;		/* time before keepalive probes begin */
-extern int tcp_keepintvl;		/* time between keepalive probes */
-extern int tcp_maxidle;			/* time to drop after starting probes */
-extern int tcp_ttl;			/* time to live for TCP segs */
-extern int tcp_backoff[];
+extern const int tcp_backoff[];
 
 struct tcpcb;
 
-void tcp_fasttimo _P((void));
-void tcp_slowtimo _P((void));
+void tcp_fasttimo(slirp_state_t *s);
+void tcp_slowtimo(slirp_state_t *s);
 void tcp_canceltimers _P((struct tcpcb *));
-struct tcpcb * tcp_timers _P((register struct tcpcb *, int));
 
 #endif
Index: qemu/slirp/tcp_var.h
===================================================================
--- qemu.orig/slirp/tcp_var.h	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tcp_var.h	2007-10-20 17:10:54.000000000 +0000
@@ -45,7 +45,6 @@
 #else
  typedef u_int32_t tcpiphdrp_32;
 #endif
-
 /*
  * Tcp control block, one per tcp; fields:
  */
@@ -183,7 +182,10 @@
 #else
 typedef u_int32_t mbufp_32;
 #endif
-#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
+/* VBox change which is too much bother to #ifdef */
+# define REASS_MBUF_SET(ti, p) (*(mbufp_32 *)&((ti)->ti_t)) = (p)
+# define REASS_MBUF_GET(ti)    ((struct mbuf *)(*(mbufp_32 *)&((ti)->ti_t)))
+/*#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) - replaced by REASS_MBUF_GET/SET */
 
 /*
  * TCP statistics.
@@ -246,7 +248,5 @@
 	u_long	tcps_didnuttin;		/* Times tcp_output didn't do anything XXX */
 };
 
-extern struct	tcpstat tcpstat;	/* tcp statistics */
-extern u_int32_t	tcp_now;		/* for RFC 1323 timestamps */
 
 #endif
Index: qemu/slirp/tftp.c
===================================================================
--- qemu.orig/slirp/tftp.c	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tftp.c	2007-10-20 09:55:19.000000000 +0000
@@ -24,23 +24,10 @@
 
 #include <slirp.h>
 
-struct tftp_session {
-    int in_use;
-    unsigned char filename[TFTP_FILENAME_MAX];
 
-    struct in_addr client_ip;
-    u_int16_t client_port;
-
-    int timestamp;
-};
-
-struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
-
-const char *tftp_prefix;
-
-static void tftp_session_update(struct tftp_session *spt)
+static void tftp_session_update(slirp_state_t *s, struct tftp_session *spt)
 {
-    spt->timestamp = curtime;
+    spt->timestamp = s->curtime;
     spt->in_use = 1;
 }
 
@@ -49,19 +36,19 @@
   spt->in_use = 0;
 }
 
-static int tftp_session_allocate(struct tftp_t *tp)
+static int tftp_session_allocate(slirp_state_t *s, struct tftp_t *tp)
 {
   struct tftp_session *spt;
   int k;
 
   for (k = 0; k < TFTP_SESSIONS_MAX; k++) {
-    spt = &tftp_sessions[k];
+    spt = &s->tftp_sessions[k];
 
     if (!spt->in_use)
         goto found;
 
     /* sessions time out after 5 inactive seconds */
-    if ((int)(curtime - spt->timestamp) > 5000)
+    if ((int)(s->curtime - spt->timestamp) > 5000)
         goto found;
   }
 
@@ -72,18 +59,18 @@
   memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));
   spt->client_port = tp->udp.uh_sport;
 
-  tftp_session_update(spt);
+  tftp_session_update(s, spt);
 
   return k;
 }
 
-static int tftp_session_find(struct tftp_t *tp)
+static int tftp_session_find(slirp_state_t *s, struct tftp_t *tp)
 {
   struct tftp_session *spt;
   int k;
 
   for (k = 0; k < TFTP_SESSIONS_MAX; k++) {
-    spt = &tftp_sessions[k];
+    spt = &s->tftp_sessions[k];
 
     if (spt->in_use) {
       if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
@@ -97,7 +84,7 @@
   return -1;
 }
 
-static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
+static int tftp_read_data(slirp_state_t *s, struct tftp_session *spt, u_int16_t block_nr,
 			  u_int8_t *buf, int len)
 {
   int fd;
@@ -106,7 +93,7 @@
   int n;
 
   n = snprintf(buffer, sizeof(buffer), "%s/%s",
-	       tftp_prefix, spt->filename);
+	       s->tftp_prefix, spt->filename);
   if (n >= sizeof(buffer))
     return -1;
 
@@ -127,7 +114,8 @@
   return bytes_read;
 }
 
-static int tftp_send_oack(struct tftp_session *spt,
+static int tftp_send_oack(slirp_state_t *s,
+                          struct tftp_session *spt,
                           const char *key, uint32_t value,
                           struct tftp_t *recv_tp)
 {
@@ -136,14 +124,14 @@
     struct tftp_t *tp;
     int n = 0;
 
-    m = m_get();
+    m = m_get(s);
 
     if (!m)
 	return -1;
 
     memset(m->m_data, 0, m->m_size);
 
-    m->m_data += if_maxlinkhdr;
+    m->m_data += s->if_maxlinkhdr;
     tp = (void *)m->m_data;
     m->m_data += sizeof(struct udpiphdr);
 
@@ -159,14 +147,15 @@
 
     m->m_len = sizeof(struct tftp_t) - 514 + n -
         sizeof(struct ip) - sizeof(struct udphdr);
-    udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+    udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 
     return 0;
 }
 
 
 
-static int tftp_send_error(struct tftp_session *spt,
+static int tftp_send_error(slirp_state_t *s,
+                           struct tftp_session *spt,
 			   u_int16_t errorcode, const char *msg,
 			   struct tftp_t *recv_tp)
 {
@@ -175,7 +164,7 @@
   struct tftp_t *tp;
   int nobytes;
 
-  m = m_get();
+  m = m_get(s);
 
   if (!m) {
     return -1;
@@ -183,7 +172,7 @@
 
   memset(m->m_data, 0, m->m_size);
 
-  m->m_data += if_maxlinkhdr;
+  m->m_data += s->if_maxlinkhdr;
   tp = (void *)m->m_data;
   m->m_data += sizeof(struct udpiphdr);
 
@@ -202,14 +191,15 @@
   m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
         sizeof(struct ip) - sizeof(struct udphdr);
 
-  udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+  udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 
   tftp_session_terminate(spt);
 
   return 0;
 }
 
-static int tftp_send_data(struct tftp_session *spt,
+static int tftp_send_data(slirp_state_t *s,
+                          struct tftp_session *spt,
 			  u_int16_t block_nr,
 			  struct tftp_t *recv_tp)
 {
@@ -222,7 +212,7 @@
     return -1;
   }
 
-  m = m_get();
+  m = m_get(s);
 
   if (!m) {
     return -1;
@@ -230,7 +220,7 @@
 
   memset(m->m_data, 0, m->m_size);
 
-  m->m_data += if_maxlinkhdr;
+  m->m_data += s->if_maxlinkhdr;
   tp = (void *)m->m_data;
   m->m_data += sizeof(struct udpiphdr);
 
@@ -243,14 +233,14 @@
   daddr.sin_addr = spt->client_ip;
   daddr.sin_port = spt->client_port;
 
-  nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512);
+  nobytes = tftp_read_data(s, spt, block_nr - 1, tp->x.tp_data.tp_buf, 512);
 
   if (nobytes < 0) {
-    m_free(m);
+    m_free(s, m);
 
     /* send "file not found" error back */
 
-    tftp_send_error(spt, 1, "File not found", tp);
+    tftp_send_error(s, spt, 1, "File not found", tp);
 
     return -1;
   }
@@ -258,10 +248,10 @@
   m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
         sizeof(struct ip) - sizeof(struct udphdr);
 
-  udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+  udp_output2(s, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
 
   if (nobytes == 512) {
-    tftp_session_update(spt);
+    tftp_session_update(s, spt);
   }
   else {
     tftp_session_terminate(spt);
@@ -270,19 +260,19 @@
   return 0;
 }
 
-static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
+static void tftp_handle_rrq(slirp_state_t *s, struct tftp_t *tp, int pktlen)
 {
   struct tftp_session *spt;
-  int s, k, n;
+  int session, k, n;
   u_int8_t *src, *dst;
 
-  s = tftp_session_allocate(tp);
+  session = tftp_session_allocate(s, tp);
 
-  if (s < 0) {
+  if (session < 0) {
     return;
   }
 
-  spt = &tftp_sessions[s];
+  spt = &s->tftp_sessions[session];
 
   src = tp->x.tp_buf;
   dst = spt->filename;
@@ -315,7 +305,7 @@
   }
 
   if (memcmp(&src[k], "octet\0", 6) != 0) {
-      tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
+      tftp_send_error(s, spt, 4, "Unsupported transfer mode", tp);
       return;
   }
 
@@ -326,26 +316,26 @@
   if ((spt->filename[0] != '/')
       || (spt->filename[strlen(spt->filename) - 1] == '/')
       ||  strstr(spt->filename, "/../")) {
-      tftp_send_error(spt, 2, "Access violation", tp);
+      tftp_send_error(s, spt, 2, "Access violation", tp);
       return;
   }
 
   /* only allow exported prefixes */
 
-  if (!tftp_prefix) {
-      tftp_send_error(spt, 2, "Access violation", tp);
+  if (!s->tftp_prefix) {
+      tftp_send_error(s, spt, 2, "Access violation", tp);
       return;
   }
 
   /* check if the file exists */
 
-  if (tftp_read_data(spt, 0, spt->filename, 0) < 0) {
-      tftp_send_error(spt, 1, "File not found", tp);
+  if (tftp_read_data(s, spt, 0, spt->filename, 0) < 0) {
+      tftp_send_error(s, spt, 1, "File not found", tp);
       return;
   }
 
   if (src[n - 1] != 0) {
-      tftp_send_error(spt, 2, "Access violation", tp);
+      tftp_send_error(s, spt, 2, "Access violation", tp);
       return;
   }
 
@@ -356,7 +346,7 @@
       k += strlen(key) + 1;
 
       if (k >= n) {
-	  tftp_send_error(spt, 2, "Access violation", tp);
+	  tftp_send_error(s, spt, 2, "Access violation", tp);
 	  return;
       }
 
@@ -367,56 +357,56 @@
 	  int tsize = atoi(value);
 	  struct stat stat_p;
 
-	  if (tsize == 0 && tftp_prefix) {
+	  if (tsize == 0 && s->tftp_prefix) {
 	      char buffer[1024];
 	      int len;
 
 	      len = snprintf(buffer, sizeof(buffer), "%s/%s",
-			     tftp_prefix, spt->filename);
+			     s->tftp_prefix, spt->filename);
 
 	      if (stat(buffer, &stat_p) == 0)
 		  tsize = stat_p.st_size;
 	      else {
-		  tftp_send_error(spt, 1, "File not found", tp);
+		  tftp_send_error(s, spt, 1, "File not found", tp);
 		  return;
 	      }
 	  }
 
-	  tftp_send_oack(spt, "tsize", tsize, tp);
+	  tftp_send_oack(s, spt, "tsize", tsize, tp);
       }
   }
 
-  tftp_send_data(spt, 1, tp);
+  tftp_send_data(s, spt, 1, tp);
 }
 
-static void tftp_handle_ack(struct tftp_t *tp, int pktlen)
+static void tftp_handle_ack(slirp_state_t *s, struct tftp_t *tp, int pktlen)
 {
-  int s;
+  int session;
 
-  s = tftp_session_find(tp);
+  session = tftp_session_find(s, tp);
 
-  if (s < 0) {
+  if (session < 0) {
     return;
   }
 
-  if (tftp_send_data(&tftp_sessions[s],
+  if (tftp_send_data(s, &s->tftp_sessions[session],
 		     ntohs(tp->x.tp_data.tp_block_nr) + 1,
 		     tp) < 0) {
     return;
   }
 }
 
-void tftp_input(struct mbuf *m)
+void tftp_input(slirp_state_t *s, struct mbuf *m)
 {
   struct tftp_t *tp = (struct tftp_t *)m->m_data;
 
   switch(ntohs(tp->tp_op)) {
   case TFTP_RRQ:
-    tftp_handle_rrq(tp, m->m_len);
+    tftp_handle_rrq(s, tp, m->m_len);
     break;
 
   case TFTP_ACK:
-    tftp_handle_ack(tp, m->m_len);
+    tftp_handle_ack(s, tp, m->m_len);
     break;
   }
 }
Index: qemu/slirp/tftp.h
===================================================================
--- qemu.orig/slirp/tftp.h	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/tftp.h	2007-10-20 08:17:52.000000000 +0000
@@ -30,4 +30,4 @@
   } x;
 };
 
-void tftp_input(struct mbuf *m);
+void tftp_input(slirp_state_t *s, struct mbuf *m);
Index: qemu/slirp/udp.c
===================================================================
--- qemu.orig/slirp/udp.c	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/udp.c	2007-10-20 17:13:45.000000000 +0000
@@ -45,35 +45,28 @@
 #include <slirp.h>
 #include "ip_icmp.h"
 
-struct udpstat udpstat;
-
-struct socket udb;
+static u_int8_t udp_tos(struct socket *so);
+static void udp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m);
 
 /*
  * UDP protocol implementation.
  * Per RFC 768, August, 1980.
  */
-#ifndef	COMPAT_42
-int	udpcksum = 1;
-#else
-int	udpcksum = 0;		/* XXX */
-#endif
-
-struct	socket *udp_last_so = &udb;
+#define udpcksum 1
 
 void
-udp_init()
+udp_init(slirp_state_t *s)
 {
-	udb.so_next = udb.so_prev = &udb;
+        s->udp_last_so = &s->udb;
+	s->udb.so_next = s->udb.so_prev = &s->udb;
 }
+
 /* m->m_data  points at ip packet header
  * m->m_len   length ip packet
  * ip->ip_len length data (IPDU)
  */
 void
-udp_input(m, iphlen)
-	register struct mbuf *m;
-	int iphlen;
+udp_input(slirp_state_t *s, register struct mbuf *m, int iphlen)
 {
 	register struct ip *ip;
 	register struct udphdr *uh;
@@ -86,7 +79,7 @@
 	DEBUG_ARG("m = %lx", (long)m);
 	DEBUG_ARG("iphlen = %d", iphlen);
 
-	udpstat.udps_ipackets++;
+	s->udpstat.udps_ipackets++;
 
 	/*
 	 * Strip IP options, if any; should skip this,
@@ -113,7 +106,7 @@
 
 	if (ip->ip_len != len) {
 		if (len > ip->ip_len) {
-			udpstat.udps_badlen++;
+			s->udpstat.udps_badlen++;
 			goto bad;
 		}
 		m_adj(m, len - ip->ip_len);
@@ -140,7 +133,7 @@
 	   * if (uh->uh_sum) {
 	   */
 	  if(cksum(m, len + sizeof(struct ip))) {
-	    udpstat.udps_badsum++;
+	    s->udpstat.udps_badsum++;
 	    goto bad;
 	  }
 	}
@@ -149,7 +142,7 @@
          *  handle DHCP/BOOTP
          */
         if (ntohs(uh->uh_dport) == BOOTP_SERVER) {
-            bootp_input(m);
+            bootp_input(s, m);
             goto bad;
         }
 
@@ -157,19 +150,19 @@
          *  handle TFTP
          */
         if (ntohs(uh->uh_dport) == TFTP_SERVER) {
-            tftp_input(m);
+            tftp_input(s, m);
             goto bad;
         }
 
 	/*
 	 * Locate pcb for datagram.
 	 */
-	so = udp_last_so;
+	so = s->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 = s->udb.so_next; tmp != &s->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;
@@ -178,11 +171,11 @@
 				break;
 			}
 		}
-		if (tmp == &udb) {
+		if (tmp == &s->udb) {
 		  so = NULL;
 		} else {
-		  udpstat.udpps_pcbcachemiss++;
-		  udp_last_so = so;
+		  s->udpstat.udpps_pcbcachemiss++;
+		  s->udp_last_so = so;
 		}
 	}
 
@@ -192,10 +185,10 @@
 	   * create one
 	   */
 	  if ((so = socreate()) == NULL) goto bad;
-	  if(udp_attach(so) == -1) {
+	  if(udp_attach(s, so) == -1) {
 	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
 			errno,strerror(errno)));
-	    sofree(so);
+            sofree(s, so);
 	    goto bad;
 	  }
 
@@ -226,17 +219,17 @@
 	 * Now we sendto() the packet.
 	 */
 	if (so->so_emu)
-	   udp_emu(so, m);
+	   udp_emu(s, so, m);
 
-	if(sosendto(so,m) == -1) {
+	if(sosendto(s, so,m) == -1) {
 	  m->m_len += iphlen;
 	  m->m_data -= iphlen;
 	  *ip=save_ip;
 	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
-	  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
+	  icmp_error(s, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
 	}
 
-	m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */
+	m_free(s, so->so_m);   /* used for ICMP if error on sorecvfrom */
 
 	/* restore the orig mbuf packet */
 	m->m_len += iphlen;
@@ -246,12 +239,12 @@
 
 	return;
 bad:
-	m_freem(m);
+	m_freem(s, m);
 	/* if (opts) m_freem(opts); */
 	return;
 }
 
-int udp_output2(struct socket *so, struct mbuf *m,
+int udp_output2(slirp_state_t *s, struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos)
 {
@@ -296,37 +289,35 @@
 	}
 	((struct ip *)ui)->ip_len = m->m_len;
 
-	((struct ip *)ui)->ip_ttl = ip_defttl;
+	((struct ip *)ui)->ip_ttl = IPDEFTTL;
 	((struct ip *)ui)->ip_tos = iptos;
 
-	udpstat.udps_opackets++;
+	s->udpstat.udps_opackets++;
 
-	error = ip_output(so, m);
+	error = ip_output(s, so, m);
 
 	return (error);
 }
 
-int udp_output(struct socket *so, struct mbuf *m,
+int udp_output(slirp_state_t *s, struct socket *so, struct mbuf *m,
                struct sockaddr_in *addr)
-
 {
     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(0xffffff00)) == s->special_addr.s_addr) {
         saddr.sin_addr.s_addr = so->so_faddr.s_addr;
         if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))
-            saddr.sin_addr.s_addr = alias_addr.s_addr;
+            saddr.sin_addr.s_addr = s->alias_addr.s_addr;
     }
     daddr.sin_addr = so->so_laddr;
     daddr.sin_port = so->so_lport;
 
-    return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
+    return udp_output2(s, so, m, &saddr, &daddr, so->so_iptos);
 }
 
 int
-udp_attach(so)
-     struct socket *so;
+udp_attach(slirp_state_t *s, struct socket *so)
 {
   struct sockaddr_in addr;
 
@@ -349,25 +340,30 @@
       errno=lasterrno;
 #endif
     } else {
+      int opt = 1;
       /* success, insert in queue */
-      so->so_expire = curtime + SO_EXPIRE;
-      insque(so,&udb);
+      so->so_expire = s->curtime + SO_EXPIRE;
+      /* enable broadcast for later use */
+      setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
+      insque(s, so, &s->udb);
     }
   }
   return(so->s);
 }
 
 void
-udp_detach(so)
-	struct socket *so;
+udp_detach(slirp_state_t *s, struct socket *so)
 {
+	/* Correctly update list if detaching last socket in list. */
+	if (so == s->udp_last_so)
+            s->udp_last_so = &s->udb;
 	closesocket(so->s);
 	/* if (so->so_m) m_free(so->so_m);    done by sofree */
 
-	sofree(so);
+	sofree(s, so);
 }
 
-struct tos_t udptos[] = {
+static const struct tos_t udptos[] = {
 	{0, 53, IPTOS_LOWDELAY, 0},			/* DNS */
 	{517, 517, IPTOS_LOWDELAY, EMU_TALK},	/* talk */
 	{518, 518, IPTOS_LOWDELAY, EMU_NTALK},	/* ntalk */
@@ -375,9 +371,8 @@
 	{0, 0, 0, 0}
 };
 
-u_int8_t
-udp_tos(so)
-	struct socket *so;
+static u_int8_t
+udp_tos(struct socket *so)
 {
 	int i = 0;
 
@@ -400,10 +395,8 @@
 /*
  * Here, talk/ytalk/ntalk requests must be emulated
  */
-void
-udp_emu(so, m)
-	struct socket *so;
-	struct mbuf *m;
+static void
+udp_emu(slirp_state_t *s, struct socket *so, struct mbuf *m)
 {
 	struct sockaddr_in addr;
         int addrlen = sizeof(addr);
@@ -470,14 +463,14 @@
 			nmsg = (CTL_MSG *) buff;
 			type = omsg->type;
 			OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
-			OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
+			OTOSIN(omsg, ctl_addr)->sin_addr = s->our_addr;
 			strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
 		} else {		/* new talk */
 			omsg = (CTL_MSG_OLD *) buff;
 			nmsg = mtod(m, CTL_MSG *);
 			type = nmsg->type;
 			OTOSIN(nmsg, ctl_addr)->sin_port = addr.sin_port;
-			OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
+			OTOSIN(nmsg, ctl_addr)->sin_addr = s->our_addr;
 			strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
 		}
 
@@ -530,9 +523,9 @@
 					(struct sockaddr *) &addr,
 					&addrlen);
 			OTOSIN(omsg, addr)->sin_port = addr.sin_port;
-			OTOSIN(omsg, addr)->sin_addr = our_addr;
+			OTOSIN(omsg, addr)->sin_addr = s->our_addr;
 			OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
-			OTOSIN(nmsg, addr)->sin_addr = our_addr;
+			OTOSIN(nmsg, addr)->sin_addr = s->our_addr;
 
 			/* send LEAVE_INVITEs */
 			temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
@@ -541,7 +534,7 @@
 			omsg->type = nmsg->type = LEAVE_INVITE;
 
 			s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
-			addr.sin_addr = our_addr;
+			addr.sin_addr = s->our_addr;
 			addr.sin_family = AF_INET;
 			addr.sin_port = htons(517);
 			sendto(s, (char *)omsg, sizeof(*omsg), 0,
@@ -572,7 +565,7 @@
 			OTOSIN(nmsg, ctl_addr)->sin_port = 0;
 
 			s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
-			addr.sin_addr = our_addr;
+			addr.sin_addr = s->our_addr;
 			addr.sin_family = AF_INET;
 			addr.sin_port = htons(517);
 			sendto(s, (char *)omsg, sizeof(*omsg), 0,
@@ -621,7 +614,7 @@
 				return;
 			cu_head = mtod(m, struct cu_header *);
 			cu_head->s_port = addr.sin_port;
-			cu_head->so_addr = our_addr.s_addr;
+			cu_head->so_addr = s->our_addr.s_addr;
 		}
 
 		return;
@@ -629,11 +622,8 @@
 }
 
 struct socket *
-udp_listen(port, laddr, lport, flags)
-	u_int port;
-	u_int32_t laddr;
-	u_int lport;
-	int flags;
+udp_listen(slirp_state_t *s, u_int port, u_int32_t laddr, u_int lport,
+           int flags)
 {
 	struct sockaddr_in addr;
 	struct socket *so;
@@ -644,15 +634,15 @@
 		return NULL;
 	}
 	so->s = socket(AF_INET,SOCK_DGRAM,0);
-	so->so_expire = curtime + SO_EXPIRE;
-	insque(so,&udb);
+	so->so_expire = s->curtime + SO_EXPIRE;
+	insque(s, so, &s->udb);
 
 	addr.sin_family = AF_INET;
 	addr.sin_addr.s_addr = INADDR_ANY;
 	addr.sin_port = port;
 
 	if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
-		udp_detach(so);
+		udp_detach(s, so);
 		return NULL;
 	}
 	setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
@@ -660,8 +650,8 @@
 
 	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;
+	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == s->loopback_addr.s_addr)
+	   so->so_faddr = s->alias_addr;
 	else
 	   so->so_faddr = addr.sin_addr;
 
Index: qemu/slirp/udp.h
===================================================================
--- qemu.orig/slirp/udp.h	2007-10-20 07:33:38.000000000 +0000
+++ qemu/slirp/udp.h	2007-10-20 17:20:01.000000000 +0000
@@ -40,8 +40,6 @@
 #define UDP_TTL 0x60
 #define UDP_UDPDATALEN 16192
 
-extern struct socket *udp_last_so;
-
 /*
  * Udp protocol header.
  * Per RFC 768, September, 1981.
@@ -92,19 +90,17 @@
 #define UDPCTL_CHECKSUM         1       /* checksum UDP packets */
 #define UDPCTL_MAXID            2
 
-extern struct udpstat udpstat;
-extern struct socket udb;
 struct mbuf;
 
-void udp_init _P((void));
-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 *));
-u_int8_t udp_tos _P((struct socket *));
-void udp_emu _P((struct socket *, struct mbuf *));
-struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
-int udp_output2(struct socket *so, struct mbuf *m,
+void udp_init(slirp_state_t *s);
+void udp_input(slirp_state_t *s, register struct mbuf *m, int iphlen);
+int udp_output(slirp_state_t *s, struct socket *so, struct mbuf *m,
+               struct sockaddr_in *addr);
+int udp_attach(slirp_state_t *s, struct socket *so);
+void udp_detach(slirp_state_t *s, struct socket *so);
+struct socket *udp_listen(slirp_state_t *s, u_int port, u_int32_t laddr,
+                          u_int lport, int flags);
+int udp_output2(slirp_state_t *s, struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos);
 #endif
Index: qemu/slirp/debug.c
===================================================================
--- qemu.orig/slirp/debug.c	2007-10-20 07:33:39.000000000 +0000
+++ qemu/slirp/debug.c	2007-10-20 12:52:40.000000000 +0000
@@ -9,10 +9,12 @@
 #include <slirp.h>
 
 FILE *dfd = NULL;
+#if 0
 #ifdef DEBUG
-int dostats = 1;
+static int dostats = 1;
 #else
-int dostats = 0;
+static int dostats = 0;
+#endif
 #endif
 int slirp_debug = 0;
 
@@ -20,10 +22,10 @@
 
 /* Carry over one item from main.c so that the tty's restored.
  * Only done when the tty being used is /dev/tty --RedWolf */
+#if 0
 extern struct termios slirp_tty_settings;
 extern int slirp_tty_restore;
 
-
 void
 debug_init(file, dbg)
 	char *file;
@@ -70,7 +72,16 @@
 	}
 }
 #endif
+#endif
 
+#ifdef LOG_ENABLED
+//static void ttystats(struct ttys *);
+static void ipstats(slirp_state_t *s);
+static void tcpstats(slirp_state_t *s);
+static void udpstats(slirp_state_t *s);
+static void icmpstats(slirp_state_t *s);
+static void mbufstats(slirp_state_t *s);
+static void sockstats(slirp_state_t *s);
 #if 0
 /*
  * Statistic routines
@@ -80,7 +91,7 @@
  * the link as well.
  */
 
-void
+static void
 ttystats(ttyp)
 	struct ttys *ttyp;
 {
@@ -89,9 +100,9 @@
 
 	lprint(" \r\n");
 
-	if (if_comp & IF_COMPRESS)
+	if (s->if_comp & IF_COMPRESS)
 	   strcpy(buff, "on");
-	else if (if_comp & IF_NOCOMPRESS)
+	else if (s->if_comp & IF_NOCOMPRESS)
 	   strcpy(buff, "off");
 	else
 	   strcpy(buff, "off (for now)");
@@ -129,28 +140,28 @@
 }
 #endif
 
-void
-ipstats()
+static void
+ipstats(slirp_state_t *s)
 {
 	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);
+			s->ipstat.ips_total, s->ipstat.ips_unaligned);
+	lprint("  %6d with incorrect version\r\n", s->ipstat.ips_badvers);
+	lprint("  %6d with bad header checksum\r\n", s->ipstat.ips_badsum);
+	lprint("  %6d with length too short (len < sizeof(iphdr))\r\n", s->ipstat.ips_tooshort);
+	lprint("  %6d with length too small (len < ip->len)\r\n", s->ipstat.ips_toosmall);
+	lprint("  %6d with bad header length\r\n", s->ipstat.ips_badhlen);
+	lprint("  %6d with bad packet length\r\n", s->ipstat.ips_badlen);
+	lprint("  %6d fragments received\r\n", s->ipstat.ips_fragments);
+	lprint("  %6d fragments dropped\r\n", s->ipstat.ips_fragdropped);
+	lprint("  %6d fragments timed out\r\n", s->ipstat.ips_fragtimeout);
+	lprint("  %6d packets reassembled ok\r\n", s->ipstat.ips_reassembled);
+	lprint("  %6d outgoing packets fragmented\r\n", s->ipstat.ips_fragmented);
+	lprint("  %6d total outgoing fragments\r\n", s->ipstat.ips_ofragments);
+	lprint("  %6d with bad protocol field\r\n", s->ipstat.ips_noproto);
+	lprint("  %6d total packets delivered\r\n", s->ipstat.ips_delivered);
 }
 
 #if 0
@@ -172,67 +183,67 @@
 }
 #endif
 
-void
-tcpstats()
+static void
+tcpstats(slirp_state_t *s)
 {
 	lprint(" \r\n");
 
 	lprint("TCP stats:\r\n");
 
-	lprint("  %6d packets sent\r\n", tcpstat.tcps_sndtotal);
+	lprint("  %6d packets sent\r\n", s->tcpstat.tcps_sndtotal);
 	lprint("          %6d data packets (%d bytes)\r\n",
-			tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
+			s->tcpstat.tcps_sndpack, s->tcpstat.tcps_sndbyte);
 	lprint("          %6d data packets retransmitted (%d bytes)\r\n",
-			tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte);
+			s->tcpstat.tcps_sndrexmitpack, s->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);
+			s->tcpstat.tcps_sndacks, s->tcpstat.tcps_delack);
+	lprint("          %6d URG only packets\r\n", s->tcpstat.tcps_sndurg);
+	lprint("          %6d window probe packets\r\n", s->tcpstat.tcps_sndprobe);
+	lprint("          %6d window update packets\r\n", s->tcpstat.tcps_sndwinup);
+	lprint("          %6d control (SYN/FIN/RST) packets\r\n", s->tcpstat.tcps_sndctrl);
+	lprint("          %6d times tcp_output did nothing\r\n", s->tcpstat.tcps_didnuttin);
 
-	lprint("  %6d packets received\r\n", tcpstat.tcps_rcvtotal);
+	lprint("  %6d packets received\r\n", s->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);
+			s->tcpstat.tcps_rcvackpack, s->tcpstat.tcps_rcvackbyte);
+	lprint("          %6d duplicate acks\r\n", s->tcpstat.tcps_rcvdupack);
+	lprint("          %6d acks for unsent data\r\n", s->tcpstat.tcps_rcvacktoomuch);
 	lprint("          %6d packets received in sequence (%d bytes)\r\n",
-			tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
+			s->tcpstat.tcps_rcvpack, s->tcpstat.tcps_rcvbyte);
         lprint("          %6d completely duplicate packets (%d bytes)\r\n",
-			tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
+			s->tcpstat.tcps_rcvduppack, s->tcpstat.tcps_rcvdupbyte);
 
 	lprint("          %6d packets with some duplicate data (%d bytes duped)\r\n",
-			tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
+			s->tcpstat.tcps_rcvpartduppack, s->tcpstat.tcps_rcvpartdupbyte);
 	lprint("          %6d out-of-order packets (%d bytes)\r\n",
-			tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte);
+			s->tcpstat.tcps_rcvoopack, s->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);
+			s->tcpstat.tcps_rcvpackafterwin, s->tcpstat.tcps_rcvbyteafterwin);
+	lprint("          %6d window probes\r\n", s->tcpstat.tcps_rcvwinprobe);
+	lprint("          %6d window update packets\r\n", s->tcpstat.tcps_rcvwinupd);
+	lprint("          %6d packets received after close\r\n", s->tcpstat.tcps_rcvafterclose);
+	lprint("          %6d discarded for bad checksums\r\n", s->tcpstat.tcps_rcvbadsum);
 	lprint("          %6d discarded for bad header offset fields\r\n",
-			tcpstat.tcps_rcvbadoff);
+			s->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 connection requests\r\n", s->tcpstat.tcps_connattempt);
+	lprint("  %6d connection accepts\r\n", s->tcpstat.tcps_accepts);
+	lprint("  %6d connections established (including accepts)\r\n", s->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);
+			s->tcpstat.tcps_closed, s->tcpstat.tcps_drops);
+	lprint("  %6d embryonic connections dropped\r\n", s->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);
+			s->tcpstat.tcps_segstimed, s->tcpstat.tcps_rttupdated);
+	lprint("  %6d retransmit timeouts\r\n", s->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);
+			s->tcpstat.tcps_timeoutdrop);
+	lprint("  %6d persist timeouts\r\n", s->tcpstat.tcps_persisttimeo);
+	lprint("  %6d keepalive timeouts\r\n", s->tcpstat.tcps_keeptimeo);
+	lprint("          %6d keepalive probes sent\r\n", s->tcpstat.tcps_keepprobe);
+	lprint("          %6d connections dropped by keepalive\r\n", s->tcpstat.tcps_keepdrops);
+	lprint("  %6d correct ACK header predictions\r\n", s->tcpstat.tcps_predack);
+	lprint("  %6d correct data packet header predictions\n", s->tcpstat.tcps_preddat);
+	lprint("  %6d TCP cache misses\r\n", s->tcpstat.tcps_socachemiss);
 
 
 /*	lprint("    Packets received too short:		%d\r\n", tcpstat.tcps_rcvshort); */
@@ -240,35 +251,35 @@
 
 }
 
-void
-udpstats()
+static void
+udpstats(slirp_state_t *s)
 {
         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);
+	lprint("  %6d datagrams received\r\n", s->udpstat.udps_ipackets);
+	lprint("  %6d with packets shorter than header\r\n", s->udpstat.udps_hdrops);
+	lprint("  %6d with bad checksums\r\n", s->udpstat.udps_badsum);
+	lprint("  %6d with data length larger than packet\r\n", s->udpstat.udps_badlen);
+	lprint("  %6d UDP socket cache misses\r\n", s->udpstat.udpps_pcbcachemiss);
+	lprint("  %6d datagrams sent\r\n", s->udpstat.udps_opackets);
 }
 
-void
-icmpstats()
+static void
+icmpstats(slirp_state_t *s)
 {
 	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);
+	lprint("  %6d ICMP packets received\r\n", s->icmpstat.icps_received);
+	lprint("  %6d were too short\r\n", s->icmpstat.icps_tooshort);
+	lprint("  %6d with bad checksums\r\n", s->icmpstat.icps_checksum);
+	lprint("  %6d with type not supported\r\n", s->icmpstat.icps_notsupp);
+	lprint("  %6d with bad type feilds\r\n", s->icmpstat.icps_badtype);
+	lprint("  %6d ICMP packets sent in reply\r\n", s->icmpstat.icps_reflect);
 }
 
-void
-mbufstats()
+static void
+mbufstats(slirp_state_t *s)
 {
 	struct mbuf *m;
 	int i;
@@ -277,22 +288,22 @@
 
 	lprint("Mbuf stats:\r\n");
 
-	lprint("  %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
+	lprint("  %6d mbufs allocated (%d max)\r\n", s->mbuf_alloced, s->mbuf_max);
 
 	i = 0;
-	for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
+	for (m = s->m_freelist.m_next; m != &s->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)
+	for (m = s->m_usedlist.m_next; m != &s->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);
+        lprint("  %6d mbufs queued as packets\r\n\r\n", s->if_queued);
 }
 
-void
-sockstats()
+static void
+sockstats(slirp_state_t *s)
 {
 	char buff[256];
 	int n;
@@ -303,7 +314,7 @@
 	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) {
+	for (so = s->tcb.so_next; so != &s->tcb; so = so->so_next) {
 
 		n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
 		while (n < 17)
@@ -317,9 +328,9 @@
 				so->so_rcv.sb_cc, so->so_snd.sb_cc);
 	}
 
-	for (so = udb.so_next; so != &udb; so = so->so_next) {
+	for (so = s->udb.so_next; so != &s->udb; so = so->so_next) {
 
-		n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
+		n = sprintf(buff, "udp[%d sec]", (so->so_expire - s->curtime) / 1000);
 		while (n < 17)
 		   buff[n++] = ' ';
 		buff[17] = 0;
@@ -331,6 +342,7 @@
 				so->so_rcv.sb_cc, so->so_snd.sb_cc);
 	}
 }
+#endif
 
 #if 0
 void
@@ -374,3 +386,18 @@
 	exit(exit_status);
 }
 #endif
+
+void
+slirp_stats(slirp_state_t *s)
+{
+#ifdef LOG_ENABLED
+    ipstats(s);
+    tcpstats(s);
+    udpstats(s);
+    icmpstats(s);
+    mbufstats(s);
+    sockstats(s);
+#else
+    fprintf(stderr, "SLIRP statistics not compiled\n");
+#endif
+}
Index: qemu/slirp/debug.h
===================================================================
--- qemu.orig/slirp/debug.h	2007-10-20 07:33:39.000000000 +0000
+++ qemu/slirp/debug.h	2007-10-20 12:50:47.000000000 +0000
@@ -37,14 +37,4 @@
 #endif
 
 void debug_init _P((char *, int));
-//void ttystats _P((struct ttys *));
-void allttystats _P((void));
-void ipstats _P((void));
-void vjstats _P((void));
-void tcpstats _P((void));
-void udpstats _P((void));
-void icmpstats _P((void));
-void mbufstats _P((void));
-void sockstats _P((void));
-void slirp_exit _P((int));
 
Index: qemu/slirp/icmp_var.h
===================================================================
--- qemu.orig/slirp/icmp_var.h	2007-10-20 07:33:39.000000000 +0000
+++ qemu/slirp/icmp_var.h	2007-10-20 08:17:52.000000000 +0000
@@ -64,6 +64,4 @@
 	{ "stats", CTLTYPE_STRUCT }, \
 }
 
-extern struct icmpstat icmpstat;
-
 #endif
Index: qemu/slirp/if.h
===================================================================
--- qemu.orig/slirp/if.h	2007-10-20 07:33:39.000000000 +0000
+++ qemu/slirp/if.h	2007-10-20 08:17:52.000000000 +0000
@@ -13,20 +13,6 @@
 #define IF_AUTOCOMP	0x04	/* Autodetect (default) */
 #define IF_NOCIDCOMP	0x08	/* CID compression */
 
-/* Needed for FreeBSD */
-#undef if_mtu
-extern int	if_mtu;
-extern int	if_mru;	/* MTU and MRU */
-extern int	if_comp;	/* Flags for compression */
-extern int	if_maxlinkhdr;
-extern int	if_queued;	/* Number of packets queued so far */
-extern int	if_thresh;	/* Number of packets queued before we start sending
-				 * (to prevent allocing too many mbufs) */
-
-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))
 
 /* Interface statistics */
Index: qemu/vl.c
===================================================================
--- qemu.orig/vl.c	2007-10-20 07:33:39.000000000 +0000
+++ qemu/vl.c	2007-10-20 17:16:26.000000000 +0000
@@ -3608,13 +3608,28 @@
 
 static int slirp_inited;
 static VLANClientState *slirp_vc;
+static const char *tftp_prefix;
+static const char *bootp_filename;
+static const char *slirp_hostname;
+static void *slirp_opaque;
+static char slirp_network[32];
 
-int slirp_can_output(void)
+void slirp_maybe_init(void)
+{
+    if (!slirp_inited) {
+        slirp_inited = 1;
+        sprintf(slirp_network, "10.0.%d.0", slirp_vc->vlan->id + 2);
+        slirp_opaque = slirp_init(slirp_vc, slirp_hostname, tftp_prefix,
+                                  slirp_network);
+    }
+}
+
+int slirp_can_output(void *user)
 {
     return !slirp_vc || qemu_can_send_packet(slirp_vc);
 }
 
-void slirp_output(const uint8_t *pkt, int pkt_len)
+void slirp_output(void *user, const uint8_t *pkt, int pkt_len)
 {
 #if 0
     printf("slirp output:\n");
@@ -3631,17 +3646,13 @@
     printf("slirp input:\n");
     hex_dump(stdout, buf, size);
 #endif
-    slirp_input(buf, size);
+    slirp_input(slirp_opaque, buf, size);
 }
 
 static int net_slirp_init(VLANState *vlan)
 {
-    if (!slirp_inited) {
-        slirp_inited = 1;
-        slirp_init();
-    }
-    slirp_vc = qemu_new_vlan_client(vlan,
-                                    slirp_receive, NULL, NULL);
+    slirp_vc = qemu_new_vlan_client(vlan, slirp_receive, NULL, NULL);
+    slirp_maybe_init();
     snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector");
     return 0;
 }
@@ -3654,11 +3665,7 @@
     struct in_addr guest_addr;
     int host_port, guest_port;
 
-    if (!slirp_inited) {
-        slirp_inited = 1;
-        slirp_init();
-    }
-
+    slirp_maybe_init();
     p = redir_str;
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
         goto fail;
@@ -3688,7 +3695,8 @@
     if (r == p)
         goto fail;
 
-    if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
+    if (slirp_redir(slirp_opaque, is_udp, host_port, guest_addr,
+                    guest_port) < 0) {
         fprintf(stderr, "qemu: could not set up redirection\n");
         exit(1);
     }
@@ -3732,11 +3740,7 @@
     char smb_cmdline[1024];
     FILE *f;
 
-    if (!slirp_inited) {
-        slirp_inited = 1;
-        slirp_init();
-    }
-
+    slirp_maybe_init();
     /* XXX: better tmp dir construction */
     snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid());
     if (mkdir(smb_dir, 0700) < 0) {
@@ -3777,10 +3781,14 @@
     snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
              SMBD_COMMAND, smb_conf);
 
-    slirp_add_exec(0, smb_cmdline, 4, 139);
+    slirp_add_exec(slirp_opaque, 0, smb_cmdline, 4, 139);
 }
 
 #endif /* !defined(_WIN32) */
+void do_info_slirp(void)
+{
+    slirp_stats(slirp_opaque);
+}
 
 #endif /* CONFIG_SLIRP */
 
@@ -4600,8 +4608,8 @@
     } else
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
-        if (get_param_value(buf, sizeof(buf), "hostname", p)) {
-            pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
+        if (get_param_value(buf, sizeof(buf), "hostname", p) <= 0) {
+            slirp_hostname = strdup(buf);
         }
         vlan->nb_host_devs++;
         ret = net_slirp_init(vlan);
@@ -6823,7 +6831,7 @@
 #endif
 #if defined(CONFIG_SLIRP)
     if (slirp_inited) {
-        slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
+        slirp_select_fill(slirp_opaque, &nfds, &rfds, &wfds, &xfds);
     }
 #endif
     ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
@@ -6857,7 +6865,7 @@
             FD_ZERO(&wfds);
             FD_ZERO(&xfds);
         }
-        slirp_select_poll(&rfds, &wfds, &xfds);
+        slirp_select_poll(slirp_opaque, &rfds, &wfds, &xfds);
     }
 #endif
     qemu_aio_poll();
Index: qemu/vl.h
===================================================================
--- qemu.orig/vl.h	2007-10-20 07:33:39.000000000 +0000
+++ qemu/vl.h	2007-10-20 08:17:52.000000000 +0000
@@ -183,7 +183,6 @@
 extern int semihosting_enabled;
 extern int autostart;
 extern int old_param;
-extern const char *bootp_filename;
 
 #define MAX_OPTION_ROMS 16
 extern const char *option_rom[MAX_OPTION_ROMS];
@@ -439,6 +438,9 @@
 extern int nb_nics;
 extern NICInfo nd_table[MAX_NICS];
 
+/* SLIRP */
+void do_info_slirp(void);
+
 /* timers */
 
 typedef struct QEMUClock QEMUClock;
Index: qemu/monitor.c
===================================================================
--- qemu.orig/monitor.c	2007-10-20 07:33:39.000000000 +0000
+++ qemu/monitor.c	2007-10-20 08:17:52.000000000 +0000
@@ -1365,6 +1365,10 @@
     { "cpustats", "", do_info_cpu_stats,
       "", "show CPU statistics", },
 #endif
+#if defined(CONFIG_SLIRP)
+    { "slirp", "", do_info_slirp,
+      "", "show SLIRP statistics", },
+#endif
     { NULL, NULL, },
 };
 

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

end of thread, other threads:[~2007-10-23 17:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-20 18:42 [Qemu-devel] PATCH, RFC: Slirp improvements Blue Swirl
2007-10-23 17:42 ` [Qemu-devel] " Blue Swirl

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).