4 struct in_addr our_addr;
6 struct in_addr dns_addr;
7 /* host loopback address */
8 struct in_addr loopback_addr;
10 /* address for slirp virtual addresses */
11 struct in_addr special_addr;
12 /* virtual address alias for host */
13 struct in_addr alias_addr;
15 static const uint8_t special_ethaddr[6] = {
16 0x52, 0x54, 0x00, 0x12, 0x35, 0x00
19 /* ARP cache for the guest IP addresses (XXX: allow many entries) */
20 uint8_t client_ethaddr[6];
21 static struct in_addr client_ipaddr;
23 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
29 struct ex_list *exec_list;
31 /* XXX: suppress those select globals */
32 fd_set *global_readfds, *global_writefds, *global_xfds;
34 char slirp_hostname[33];
38 static int get_dns_addr(struct in_addr *pdns_addr)
40 FIXED_INFO *FixedInfo=NULL;
43 IP_ADDR_STRING *pIPAddr;
44 struct in_addr tmp_addr;
46 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
47 BufLen = sizeof(FIXED_INFO);
49 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
51 GlobalFree(FixedInfo);
54 FixedInfo = GlobalAlloc(GPTR, BufLen);
57 if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
58 printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
60 GlobalFree(FixedInfo);
66 pIPAddr = &(FixedInfo->DnsServerList);
67 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
68 *pdns_addr = tmp_addr;
70 printf( "DNS Servers:\n" );
71 printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
73 pIPAddr = FixedInfo -> DnsServerList.Next;
75 printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
76 pIPAddr = pIPAddr ->Next;
80 GlobalFree(FixedInfo);
88 static int get_dns_addr(struct in_addr *pdns_addr)
94 struct in_addr tmp_addr;
96 f = fopen("/etc/resolv.conf", "r");
101 lprint("IP address of your DNS(s): ");
103 while (fgets(buff, 512, f) != NULL) {
104 if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
105 if (!inet_aton(buff2, &tmp_addr))
107 if (tmp_addr.s_addr == loopback_addr.s_addr)
109 /* If it's the first one, set it to dns_addr */
111 *pdns_addr = tmp_addr;
124 lprint("%s", inet_ntoa(tmp_addr));
137 static void slirp_cleanup(void)
143 void slirp_init(void)
145 // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
150 WSAStartup(MAKEWORD(2,0), &Data);
151 atexit(slirp_cleanup);
160 /* Initialise mbufs *after* setting the MTU */
163 /* set default addresses */
164 inet_aton("127.0.0.1", &loopback_addr);
166 if (get_dns_addr(&dns_addr) < 0) {
167 dns_addr = loopback_addr;
168 fprintf (stderr, "Warning: No DNS servers found\n");
171 inet_aton(CTL_SPECIAL, &special_addr);
172 alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
176 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
177 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
178 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
181 * curtime kept to an accuracy of 1ms
184 static void updtime(void)
189 curtime = (u_int)tb.time * (u_int)1000;
190 curtime += (u_int)tb.millitm;
193 static void updtime(void)
195 gettimeofday(&tt, 0);
197 curtime = (u_int)tt.tv_sec * (u_int)1000;
198 curtime += (u_int)tt.tv_usec / (u_int)1000;
200 if ((tt.tv_usec % 1000) >= 500)
205 void slirp_select_fill(int *pnfds,
206 fd_set *readfds, fd_set *writefds, fd_set *xfds)
208 struct socket *so, *so_next;
209 struct timeval timeout;
214 global_readfds = NULL;
215 global_writefds = NULL;
225 * *_slowtimo needs calling if there are IP fragments
226 * in the fragment queue, or there are TCP connections active
228 do_slowtimo = ((tcb.so_next != &tcb) ||
229 ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
231 for (so = tcb.so_next; so != &tcb; so = so_next) {
232 so_next = so->so_next;
235 * See if we need a tcp_fasttimo
237 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
238 time_fasttimo = curtime; /* Flag when we want a fasttimo */
241 * NOFDREF can include still connecting to local-host,
242 * newly socreated() sockets etc. Don't want to select these.
244 if (so->so_state & SS_NOFDREF || so->s == -1)
248 * Set for reading sockets which are accepting
250 if (so->so_state & SS_FACCEPTCONN) {
251 FD_SET(so->s, readfds);
257 * Set for writing sockets which are connecting
259 if (so->so_state & SS_ISFCONNECTING) {
260 FD_SET(so->s, writefds);
266 * Set for writing if we are connected, can send more, and
267 * we have something to send
269 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
270 FD_SET(so->s, writefds);
275 * Set for reading (and urgent data) if we are connected, can
276 * receive more, and we have room for it XXX /2 ?
278 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
279 FD_SET(so->s, readfds);
288 for (so = udb.so_next; so != &udb; so = so_next) {
289 so_next = so->so_next;
292 * See if it's timed out
295 if (so->so_expire <= curtime) {
299 do_slowtimo = 1; /* Let socket expire */
303 * When UDP packets are received from over the
304 * link, they're sendto()'d straight away, so
305 * no need for setting for writing
306 * Limit the number of packets queued by this session
307 * to 4. Note that even though we try and limit this
308 * to 4 packets, the session could have more queued
309 * if the packets needed to be fragmented
312 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
313 FD_SET(so->s, readfds);
320 * Setup timeout to use minimum CPU usage, especially when idle
324 * First, see the timeout needed by *timo
327 timeout.tv_usec = -1;
329 * If a slowtimo is needed, set timeout to 500ms from the last
330 * slow timeout. If a fast timeout is needed, set timeout within
331 * 200ms of when it was requested.
334 /* XXX + 10000 because some select()'s aren't that accurate */
335 timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
336 if (timeout.tv_usec < 0)
338 else if (timeout.tv_usec > 510000)
339 timeout.tv_usec = 510000;
341 /* Can only fasttimo if we also slowtimo */
343 tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
347 /* Choose the smallest of the 2 */
348 if (tmp_time < timeout.tv_usec)
349 timeout.tv_usec = (u_int)tmp_time;
355 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
357 struct socket *so, *so_next;
360 global_readfds = readfds;
361 global_writefds = writefds;
368 * See if anything has timed out
371 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
375 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
378 last_slowtimo = curtime;
389 for (so = tcb.so_next; so != &tcb; so = so_next) {
390 so_next = so->so_next;
393 * FD_ISSET is meaningless on these sockets
394 * (and they can crash the program)
396 if (so->so_state & SS_NOFDREF || so->s == -1)
401 * This will soread as well, so no need to
402 * test for readfds below if this succeeds
404 if (FD_ISSET(so->s, xfds))
407 * Check sockets for reading
409 else if (FD_ISSET(so->s, readfds)) {
411 * Check for incoming connections
413 if (so->so_state & SS_FACCEPTCONN) {
419 /* Output it if we read something */
421 tcp_output(sototcpcb(so));
425 * Check sockets for writing
427 if (FD_ISSET(so->s, writefds)) {
429 * Check for non-blocking, still-connecting sockets
431 if (so->so_state & SS_ISFCONNECTING) {
433 so->so_state &= ~SS_ISFCONNECTING;
435 ret = send(so->s, &ret, 0, 0);
437 /* XXXXX Must fix, zero bytes is a NOP */
438 if (errno == EAGAIN || errno == EWOULDBLOCK ||
439 errno == EINPROGRESS || errno == ENOTCONN)
443 so->so_state = SS_NOFDREF;
445 /* else so->so_state &= ~SS_ISFCONNECTING; */
450 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
455 * XXXXX If we wrote something (a lot), there
456 * could be a need for a window update.
457 * In the worst case, the remote will send
458 * a window probe to get things going again
463 * Probe a still-connecting, non-blocking socket
464 * to check if it's still alive
467 if (so->so_state & SS_ISFCONNECTING) {
468 ret = recv(so->s, (char *)&ret, 0,0);
472 if (errno == EAGAIN || errno == EWOULDBLOCK ||
473 errno == EINPROGRESS || errno == ENOTCONN)
474 continue; /* Still connecting, continue */
477 so->so_state = SS_NOFDREF;
479 /* tcp_input will take care of it */
481 ret = send(so->s, &ret, 0,0);
484 if (errno == EAGAIN || errno == EWOULDBLOCK ||
485 errno == EINPROGRESS || errno == ENOTCONN)
488 so->so_state = SS_NOFDREF;
490 so->so_state &= ~SS_ISFCONNECTING;
493 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
494 } /* SS_ISFCONNECTING */
500 * Incoming packets are sent straight away, they're not buffered.
501 * Incoming UDP data isn't buffered either.
503 for (so = udb.so_next; so != &udb; so = so_next) {
504 so_next = so->so_next;
506 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
513 * See if we can start outputting
515 if (if_queued && link_up)
518 /* clear global file descriptor sets.
519 * these reside on the stack in vl.c
520 * so they're unusable if we're not in
521 * slirp_select_fill or slirp_select_poll.
523 global_readfds = NULL;
524 global_writefds = NULL;
531 #define ETH_P_IP 0x0800 /* Internet Protocol packet */
532 #define ETH_P_ARP 0x0806 /* Address Resolution packet */
534 #define ARPOP_REQUEST 1 /* ARP request */
535 #define ARPOP_REPLY 2 /* ARP reply */
539 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
540 unsigned char h_source[ETH_ALEN]; /* source ether addr */
541 unsigned short h_proto; /* packet type ID field */
546 unsigned short ar_hrd; /* format of hardware address */
547 unsigned short ar_pro; /* format of protocol address */
548 unsigned char ar_hln; /* length of hardware address */
549 unsigned char ar_pln; /* length of protocol address */
550 unsigned short ar_op; /* ARP opcode (command) */
553 * Ethernet looks like this : This bit is variable sized however...
555 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
556 unsigned char ar_sip[4]; /* sender IP address */
557 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
558 unsigned char ar_tip[4]; /* target IP address */
561 static void arp_input(const uint8_t *pkt, int pkt_len)
563 struct ethhdr *eh = (struct ethhdr *)pkt;
564 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
565 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
566 struct ethhdr *reh = (struct ethhdr *)arp_reply;
567 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
569 struct ex_list *ex_ptr;
571 ar_op = ntohs(ah->ar_op);
574 if (!memcmp(ah->ar_tip, &special_addr, 3)) {
575 if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
577 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
578 if (ex_ptr->ex_addr == ah->ar_tip[3])
583 /* XXX: make an ARP request to have the client address */
584 memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
586 /* ARP request for alias/dns mac address */
587 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
588 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
589 reh->h_source[5] = ah->ar_tip[3];
590 reh->h_proto = htons(ETH_P_ARP);
592 rah->ar_hrd = htons(1);
593 rah->ar_pro = htons(ETH_P_IP);
594 rah->ar_hln = ETH_ALEN;
596 rah->ar_op = htons(ARPOP_REPLY);
597 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
598 memcpy(rah->ar_sip, ah->ar_tip, 4);
599 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
600 memcpy(rah->ar_tip, ah->ar_sip, 4);
601 slirp_output(arp_reply, sizeof(arp_reply));
605 /* reply to request of client mac address ? */
606 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
607 !memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) {
608 memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
616 void slirp_input(const uint8_t *pkt, int pkt_len)
621 if (pkt_len < ETH_HLEN)
624 proto = ntohs(*(uint16_t *)(pkt + 12));
627 arp_input(pkt, pkt_len);
633 /* Note: we add to align the IP header */
634 m->m_len = pkt_len + 2;
635 memcpy(m->m_data + 2, pkt, pkt_len);
637 m->m_data += 2 + ETH_HLEN;
638 m->m_len -= 2 + ETH_HLEN;
647 /* output the IP packet to the ethernet device */
648 void if_encap(const uint8_t *ip_data, int ip_data_len)
651 struct ethhdr *eh = (struct ethhdr *)buf;
653 if (ip_data_len + ETH_HLEN > sizeof(buf))
656 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
657 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
658 struct ethhdr *reh = (struct ethhdr *)arp_req;
659 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
660 const struct ip *iph = (const struct ip *)ip_data;
662 /* If the client addr is not known, there is no point in
663 sending the packet to it. Normally the sender should have
664 done an ARP request to get its MAC address. Here we do it
665 in place of sending the packet and we hope that the sender
666 will retry sending its packet. */
667 memset(reh->h_dest, 0xff, ETH_ALEN);
668 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
669 reh->h_source[5] = CTL_ALIAS;
670 reh->h_proto = htons(ETH_P_ARP);
671 rah->ar_hrd = htons(1);
672 rah->ar_pro = htons(ETH_P_IP);
673 rah->ar_hln = ETH_ALEN;
675 rah->ar_op = htons(ARPOP_REQUEST);
677 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
678 rah->ar_sha[5] = CTL_ALIAS;
680 memcpy(rah->ar_sip, &alias_addr, 4);
681 /* target hw addr (none) */
682 memset(rah->ar_tha, 0, ETH_ALEN);
684 memcpy(rah->ar_tip, &iph->ip_dst, 4);
685 client_ipaddr = iph->ip_dst;
686 slirp_output(arp_req, sizeof(arp_req));
688 memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
689 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
690 /* XXX: not correct */
691 eh->h_source[5] = CTL_ALIAS;
692 eh->h_proto = htons(ETH_P_IP);
693 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
694 slirp_output(buf, ip_data_len + ETH_HLEN);
698 int slirp_redir(int is_udp, int host_port,
699 struct in_addr guest_addr, int guest_port)
702 if (!udp_listen(htons(host_port), guest_addr.s_addr,
703 htons(guest_port), 0))
706 if (!solisten(htons(host_port), guest_addr.s_addr,
707 htons(guest_port), 0))
713 int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
716 return add_exec(&exec_list, do_pty, (char *)args,
717 addr_low_byte, htons(guest_port));