target-ppc: revert part of commit r6254 committed accidentally
[qemu/mini2440/sniper_sniper_test.git] / slirp / slirp.c
blobc1361ab108d56efdd31f6a2456183bb5cde09aad
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 "qemu-common.h"
25 #include "slirp.h"
26 #include "hw/hw.h"
28 /* host address */
29 struct in_addr our_addr;
30 /* host dns address */
31 struct in_addr dns_addr;
32 /* host loopback address */
33 struct in_addr loopback_addr;
35 /* address for slirp virtual addresses */
36 struct in_addr special_addr;
37 /* virtual address alias for host */
38 struct in_addr alias_addr;
40 static const uint8_t special_ethaddr[6] = {
41 0x52, 0x54, 0x00, 0x12, 0x35, 0x00
44 /* ARP cache for the guest IP addresses (XXX: allow many entries) */
45 uint8_t client_ethaddr[6];
46 static struct in_addr client_ipaddr;
48 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
50 char *slirp_special_ip = CTL_SPECIAL;
51 int slirp_restrict;
52 int do_slowtimo;
53 int link_up;
54 struct timeval tt;
55 FILE *lfd;
56 struct ex_list *exec_list;
58 /* XXX: suppress those select globals */
59 fd_set *global_readfds, *global_writefds, *global_xfds;
61 char slirp_hostname[33];
63 #ifdef _WIN32
65 static int get_dns_addr(struct in_addr *pdns_addr)
67 FIXED_INFO *FixedInfo=NULL;
68 ULONG BufLen;
69 DWORD ret;
70 IP_ADDR_STRING *pIPAddr;
71 struct in_addr tmp_addr;
73 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
74 BufLen = sizeof(FIXED_INFO);
76 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
77 if (FixedInfo) {
78 GlobalFree(FixedInfo);
79 FixedInfo = NULL;
81 FixedInfo = GlobalAlloc(GPTR, BufLen);
84 if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
85 printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
86 if (FixedInfo) {
87 GlobalFree(FixedInfo);
88 FixedInfo = NULL;
90 return -1;
93 pIPAddr = &(FixedInfo->DnsServerList);
94 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
95 *pdns_addr = tmp_addr;
96 #if 0
97 printf( "DNS Servers:\n" );
98 printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
100 pIPAddr = FixedInfo -> DnsServerList.Next;
101 while ( pIPAddr ) {
102 printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
103 pIPAddr = pIPAddr ->Next;
105 #endif
106 if (FixedInfo) {
107 GlobalFree(FixedInfo);
108 FixedInfo = NULL;
110 return 0;
113 #else
115 static int get_dns_addr(struct in_addr *pdns_addr)
117 char buff[512];
118 char buff2[257];
119 FILE *f;
120 int found = 0;
121 struct in_addr tmp_addr;
123 f = fopen("/etc/resolv.conf", "r");
124 if (!f)
125 return -1;
127 #ifdef DEBUG
128 lprint("IP address of your DNS(s): ");
129 #endif
130 while (fgets(buff, 512, f) != NULL) {
131 if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
132 if (!inet_aton(buff2, &tmp_addr))
133 continue;
134 if (tmp_addr.s_addr == loopback_addr.s_addr)
135 tmp_addr = our_addr;
136 /* If it's the first one, set it to dns_addr */
137 if (!found)
138 *pdns_addr = tmp_addr;
139 #ifdef DEBUG
140 else
141 lprint(", ");
142 #endif
143 if (++found > 3) {
144 #ifdef DEBUG
145 lprint("(more)");
146 #endif
147 break;
149 #ifdef DEBUG
150 else
151 lprint("%s", inet_ntoa(tmp_addr));
152 #endif
155 fclose(f);
156 if (!found)
157 return -1;
158 return 0;
161 #endif
163 #ifdef _WIN32
164 static void slirp_cleanup(void)
166 WSACleanup();
168 #endif
170 static void slirp_state_save(QEMUFile *f, void *opaque);
171 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
173 void slirp_init(int restrict, char *special_ip)
175 // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
177 #ifdef _WIN32
179 WSADATA Data;
180 WSAStartup(MAKEWORD(2,0), &Data);
181 atexit(slirp_cleanup);
183 #endif
185 link_up = 1;
186 slirp_restrict = restrict;
188 if_init();
189 ip_init();
191 /* Initialise mbufs *after* setting the MTU */
192 m_init();
194 /* set default addresses */
195 inet_aton("127.0.0.1", &loopback_addr);
197 if (get_dns_addr(&dns_addr) < 0) {
198 dns_addr = loopback_addr;
199 fprintf (stderr, "Warning: No DNS servers found\n");
202 if (special_ip)
203 slirp_special_ip = special_ip;
205 inet_aton(slirp_special_ip, &special_addr);
206 alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
207 getouraddr();
208 register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
211 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
212 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
213 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
216 * curtime kept to an accuracy of 1ms
218 #ifdef _WIN32
219 static void updtime(void)
221 struct _timeb tb;
223 _ftime(&tb);
224 curtime = (u_int)tb.time * (u_int)1000;
225 curtime += (u_int)tb.millitm;
227 #else
228 static void updtime(void)
230 gettimeofday(&tt, 0);
232 curtime = (u_int)tt.tv_sec * (u_int)1000;
233 curtime += (u_int)tt.tv_usec / (u_int)1000;
235 if ((tt.tv_usec % 1000) >= 500)
236 curtime++;
238 #endif
240 void slirp_select_fill(int *pnfds,
241 fd_set *readfds, fd_set *writefds, fd_set *xfds)
243 struct socket *so, *so_next;
244 struct timeval timeout;
245 int nfds;
246 int tmp_time;
248 /* fail safe */
249 global_readfds = NULL;
250 global_writefds = NULL;
251 global_xfds = NULL;
253 nfds = *pnfds;
255 * First, TCP sockets
257 do_slowtimo = 0;
258 if (link_up) {
260 * *_slowtimo needs calling if there are IP fragments
261 * in the fragment queue, or there are TCP connections active
263 do_slowtimo = ((tcb.so_next != &tcb) ||
264 ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
266 for (so = tcb.so_next; so != &tcb; so = so_next) {
267 so_next = so->so_next;
270 * See if we need a tcp_fasttimo
272 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
273 time_fasttimo = curtime; /* Flag when we want a fasttimo */
276 * NOFDREF can include still connecting to local-host,
277 * newly socreated() sockets etc. Don't want to select these.
279 if (so->so_state & SS_NOFDREF || so->s == -1)
280 continue;
283 * Set for reading sockets which are accepting
285 if (so->so_state & SS_FACCEPTCONN) {
286 FD_SET(so->s, readfds);
287 UPD_NFDS(so->s);
288 continue;
292 * Set for writing sockets which are connecting
294 if (so->so_state & SS_ISFCONNECTING) {
295 FD_SET(so->s, writefds);
296 UPD_NFDS(so->s);
297 continue;
301 * Set for writing if we are connected, can send more, and
302 * we have something to send
304 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
305 FD_SET(so->s, writefds);
306 UPD_NFDS(so->s);
310 * Set for reading (and urgent data) if we are connected, can
311 * receive more, and we have room for it XXX /2 ?
313 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
314 FD_SET(so->s, readfds);
315 FD_SET(so->s, xfds);
316 UPD_NFDS(so->s);
321 * UDP sockets
323 for (so = udb.so_next; so != &udb; so = so_next) {
324 so_next = so->so_next;
327 * See if it's timed out
329 if (so->so_expire) {
330 if (so->so_expire <= curtime) {
331 udp_detach(so);
332 continue;
333 } else
334 do_slowtimo = 1; /* Let socket expire */
338 * When UDP packets are received from over the
339 * link, they're sendto()'d straight away, so
340 * no need for setting for writing
341 * Limit the number of packets queued by this session
342 * to 4. Note that even though we try and limit this
343 * to 4 packets, the session could have more queued
344 * if the packets needed to be fragmented
345 * (XXX <= 4 ?)
347 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
348 FD_SET(so->s, readfds);
349 UPD_NFDS(so->s);
355 * Setup timeout to use minimum CPU usage, especially when idle
359 * First, see the timeout needed by *timo
361 timeout.tv_sec = 0;
362 timeout.tv_usec = -1;
364 * If a slowtimo is needed, set timeout to 500ms from the last
365 * slow timeout. If a fast timeout is needed, set timeout within
366 * 200ms of when it was requested.
368 if (do_slowtimo) {
369 /* XXX + 10000 because some select()'s aren't that accurate */
370 timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
371 if (timeout.tv_usec < 0)
372 timeout.tv_usec = 0;
373 else if (timeout.tv_usec > 510000)
374 timeout.tv_usec = 510000;
376 /* Can only fasttimo if we also slowtimo */
377 if (time_fasttimo) {
378 tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
379 if (tmp_time < 0)
380 tmp_time = 0;
382 /* Choose the smallest of the 2 */
383 if (tmp_time < timeout.tv_usec)
384 timeout.tv_usec = (u_int)tmp_time;
387 *pnfds = nfds;
390 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
392 struct socket *so, *so_next;
393 int ret;
395 global_readfds = readfds;
396 global_writefds = writefds;
397 global_xfds = xfds;
399 /* Update time */
400 updtime();
403 * See if anything has timed out
405 if (link_up) {
406 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
407 tcp_fasttimo();
408 time_fasttimo = 0;
410 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
411 ip_slowtimo();
412 tcp_slowtimo();
413 last_slowtimo = curtime;
418 * Check sockets
420 if (link_up) {
422 * Check TCP sockets
424 for (so = tcb.so_next; so != &tcb; so = so_next) {
425 so_next = so->so_next;
428 * FD_ISSET is meaningless on these sockets
429 * (and they can crash the program)
431 if (so->so_state & SS_NOFDREF || so->s == -1)
432 continue;
435 * Check for URG data
436 * This will soread as well, so no need to
437 * test for readfds below if this succeeds
439 if (FD_ISSET(so->s, xfds))
440 sorecvoob(so);
442 * Check sockets for reading
444 else if (FD_ISSET(so->s, readfds)) {
446 * Check for incoming connections
448 if (so->so_state & SS_FACCEPTCONN) {
449 tcp_connect(so);
450 continue;
451 } /* else */
452 ret = soread(so);
454 /* Output it if we read something */
455 if (ret > 0)
456 tcp_output(sototcpcb(so));
460 * Check sockets for writing
462 if (FD_ISSET(so->s, writefds)) {
464 * Check for non-blocking, still-connecting sockets
466 if (so->so_state & SS_ISFCONNECTING) {
467 /* Connected */
468 so->so_state &= ~SS_ISFCONNECTING;
470 ret = send(so->s, &ret, 0, 0);
471 if (ret < 0) {
472 /* XXXXX Must fix, zero bytes is a NOP */
473 if (errno == EAGAIN || errno == EWOULDBLOCK ||
474 errno == EINPROGRESS || errno == ENOTCONN)
475 continue;
477 /* else failed */
478 so->so_state = SS_NOFDREF;
480 /* else so->so_state &= ~SS_ISFCONNECTING; */
483 * Continue tcp_input
485 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
486 /* continue; */
487 } else
488 ret = sowrite(so);
490 * XXXXX If we wrote something (a lot), there
491 * could be a need for a window update.
492 * In the worst case, the remote will send
493 * a window probe to get things going again
498 * Probe a still-connecting, non-blocking socket
499 * to check if it's still alive
501 #ifdef PROBE_CONN
502 if (so->so_state & SS_ISFCONNECTING) {
503 ret = recv(so->s, (char *)&ret, 0,0);
505 if (ret < 0) {
506 /* XXX */
507 if (errno == EAGAIN || errno == EWOULDBLOCK ||
508 errno == EINPROGRESS || errno == ENOTCONN)
509 continue; /* Still connecting, continue */
511 /* else failed */
512 so->so_state = SS_NOFDREF;
514 /* tcp_input will take care of it */
515 } else {
516 ret = send(so->s, &ret, 0,0);
517 if (ret < 0) {
518 /* XXX */
519 if (errno == EAGAIN || errno == EWOULDBLOCK ||
520 errno == EINPROGRESS || errno == ENOTCONN)
521 continue;
522 /* else failed */
523 so->so_state = SS_NOFDREF;
524 } else
525 so->so_state &= ~SS_ISFCONNECTING;
528 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
529 } /* SS_ISFCONNECTING */
530 #endif
534 * Now UDP sockets.
535 * Incoming packets are sent straight away, they're not buffered.
536 * Incoming UDP data isn't buffered either.
538 for (so = udb.so_next; so != &udb; so = so_next) {
539 so_next = so->so_next;
541 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
542 sorecvfrom(so);
548 * See if we can start outputting
550 if (if_queued && link_up)
551 if_start();
553 /* clear global file descriptor sets.
554 * these reside on the stack in vl.c
555 * so they're unusable if we're not in
556 * slirp_select_fill or slirp_select_poll.
558 global_readfds = NULL;
559 global_writefds = NULL;
560 global_xfds = NULL;
563 #define ETH_ALEN 6
564 #define ETH_HLEN 14
566 #define ETH_P_IP 0x0800 /* Internet Protocol packet */
567 #define ETH_P_ARP 0x0806 /* Address Resolution packet */
569 #define ARPOP_REQUEST 1 /* ARP request */
570 #define ARPOP_REPLY 2 /* ARP reply */
572 struct ethhdr
574 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
575 unsigned char h_source[ETH_ALEN]; /* source ether addr */
576 unsigned short h_proto; /* packet type ID field */
579 struct arphdr
581 unsigned short ar_hrd; /* format of hardware address */
582 unsigned short ar_pro; /* format of protocol address */
583 unsigned char ar_hln; /* length of hardware address */
584 unsigned char ar_pln; /* length of protocol address */
585 unsigned short ar_op; /* ARP opcode (command) */
588 * Ethernet looks like this : This bit is variable sized however...
590 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
591 unsigned char ar_sip[4]; /* sender IP address */
592 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
593 unsigned char ar_tip[4]; /* target IP address */
596 static void arp_input(const uint8_t *pkt, int pkt_len)
598 struct ethhdr *eh = (struct ethhdr *)pkt;
599 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
600 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
601 struct ethhdr *reh = (struct ethhdr *)arp_reply;
602 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
603 int ar_op;
604 struct ex_list *ex_ptr;
606 ar_op = ntohs(ah->ar_op);
607 switch(ar_op) {
608 case ARPOP_REQUEST:
609 if (!memcmp(ah->ar_tip, &special_addr, 3)) {
610 if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
611 goto arp_ok;
612 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
613 if (ex_ptr->ex_addr == ah->ar_tip[3])
614 goto arp_ok;
616 return;
617 arp_ok:
618 /* XXX: make an ARP request to have the client address */
619 memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
621 /* ARP request for alias/dns mac address */
622 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
623 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
624 reh->h_source[5] = ah->ar_tip[3];
625 reh->h_proto = htons(ETH_P_ARP);
627 rah->ar_hrd = htons(1);
628 rah->ar_pro = htons(ETH_P_IP);
629 rah->ar_hln = ETH_ALEN;
630 rah->ar_pln = 4;
631 rah->ar_op = htons(ARPOP_REPLY);
632 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
633 memcpy(rah->ar_sip, ah->ar_tip, 4);
634 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
635 memcpy(rah->ar_tip, ah->ar_sip, 4);
636 slirp_output(arp_reply, sizeof(arp_reply));
638 break;
639 case ARPOP_REPLY:
640 /* reply to request of client mac address ? */
641 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
642 !memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) {
643 memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
645 break;
646 default:
647 break;
651 void slirp_input(const uint8_t *pkt, int pkt_len)
653 struct mbuf *m;
654 int proto;
656 if (pkt_len < ETH_HLEN)
657 return;
659 proto = ntohs(*(uint16_t *)(pkt + 12));
660 switch(proto) {
661 case ETH_P_ARP:
662 arp_input(pkt, pkt_len);
663 break;
664 case ETH_P_IP:
665 m = m_get();
666 if (!m)
667 return;
668 /* Note: we add to align the IP header */
669 if (M_FREEROOM(m) < pkt_len + 2) {
670 m_inc(m, pkt_len + 2);
672 m->m_len = pkt_len + 2;
673 memcpy(m->m_data + 2, pkt, pkt_len);
675 m->m_data += 2 + ETH_HLEN;
676 m->m_len -= 2 + ETH_HLEN;
678 ip_input(m);
679 break;
680 default:
681 break;
685 /* output the IP packet to the ethernet device */
686 void if_encap(const uint8_t *ip_data, int ip_data_len)
688 uint8_t buf[1600];
689 struct ethhdr *eh = (struct ethhdr *)buf;
691 if (ip_data_len + ETH_HLEN > sizeof(buf))
692 return;
694 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
695 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
696 struct ethhdr *reh = (struct ethhdr *)arp_req;
697 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
698 const struct ip *iph = (const struct ip *)ip_data;
700 /* If the client addr is not known, there is no point in
701 sending the packet to it. Normally the sender should have
702 done an ARP request to get its MAC address. Here we do it
703 in place of sending the packet and we hope that the sender
704 will retry sending its packet. */
705 memset(reh->h_dest, 0xff, ETH_ALEN);
706 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
707 reh->h_source[5] = CTL_ALIAS;
708 reh->h_proto = htons(ETH_P_ARP);
709 rah->ar_hrd = htons(1);
710 rah->ar_pro = htons(ETH_P_IP);
711 rah->ar_hln = ETH_ALEN;
712 rah->ar_pln = 4;
713 rah->ar_op = htons(ARPOP_REQUEST);
714 /* source hw addr */
715 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
716 rah->ar_sha[5] = CTL_ALIAS;
717 /* source IP */
718 memcpy(rah->ar_sip, &alias_addr, 4);
719 /* target hw addr (none) */
720 memset(rah->ar_tha, 0, ETH_ALEN);
721 /* target IP */
722 memcpy(rah->ar_tip, &iph->ip_dst, 4);
723 client_ipaddr = iph->ip_dst;
724 slirp_output(arp_req, sizeof(arp_req));
725 } else {
726 memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
727 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
728 /* XXX: not correct */
729 eh->h_source[5] = CTL_ALIAS;
730 eh->h_proto = htons(ETH_P_IP);
731 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
732 slirp_output(buf, ip_data_len + ETH_HLEN);
736 int slirp_redir(int is_udp, int host_port,
737 struct in_addr guest_addr, int guest_port)
739 if (is_udp) {
740 if (!udp_listen(htons(host_port), guest_addr.s_addr,
741 htons(guest_port), 0))
742 return -1;
743 } else {
744 if (!solisten(htons(host_port), guest_addr.s_addr,
745 htons(guest_port), 0))
746 return -1;
748 return 0;
751 int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
752 int guest_port)
754 return add_exec(&exec_list, do_pty, (char *)args,
755 addr_low_byte, htons(guest_port));
758 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
760 if (so->s == -1 && so->extra) {
761 qemu_chr_write(so->extra, buf, len);
762 return len;
765 return send(so->s, buf, len, flags);
768 static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
770 struct socket *so;
772 for (so = tcb.so_next; so != &tcb; so = so->so_next) {
773 if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
774 special_addr.s_addr
775 && (ntohl(so->so_faddr.s_addr) & 0xff) ==
776 addr_low_byte
777 && htons(so->so_fport) == guest_port)
778 return so;
781 return NULL;
784 size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
786 struct iovec iov[2];
787 struct socket *so;
789 if (!link_up)
790 return 0;
792 so = slirp_find_ctl_socket(addr_low_byte, guest_port);
794 if (!so || so->so_state & SS_NOFDREF)
795 return 0;
797 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
798 return 0;
800 return sopreprbuf(so, iov, NULL);
803 void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
804 int size)
806 int ret;
807 struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
809 if (!so)
810 return;
812 ret = soreadbuf(so, buf, size);
814 if (ret > 0)
815 tcp_output(sototcpcb(so));
818 static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
820 int i;
822 qemu_put_sbe16(f, tp->t_state);
823 for (i = 0; i < TCPT_NTIMERS; i++)
824 qemu_put_sbe16(f, tp->t_timer[i]);
825 qemu_put_sbe16(f, tp->t_rxtshift);
826 qemu_put_sbe16(f, tp->t_rxtcur);
827 qemu_put_sbe16(f, tp->t_dupacks);
828 qemu_put_be16(f, tp->t_maxseg);
829 qemu_put_sbyte(f, tp->t_force);
830 qemu_put_be16(f, tp->t_flags);
831 qemu_put_be32(f, tp->snd_una);
832 qemu_put_be32(f, tp->snd_nxt);
833 qemu_put_be32(f, tp->snd_up);
834 qemu_put_be32(f, tp->snd_wl1);
835 qemu_put_be32(f, tp->snd_wl2);
836 qemu_put_be32(f, tp->iss);
837 qemu_put_be32(f, tp->snd_wnd);
838 qemu_put_be32(f, tp->rcv_wnd);
839 qemu_put_be32(f, tp->rcv_nxt);
840 qemu_put_be32(f, tp->rcv_up);
841 qemu_put_be32(f, tp->irs);
842 qemu_put_be32(f, tp->rcv_adv);
843 qemu_put_be32(f, tp->snd_max);
844 qemu_put_be32(f, tp->snd_cwnd);
845 qemu_put_be32(f, tp->snd_ssthresh);
846 qemu_put_sbe16(f, tp->t_idle);
847 qemu_put_sbe16(f, tp->t_rtt);
848 qemu_put_be32(f, tp->t_rtseq);
849 qemu_put_sbe16(f, tp->t_srtt);
850 qemu_put_sbe16(f, tp->t_rttvar);
851 qemu_put_be16(f, tp->t_rttmin);
852 qemu_put_be32(f, tp->max_sndwnd);
853 qemu_put_byte(f, tp->t_oobflags);
854 qemu_put_byte(f, tp->t_iobc);
855 qemu_put_sbe16(f, tp->t_softerror);
856 qemu_put_byte(f, tp->snd_scale);
857 qemu_put_byte(f, tp->rcv_scale);
858 qemu_put_byte(f, tp->request_r_scale);
859 qemu_put_byte(f, tp->requested_s_scale);
860 qemu_put_be32(f, tp->ts_recent);
861 qemu_put_be32(f, tp->ts_recent_age);
862 qemu_put_be32(f, tp->last_ack_sent);
865 static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
867 uint32_t off;
869 qemu_put_be32(f, sbuf->sb_cc);
870 qemu_put_be32(f, sbuf->sb_datalen);
871 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
872 qemu_put_sbe32(f, off);
873 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
874 qemu_put_sbe32(f, off);
875 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
878 static void slirp_socket_save(QEMUFile *f, struct socket *so)
880 qemu_put_be32(f, so->so_urgc);
881 qemu_put_be32(f, so->so_faddr.s_addr);
882 qemu_put_be32(f, so->so_laddr.s_addr);
883 qemu_put_be16(f, so->so_fport);
884 qemu_put_be16(f, so->so_lport);
885 qemu_put_byte(f, so->so_iptos);
886 qemu_put_byte(f, so->so_emu);
887 qemu_put_byte(f, so->so_type);
888 qemu_put_be32(f, so->so_state);
889 slirp_sbuf_save(f, &so->so_rcv);
890 slirp_sbuf_save(f, &so->so_snd);
891 slirp_tcp_save(f, so->so_tcpcb);
894 static void slirp_state_save(QEMUFile *f, void *opaque)
896 struct ex_list *ex_ptr;
898 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
899 if (ex_ptr->ex_pty == 3) {
900 struct socket *so;
901 so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
902 if (!so)
903 continue;
905 qemu_put_byte(f, 42);
906 slirp_socket_save(f, so);
908 qemu_put_byte(f, 0);
911 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
913 int i;
915 tp->t_state = qemu_get_sbe16(f);
916 for (i = 0; i < TCPT_NTIMERS; i++)
917 tp->t_timer[i] = qemu_get_sbe16(f);
918 tp->t_rxtshift = qemu_get_sbe16(f);
919 tp->t_rxtcur = qemu_get_sbe16(f);
920 tp->t_dupacks = qemu_get_sbe16(f);
921 tp->t_maxseg = qemu_get_be16(f);
922 tp->t_force = qemu_get_sbyte(f);
923 tp->t_flags = qemu_get_be16(f);
924 tp->snd_una = qemu_get_be32(f);
925 tp->snd_nxt = qemu_get_be32(f);
926 tp->snd_up = qemu_get_be32(f);
927 tp->snd_wl1 = qemu_get_be32(f);
928 tp->snd_wl2 = qemu_get_be32(f);
929 tp->iss = qemu_get_be32(f);
930 tp->snd_wnd = qemu_get_be32(f);
931 tp->rcv_wnd = qemu_get_be32(f);
932 tp->rcv_nxt = qemu_get_be32(f);
933 tp->rcv_up = qemu_get_be32(f);
934 tp->irs = qemu_get_be32(f);
935 tp->rcv_adv = qemu_get_be32(f);
936 tp->snd_max = qemu_get_be32(f);
937 tp->snd_cwnd = qemu_get_be32(f);
938 tp->snd_ssthresh = qemu_get_be32(f);
939 tp->t_idle = qemu_get_sbe16(f);
940 tp->t_rtt = qemu_get_sbe16(f);
941 tp->t_rtseq = qemu_get_be32(f);
942 tp->t_srtt = qemu_get_sbe16(f);
943 tp->t_rttvar = qemu_get_sbe16(f);
944 tp->t_rttmin = qemu_get_be16(f);
945 tp->max_sndwnd = qemu_get_be32(f);
946 tp->t_oobflags = qemu_get_byte(f);
947 tp->t_iobc = qemu_get_byte(f);
948 tp->t_softerror = qemu_get_sbe16(f);
949 tp->snd_scale = qemu_get_byte(f);
950 tp->rcv_scale = qemu_get_byte(f);
951 tp->request_r_scale = qemu_get_byte(f);
952 tp->requested_s_scale = qemu_get_byte(f);
953 tp->ts_recent = qemu_get_be32(f);
954 tp->ts_recent_age = qemu_get_be32(f);
955 tp->last_ack_sent = qemu_get_be32(f);
956 tcp_template(tp);
959 static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
961 uint32_t off, sb_cc, sb_datalen;
963 sb_cc = qemu_get_be32(f);
964 sb_datalen = qemu_get_be32(f);
966 sbreserve(sbuf, sb_datalen);
968 if (sbuf->sb_datalen != sb_datalen)
969 return -ENOMEM;
971 sbuf->sb_cc = sb_cc;
973 off = qemu_get_sbe32(f);
974 sbuf->sb_wptr = sbuf->sb_data + off;
975 off = qemu_get_sbe32(f);
976 sbuf->sb_rptr = sbuf->sb_data + off;
977 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
979 return 0;
982 static int slirp_socket_load(QEMUFile *f, struct socket *so)
984 if (tcp_attach(so) < 0)
985 return -ENOMEM;
987 so->so_urgc = qemu_get_be32(f);
988 so->so_faddr.s_addr = qemu_get_be32(f);
989 so->so_laddr.s_addr = qemu_get_be32(f);
990 so->so_fport = qemu_get_be16(f);
991 so->so_lport = qemu_get_be16(f);
992 so->so_iptos = qemu_get_byte(f);
993 so->so_emu = qemu_get_byte(f);
994 so->so_type = qemu_get_byte(f);
995 so->so_state = qemu_get_be32(f);
996 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
997 return -ENOMEM;
998 if (slirp_sbuf_load(f, &so->so_snd) < 0)
999 return -ENOMEM;
1000 slirp_tcp_load(f, so->so_tcpcb);
1002 return 0;
1005 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1007 struct ex_list *ex_ptr;
1008 int r;
1010 while ((r = qemu_get_byte(f))) {
1011 int ret;
1012 struct socket *so = socreate();
1014 if (!so)
1015 return -ENOMEM;
1017 ret = slirp_socket_load(f, so);
1019 if (ret < 0)
1020 return ret;
1022 if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr)
1023 return -EINVAL;
1025 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
1026 if (ex_ptr->ex_pty == 3 &&
1027 (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr &&
1028 so->so_fport == ex_ptr->ex_fport)
1029 break;
1031 if (!ex_ptr)
1032 return -EINVAL;
1034 so->extra = ex_ptr->ex_exec;
1037 return 0;