4
* Copyright (c) 2004-2008 Fabrice Bellard
6
* Permission is hereby granted, free of charge, to any person obtaining a copy
7
* of this software and associated documentation files (the "Software"), to deal
8
* in the Software without restriction, including without limitation the rights
9
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
* copies of the Software, and to permit persons to whom the Software is
11
* furnished to do so, subject to the following conditions:
13
* The above copyright notice and this permission notice shall be included in
14
* all copies or substantial portions of the Software.
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
struct in_addr our_addr;
28
/* host dns address */
29
struct in_addr dns_addr;
30
/* host loopback address */
31
struct in_addr loopback_addr;
33
/* address for slirp virtual addresses */
34
struct in_addr special_addr;
35
/* virtual address alias for host */
36
struct in_addr alias_addr;
38
static const uint8_t special_ethaddr[6] = {
39
0x52, 0x54, 0x00, 0x12, 0x35, 0x00
42
/* ARP cache for the guest IP addresses (XXX: allow many entries) */
43
uint8_t client_ethaddr[6];
44
static struct in_addr client_ipaddr;
46
static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
52
struct ex_list *exec_list;
54
/* XXX: suppress those select globals */
55
fd_set *global_readfds, *global_writefds, *global_xfds;
57
char slirp_hostname[33];
61
static int get_dns_addr(struct in_addr *pdns_addr)
63
FIXED_INFO *FixedInfo=NULL;
66
IP_ADDR_STRING *pIPAddr;
67
struct in_addr tmp_addr;
69
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
70
BufLen = sizeof(FIXED_INFO);
72
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
74
GlobalFree(FixedInfo);
77
FixedInfo = GlobalAlloc(GPTR, BufLen);
80
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
81
printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
83
GlobalFree(FixedInfo);
89
pIPAddr = &(FixedInfo->DnsServerList);
90
inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
91
*pdns_addr = tmp_addr;
93
printf( "DNS Servers:\n" );
94
printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
96
pIPAddr = FixedInfo -> DnsServerList.Next;
98
printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
99
pIPAddr = pIPAddr ->Next;
103
GlobalFree(FixedInfo);
111
static int get_dns_addr(struct in_addr *pdns_addr)
117
struct in_addr tmp_addr;
119
f = fopen("/etc/resolv.conf", "r");
124
lprint("IP address of your DNS(s): ");
126
while (fgets(buff, 512, f) != NULL) {
127
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
128
if (!inet_aton(buff2, &tmp_addr))
130
if (tmp_addr.s_addr == loopback_addr.s_addr)
132
/* If it's the first one, set it to dns_addr */
134
*pdns_addr = tmp_addr;
147
lprint("%s", inet_ntoa(tmp_addr));
160
static void slirp_cleanup(void)
166
void slirp_init(void)
168
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
173
WSAStartup(MAKEWORD(2,0), &Data);
174
atexit(slirp_cleanup);
183
/* Initialise mbufs *after* setting the MTU */
186
/* set default addresses */
187
inet_aton("127.0.0.1", &loopback_addr);
189
if (get_dns_addr(&dns_addr) < 0) {
190
dns_addr = loopback_addr;
191
fprintf (stderr, "Warning: No DNS servers found\n");
194
inet_aton(CTL_SPECIAL, &special_addr);
195
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
199
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
200
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
201
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
204
* curtime kept to an accuracy of 1ms
207
static void updtime(void)
212
curtime = (u_int)tb.time * (u_int)1000;
213
curtime += (u_int)tb.millitm;
216
static void updtime(void)
218
gettimeofday(&tt, 0);
220
curtime = (u_int)tt.tv_sec * (u_int)1000;
221
curtime += (u_int)tt.tv_usec / (u_int)1000;
223
if ((tt.tv_usec % 1000) >= 500)
228
void slirp_select_fill(int *pnfds,
229
fd_set *readfds, fd_set *writefds, fd_set *xfds)
231
struct socket *so, *so_next;
232
struct timeval timeout;
237
global_readfds = NULL;
238
global_writefds = NULL;
248
* *_slowtimo needs calling if there are IP fragments
249
* in the fragment queue, or there are TCP connections active
251
do_slowtimo = ((tcb.so_next != &tcb) ||
252
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
254
for (so = tcb.so_next; so != &tcb; so = so_next) {
255
so_next = so->so_next;
258
* See if we need a tcp_fasttimo
260
if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
261
time_fasttimo = curtime; /* Flag when we want a fasttimo */
264
* NOFDREF can include still connecting to local-host,
265
* newly socreated() sockets etc. Don't want to select these.
267
if (so->so_state & SS_NOFDREF || so->s == -1)
271
* Set for reading sockets which are accepting
273
if (so->so_state & SS_FACCEPTCONN) {
274
FD_SET(so->s, readfds);
280
* Set for writing sockets which are connecting
282
if (so->so_state & SS_ISFCONNECTING) {
283
FD_SET(so->s, writefds);
289
* Set for writing if we are connected, can send more, and
290
* we have something to send
292
if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
293
FD_SET(so->s, writefds);
298
* Set for reading (and urgent data) if we are connected, can
299
* receive more, and we have room for it XXX /2 ?
301
if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
302
FD_SET(so->s, readfds);
311
for (so = udb.so_next; so != &udb; so = so_next) {
312
so_next = so->so_next;
315
* See if it's timed out
318
if (so->so_expire <= curtime) {
322
do_slowtimo = 1; /* Let socket expire */
326
* When UDP packets are received from over the
327
* link, they're sendto()'d straight away, so
328
* no need for setting for writing
329
* Limit the number of packets queued by this session
330
* to 4. Note that even though we try and limit this
331
* to 4 packets, the session could have more queued
332
* if the packets needed to be fragmented
335
if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
336
FD_SET(so->s, readfds);
343
* Setup timeout to use minimum CPU usage, especially when idle
347
* First, see the timeout needed by *timo
350
timeout.tv_usec = -1;
352
* If a slowtimo is needed, set timeout to 500ms from the last
353
* slow timeout. If a fast timeout is needed, set timeout within
354
* 200ms of when it was requested.
357
/* XXX + 10000 because some select()'s aren't that accurate */
358
timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
359
if (timeout.tv_usec < 0)
361
else if (timeout.tv_usec > 510000)
362
timeout.tv_usec = 510000;
364
/* Can only fasttimo if we also slowtimo */
366
tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
370
/* Choose the smallest of the 2 */
371
if (tmp_time < timeout.tv_usec)
372
timeout.tv_usec = (u_int)tmp_time;
378
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
380
struct socket *so, *so_next;
383
global_readfds = readfds;
384
global_writefds = writefds;
391
* See if anything has timed out
394
if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
398
if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
401
last_slowtimo = curtime;
412
for (so = tcb.so_next; so != &tcb; so = so_next) {
413
so_next = so->so_next;
416
* FD_ISSET is meaningless on these sockets
417
* (and they can crash the program)
419
if (so->so_state & SS_NOFDREF || so->s == -1)
424
* This will soread as well, so no need to
425
* test for readfds below if this succeeds
427
if (FD_ISSET(so->s, xfds))
430
* Check sockets for reading
432
else if (FD_ISSET(so->s, readfds)) {
434
* Check for incoming connections
436
if (so->so_state & SS_FACCEPTCONN) {
442
/* Output it if we read something */
444
tcp_output(sototcpcb(so));
448
* Check sockets for writing
450
if (FD_ISSET(so->s, writefds)) {
452
* Check for non-blocking, still-connecting sockets
454
if (so->so_state & SS_ISFCONNECTING) {
456
so->so_state &= ~SS_ISFCONNECTING;
458
ret = send(so->s, &ret, 0, 0);
460
/* XXXXX Must fix, zero bytes is a NOP */
461
if (errno == EAGAIN || errno == EWOULDBLOCK ||
462
errno == EINPROGRESS || errno == ENOTCONN)
466
so->so_state = SS_NOFDREF;
468
/* else so->so_state &= ~SS_ISFCONNECTING; */
473
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
478
* XXXXX If we wrote something (a lot), there
479
* could be a need for a window update.
480
* In the worst case, the remote will send
481
* a window probe to get things going again
486
* Probe a still-connecting, non-blocking socket
487
* to check if it's still alive
490
if (so->so_state & SS_ISFCONNECTING) {
491
ret = recv(so->s, (char *)&ret, 0,0);
495
if (errno == EAGAIN || errno == EWOULDBLOCK ||
496
errno == EINPROGRESS || errno == ENOTCONN)
497
continue; /* Still connecting, continue */
500
so->so_state = SS_NOFDREF;
502
/* tcp_input will take care of it */
504
ret = send(so->s, &ret, 0,0);
507
if (errno == EAGAIN || errno == EWOULDBLOCK ||
508
errno == EINPROGRESS || errno == ENOTCONN)
511
so->so_state = SS_NOFDREF;
513
so->so_state &= ~SS_ISFCONNECTING;
516
tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
517
} /* SS_ISFCONNECTING */
523
* Incoming packets are sent straight away, they're not buffered.
524
* Incoming UDP data isn't buffered either.
526
for (so = udb.so_next; so != &udb; so = so_next) {
527
so_next = so->so_next;
529
if (so->s != -1 && FD_ISSET(so->s, readfds)) {
536
* See if we can start outputting
538
if (if_queued && link_up)
541
/* clear global file descriptor sets.
542
* these reside on the stack in vl.c
543
* so they're unusable if we're not in
544
* slirp_select_fill or slirp_select_poll.
546
global_readfds = NULL;
547
global_writefds = NULL;
554
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
555
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
557
#define ARPOP_REQUEST 1 /* ARP request */
558
#define ARPOP_REPLY 2 /* ARP reply */
562
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
563
unsigned char h_source[ETH_ALEN]; /* source ether addr */
564
unsigned short h_proto; /* packet type ID field */
569
unsigned short ar_hrd; /* format of hardware address */
570
unsigned short ar_pro; /* format of protocol address */
571
unsigned char ar_hln; /* length of hardware address */
572
unsigned char ar_pln; /* length of protocol address */
573
unsigned short ar_op; /* ARP opcode (command) */
576
* Ethernet looks like this : This bit is variable sized however...
578
unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
579
unsigned char ar_sip[4]; /* sender IP address */
580
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
581
unsigned char ar_tip[4]; /* target IP address */
584
static void arp_input(const uint8_t *pkt, int pkt_len)
586
struct ethhdr *eh = (struct ethhdr *)pkt;
587
struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
588
uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
589
struct ethhdr *reh = (struct ethhdr *)arp_reply;
590
struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
592
struct ex_list *ex_ptr;
594
ar_op = ntohs(ah->ar_op);
597
if (!memcmp(ah->ar_tip, &special_addr, 3)) {
598
if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
600
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
601
if (ex_ptr->ex_addr == ah->ar_tip[3])
606
/* XXX: make an ARP request to have the client address */
607
memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
609
/* ARP request for alias/dns mac address */
610
memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
611
memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
612
reh->h_source[5] = ah->ar_tip[3];
613
reh->h_proto = htons(ETH_P_ARP);
615
rah->ar_hrd = htons(1);
616
rah->ar_pro = htons(ETH_P_IP);
617
rah->ar_hln = ETH_ALEN;
619
rah->ar_op = htons(ARPOP_REPLY);
620
memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
621
memcpy(rah->ar_sip, ah->ar_tip, 4);
622
memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
623
memcpy(rah->ar_tip, ah->ar_sip, 4);
624
slirp_output(arp_reply, sizeof(arp_reply));
628
/* reply to request of client mac address ? */
629
if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
630
!memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) {
631
memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
639
void slirp_input(const uint8_t *pkt, int pkt_len)
644
if (pkt_len < ETH_HLEN)
647
proto = ntohs(*(uint16_t *)(pkt + 12));
650
arp_input(pkt, pkt_len);
656
/* Note: we add to align the IP header */
657
m->m_len = pkt_len + 2;
658
memcpy(m->m_data + 2, pkt, pkt_len);
660
m->m_data += 2 + ETH_HLEN;
661
m->m_len -= 2 + ETH_HLEN;
670
/* output the IP packet to the ethernet device */
671
void if_encap(const uint8_t *ip_data, int ip_data_len)
674
struct ethhdr *eh = (struct ethhdr *)buf;
676
if (ip_data_len + ETH_HLEN > sizeof(buf))
679
if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
680
uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
681
struct ethhdr *reh = (struct ethhdr *)arp_req;
682
struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
683
const struct ip *iph = (const struct ip *)ip_data;
685
/* If the client addr is not known, there is no point in
686
sending the packet to it. Normally the sender should have
687
done an ARP request to get its MAC address. Here we do it
688
in place of sending the packet and we hope that the sender
689
will retry sending its packet. */
690
memset(reh->h_dest, 0xff, ETH_ALEN);
691
memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
692
reh->h_source[5] = CTL_ALIAS;
693
reh->h_proto = htons(ETH_P_ARP);
694
rah->ar_hrd = htons(1);
695
rah->ar_pro = htons(ETH_P_IP);
696
rah->ar_hln = ETH_ALEN;
698
rah->ar_op = htons(ARPOP_REQUEST);
700
memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
701
rah->ar_sha[5] = CTL_ALIAS;
703
memcpy(rah->ar_sip, &alias_addr, 4);
704
/* target hw addr (none) */
705
memset(rah->ar_tha, 0, ETH_ALEN);
707
memcpy(rah->ar_tip, &iph->ip_dst, 4);
708
client_ipaddr = iph->ip_dst;
709
slirp_output(arp_req, sizeof(arp_req));
711
memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
712
memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
713
/* XXX: not correct */
714
eh->h_source[5] = CTL_ALIAS;
715
eh->h_proto = htons(ETH_P_IP);
716
memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
717
slirp_output(buf, ip_data_len + ETH_HLEN);
721
int slirp_redir(int is_udp, int host_port,
722
struct in_addr guest_addr, int guest_port)
725
if (!udp_listen(htons(host_port), guest_addr.s_addr,
726
htons(guest_port), 0))
729
if (!solisten(htons(host_port), guest_addr.s_addr,
730
htons(guest_port), 0))
736
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
739
return add_exec(&exec_list, do_pty, (char *)args,
740
addr_low_byte, htons(guest_port));