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