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