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 if (M_FREEROOM(m
) < pkt_len
+ 2) {
658 m_inc(m
, pkt_len
+ 2);
660 m
->m_len
= pkt_len
+ 2;
661 memcpy(m
->m_data
+ 2, pkt
, pkt_len
);
663 m
->m_data
+= 2 + ETH_HLEN
;
664 m
->m_len
-= 2 + ETH_HLEN
;
673 /* output the IP packet to the ethernet device */
674 void if_encap(const uint8_t *ip_data
, int ip_data_len
)
677 struct ethhdr
*eh
= (struct ethhdr
*)buf
;
679 if (ip_data_len
+ ETH_HLEN
> sizeof(buf
))
682 if (!memcmp(client_ethaddr
, zero_ethaddr
, ETH_ALEN
)) {
683 uint8_t arp_req
[ETH_HLEN
+ sizeof(struct arphdr
)];
684 struct ethhdr
*reh
= (struct ethhdr
*)arp_req
;
685 struct arphdr
*rah
= (struct arphdr
*)(arp_req
+ ETH_HLEN
);
686 const struct ip
*iph
= (const struct ip
*)ip_data
;
688 /* If the client addr is not known, there is no point in
689 sending the packet to it. Normally the sender should have
690 done an ARP request to get its MAC address. Here we do it
691 in place of sending the packet and we hope that the sender
692 will retry sending its packet. */
693 memset(reh
->h_dest
, 0xff, ETH_ALEN
);
694 memcpy(reh
->h_source
, special_ethaddr
, ETH_ALEN
- 1);
695 reh
->h_source
[5] = CTL_ALIAS
;
696 reh
->h_proto
= htons(ETH_P_ARP
);
697 rah
->ar_hrd
= htons(1);
698 rah
->ar_pro
= htons(ETH_P_IP
);
699 rah
->ar_hln
= ETH_ALEN
;
701 rah
->ar_op
= htons(ARPOP_REQUEST
);
703 memcpy(rah
->ar_sha
, special_ethaddr
, ETH_ALEN
- 1);
704 rah
->ar_sha
[5] = CTL_ALIAS
;
706 memcpy(rah
->ar_sip
, &alias_addr
, 4);
707 /* target hw addr (none) */
708 memset(rah
->ar_tha
, 0, ETH_ALEN
);
710 memcpy(rah
->ar_tip
, &iph
->ip_dst
, 4);
711 client_ipaddr
= iph
->ip_dst
;
712 slirp_output(arp_req
, sizeof(arp_req
));
714 memcpy(eh
->h_dest
, client_ethaddr
, ETH_ALEN
);
715 memcpy(eh
->h_source
, special_ethaddr
, ETH_ALEN
- 1);
716 /* XXX: not correct */
717 eh
->h_source
[5] = CTL_ALIAS
;
718 eh
->h_proto
= htons(ETH_P_IP
);
719 memcpy(buf
+ sizeof(struct ethhdr
), ip_data
, ip_data_len
);
720 slirp_output(buf
, ip_data_len
+ ETH_HLEN
);
724 int slirp_redir(int is_udp
, int host_port
,
725 struct in_addr guest_addr
, int guest_port
)
728 if (!udp_listen(htons(host_port
), guest_addr
.s_addr
,
729 htons(guest_port
), 0))
732 if (!solisten(htons(host_port
), guest_addr
.s_addr
,
733 htons(guest_port
), 0))
739 int slirp_add_exec(int do_pty
, const char *args
, int addr_low_byte
,
742 return add_exec(&exec_list
, do_pty
, (char *)args
,
743 addr_low_byte
, htons(guest_port
));