summaryrefslogtreecommitdiffstats
path: root/slirp/slirp.c
diff options
context:
space:
mode:
Diffstat (limited to 'slirp/slirp.c')
-rw-r--r--slirp/slirp.c142
1 files changed, 83 insertions, 59 deletions
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;