fix spell error. pvao->pavo
[qemu/qemu-JZ.git] / slirp / slirp.c
blob17b40e249a2b365008bbe6a4867d68d3ea9d0bce
1 /*
2 * libslirp glue
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
22 * THE SOFTWARE.
24 #include "slirp.h"
26 /* host address */
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 };
48 int do_slowtimo;
49 int link_up;
50 struct timeval tt;
51 FILE *lfd;
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];
59 #ifdef _WIN32
61 static int get_dns_addr(struct in_addr *pdns_addr)
63 FIXED_INFO *FixedInfo=NULL;
64 ULONG BufLen;
65 DWORD ret;
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)) {
73 if (FixedInfo) {
74 GlobalFree(FixedInfo);
75 FixedInfo = NULL;
77 FixedInfo = GlobalAlloc(GPTR, BufLen);
80 if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
81 printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
82 if (FixedInfo) {
83 GlobalFree(FixedInfo);
84 FixedInfo = NULL;
86 return -1;
89 pIPAddr = &(FixedInfo->DnsServerList);
90 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
91 *pdns_addr = tmp_addr;
92 #if 0
93 printf( "DNS Servers:\n" );
94 printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
96 pIPAddr = FixedInfo -> DnsServerList.Next;
97 while ( pIPAddr ) {
98 printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
99 pIPAddr = pIPAddr ->Next;
101 #endif
102 if (FixedInfo) {
103 GlobalFree(FixedInfo);
104 FixedInfo = NULL;
106 return 0;
109 #else
111 static int get_dns_addr(struct in_addr *pdns_addr)
113 char buff[512];
114 char buff2[257];
115 FILE *f;
116 int found = 0;
117 struct in_addr tmp_addr;
119 f = fopen("/etc/resolv.conf", "r");
120 if (!f)
121 return -1;
123 #ifdef DEBUG
124 lprint("IP address of your DNS(s): ");
125 #endif
126 while (fgets(buff, 512, f) != NULL) {
127 if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
128 if (!inet_aton(buff2, &tmp_addr))
129 continue;
130 if (tmp_addr.s_addr == loopback_addr.s_addr)
131 tmp_addr = our_addr;
132 /* If it's the first one, set it to dns_addr */
133 if (!found)
134 *pdns_addr = tmp_addr;
135 #ifdef DEBUG
136 else
137 lprint(", ");
138 #endif
139 if (++found > 3) {
140 #ifdef DEBUG
141 lprint("(more)");
142 #endif
143 break;
145 #ifdef DEBUG
146 else
147 lprint("%s", inet_ntoa(tmp_addr));
148 #endif
151 fclose(f);
152 if (!found)
153 return -1;
154 return 0;
157 #endif
159 #ifdef _WIN32
160 static void slirp_cleanup(void)
162 WSACleanup();
164 #endif
166 void slirp_init(void)
168 // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
170 #ifdef _WIN32
172 WSADATA Data;
173 WSAStartup(MAKEWORD(2,0), &Data);
174 atexit(slirp_cleanup);
176 #endif
178 link_up = 1;
180 if_init();
181 ip_init();
183 /* Initialise mbufs *after* setting the MTU */
184 m_init();
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);
196 getouraddr();
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
206 #ifdef _WIN32
207 static void updtime(void)
209 struct _timeb tb;
211 _ftime(&tb);
212 curtime = (u_int)tb.time * (u_int)1000;
213 curtime += (u_int)tb.millitm;
215 #else
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)
224 curtime++;
226 #endif
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;
233 int nfds;
234 int tmp_time;
236 /* fail safe */
237 global_readfds = NULL;
238 global_writefds = NULL;
239 global_xfds = NULL;
241 nfds = *pnfds;
243 * First, TCP sockets
245 do_slowtimo = 0;
246 if (link_up) {
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)
268 continue;
271 * Set for reading sockets which are accepting
273 if (so->so_state & SS_FACCEPTCONN) {
274 FD_SET(so->s, readfds);
275 UPD_NFDS(so->s);
276 continue;
280 * Set for writing sockets which are connecting
282 if (so->so_state & SS_ISFCONNECTING) {
283 FD_SET(so->s, writefds);
284 UPD_NFDS(so->s);
285 continue;
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);
294 UPD_NFDS(so->s);
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);
303 FD_SET(so->s, xfds);
304 UPD_NFDS(so->s);
309 * UDP sockets
311 for (so = udb.so_next; so != &udb; so = so_next) {
312 so_next = so->so_next;
315 * See if it's timed out
317 if (so->so_expire) {
318 if (so->so_expire <= curtime) {
319 udp_detach(so);
320 continue;
321 } else
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
333 * (XXX <= 4 ?)
335 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
336 FD_SET(so->s, readfds);
337 UPD_NFDS(so->s);
343 * Setup timeout to use minimum CPU usage, especially when idle
347 * First, see the timeout needed by *timo
349 timeout.tv_sec = 0;
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.
356 if (do_slowtimo) {
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)
360 timeout.tv_usec = 0;
361 else if (timeout.tv_usec > 510000)
362 timeout.tv_usec = 510000;
364 /* Can only fasttimo if we also slowtimo */
365 if (time_fasttimo) {
366 tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
367 if (tmp_time < 0)
368 tmp_time = 0;
370 /* Choose the smallest of the 2 */
371 if (tmp_time < timeout.tv_usec)
372 timeout.tv_usec = (u_int)tmp_time;
375 *pnfds = nfds;
378 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
380 struct socket *so, *so_next;
381 int ret;
383 global_readfds = readfds;
384 global_writefds = writefds;
385 global_xfds = xfds;
387 /* Update time */
388 updtime();
391 * See if anything has timed out
393 if (link_up) {
394 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
395 tcp_fasttimo();
396 time_fasttimo = 0;
398 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
399 ip_slowtimo();
400 tcp_slowtimo();
401 last_slowtimo = curtime;
406 * Check sockets
408 if (link_up) {
410 * Check TCP sockets
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)
420 continue;
423 * Check for URG data
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))
428 sorecvoob(so);
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) {
437 tcp_connect(so);
438 continue;
439 } /* else */
440 ret = soread(so);
442 /* Output it if we read something */
443 if (ret > 0)
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) {
455 /* Connected */
456 so->so_state &= ~SS_ISFCONNECTING;
458 ret = send(so->s, &ret, 0, 0);
459 if (ret < 0) {
460 /* XXXXX Must fix, zero bytes is a NOP */
461 if (errno == EAGAIN || errno == EWOULDBLOCK ||
462 errno == EINPROGRESS || errno == ENOTCONN)
463 continue;
465 /* else failed */
466 so->so_state = SS_NOFDREF;
468 /* else so->so_state &= ~SS_ISFCONNECTING; */
471 * Continue tcp_input
473 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
474 /* continue; */
475 } else
476 ret = sowrite(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
489 #ifdef PROBE_CONN
490 if (so->so_state & SS_ISFCONNECTING) {
491 ret = recv(so->s, (char *)&ret, 0,0);
493 if (ret < 0) {
494 /* XXX */
495 if (errno == EAGAIN || errno == EWOULDBLOCK ||
496 errno == EINPROGRESS || errno == ENOTCONN)
497 continue; /* Still connecting, continue */
499 /* else failed */
500 so->so_state = SS_NOFDREF;
502 /* tcp_input will take care of it */
503 } else {
504 ret = send(so->s, &ret, 0,0);
505 if (ret < 0) {
506 /* XXX */
507 if (errno == EAGAIN || errno == EWOULDBLOCK ||
508 errno == EINPROGRESS || errno == ENOTCONN)
509 continue;
510 /* else failed */
511 so->so_state = SS_NOFDREF;
512 } else
513 so->so_state &= ~SS_ISFCONNECTING;
516 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
517 } /* SS_ISFCONNECTING */
518 #endif
522 * Now UDP sockets.
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)) {
530 sorecvfrom(so);
536 * See if we can start outputting
538 if (if_queued && link_up)
539 if_start();
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;
548 global_xfds = NULL;
551 #define ETH_ALEN 6
552 #define ETH_HLEN 14
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 */
560 struct ethhdr
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 */
567 struct arphdr
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);
591 int ar_op;
592 struct ex_list *ex_ptr;
594 ar_op = ntohs(ah->ar_op);
595 switch(ar_op) {
596 case ARPOP_REQUEST:
597 if (!memcmp(ah->ar_tip, &special_addr, 3)) {
598 if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
599 goto arp_ok;
600 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
601 if (ex_ptr->ex_addr == ah->ar_tip[3])
602 goto arp_ok;
604 return;
605 arp_ok:
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;
618 rah->ar_pln = 4;
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));
626 break;
627 case ARPOP_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);
633 break;
634 default:
635 break;
639 void slirp_input(const uint8_t *pkt, int pkt_len)
641 struct mbuf *m;
642 int proto;
644 if (pkt_len < ETH_HLEN)
645 return;
647 proto = ntohs(*(uint16_t *)(pkt + 12));
648 switch(proto) {
649 case ETH_P_ARP:
650 arp_input(pkt, pkt_len);
651 break;
652 case ETH_P_IP:
653 m = m_get();
654 if (!m)
655 return;
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;
666 ip_input(m);
667 break;
668 default:
669 break;
673 /* output the IP packet to the ethernet device */
674 void if_encap(const uint8_t *ip_data, int ip_data_len)
676 uint8_t buf[1600];
677 struct ethhdr *eh = (struct ethhdr *)buf;
679 if (ip_data_len + ETH_HLEN > sizeof(buf))
680 return;
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;
700 rah->ar_pln = 4;
701 rah->ar_op = htons(ARPOP_REQUEST);
702 /* source hw addr */
703 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
704 rah->ar_sha[5] = CTL_ALIAS;
705 /* source IP */
706 memcpy(rah->ar_sip, &alias_addr, 4);
707 /* target hw addr (none) */
708 memset(rah->ar_tha, 0, ETH_ALEN);
709 /* target IP */
710 memcpy(rah->ar_tip, &iph->ip_dst, 4);
711 client_ipaddr = iph->ip_dst;
712 slirp_output(arp_req, sizeof(arp_req));
713 } else {
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)
727 if (is_udp) {
728 if (!udp_listen(htons(host_port), guest_addr.s_addr,
729 htons(guest_port), 0))
730 return -1;
731 } else {
732 if (!solisten(htons(host_port), guest_addr.s_addr,
733 htons(guest_port), 0))
734 return -1;
736 return 0;
739 int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
740 int guest_port)
742 return add_exec(&exec_list, do_pty, (char *)args,
743 addr_low_byte, htons(guest_port));