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