]>
git.proxmox.com Git - mirror_qemu.git/blob - slirp/slirp.c
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
24 #include "qemu-common.h"
25 #include "qemu-char.h"
30 struct in_addr our_addr
;
31 /* host dns address */
32 struct in_addr dns_addr
;
33 /* host loopback address */
34 struct in_addr loopback_addr
;
36 /* virtual network configuration */
37 struct in_addr vnetwork_addr
;
38 struct in_addr vnetwork_mask
;
39 struct in_addr vhost_addr
;
40 struct in_addr vdhcp_startaddr
;
41 struct in_addr vnameserver_addr
;
43 /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
44 static const uint8_t special_ethaddr
[6] = {
45 0x52, 0x55, 0x00, 0x00, 0x00, 0x00
48 /* ARP cache for the guest IP addresses (XXX: allow many entries) */
49 uint8_t client_ethaddr
[6];
50 static struct in_addr client_ipaddr
;
52 static const uint8_t zero_ethaddr
[6] = { 0, 0, 0, 0, 0, 0 };
55 static int do_slowtimo
;
59 struct ex_list
*exec_list
;
61 /* XXX: suppress those select globals */
62 fd_set
*global_readfds
, *global_writefds
, *global_xfds
;
64 char slirp_hostname
[33];
68 static int get_dns_addr(struct in_addr
*pdns_addr
)
70 FIXED_INFO
*FixedInfo
=NULL
;
73 IP_ADDR_STRING
*pIPAddr
;
74 struct in_addr tmp_addr
;
76 FixedInfo
= (FIXED_INFO
*)GlobalAlloc(GPTR
, sizeof(FIXED_INFO
));
77 BufLen
= sizeof(FIXED_INFO
);
79 if (ERROR_BUFFER_OVERFLOW
== GetNetworkParams(FixedInfo
, &BufLen
)) {
81 GlobalFree(FixedInfo
);
84 FixedInfo
= GlobalAlloc(GPTR
, BufLen
);
87 if ((ret
= GetNetworkParams(FixedInfo
, &BufLen
)) != ERROR_SUCCESS
) {
88 printf("GetNetworkParams failed. ret = %08x\n", (u_int
)ret
);
90 GlobalFree(FixedInfo
);
96 pIPAddr
= &(FixedInfo
->DnsServerList
);
97 inet_aton(pIPAddr
->IpAddress
.String
, &tmp_addr
);
98 *pdns_addr
= tmp_addr
;
100 printf( "DNS Servers:\n" );
101 printf( "DNS Addr:%s\n", pIPAddr
->IpAddress
.String
);
103 pIPAddr
= FixedInfo
-> DnsServerList
.Next
;
105 printf( "DNS Addr:%s\n", pIPAddr
->IpAddress
.String
);
106 pIPAddr
= pIPAddr
->Next
;
110 GlobalFree(FixedInfo
);
118 static int get_dns_addr(struct in_addr
*pdns_addr
)
124 struct in_addr tmp_addr
;
126 f
= fopen("/etc/resolv.conf", "r");
131 lprint("IP address of your DNS(s): ");
133 while (fgets(buff
, 512, f
) != NULL
) {
134 if (sscanf(buff
, "nameserver%*[ \t]%256s", buff2
) == 1) {
135 if (!inet_aton(buff2
, &tmp_addr
))
137 if (tmp_addr
.s_addr
== loopback_addr
.s_addr
)
139 /* If it's the first one, set it to dns_addr */
141 *pdns_addr
= tmp_addr
;
154 lprint("%s", inet_ntoa(tmp_addr
));
167 static void slirp_cleanup(void)
173 static void slirp_state_save(QEMUFile
*f
, void *opaque
);
174 static int slirp_state_load(QEMUFile
*f
, void *opaque
, int version_id
);
176 void slirp_init(int restricted
, struct in_addr vnetwork
,
177 struct in_addr vnetmask
, struct in_addr vhost
,
178 const char *vhostname
, const char *tftp_path
,
179 const char *bootfile
, struct in_addr vdhcp_start
,
180 struct in_addr vnameserver
)
182 // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
187 WSAStartup(MAKEWORD(2,0), &Data
);
188 atexit(slirp_cleanup
);
192 slirp_restrict
= restricted
;
197 /* Initialise mbufs *after* setting the MTU */
200 /* set default addresses */
201 inet_aton("127.0.0.1", &loopback_addr
);
203 if (get_dns_addr(&dns_addr
) < 0) {
204 dns_addr
= loopback_addr
;
205 fprintf (stderr
, "Warning: No DNS servers found\n");
208 vnetwork_addr
= vnetwork
;
209 vnetwork_mask
= vnetmask
;
212 pstrcpy(slirp_hostname
, sizeof(slirp_hostname
), vhostname
);
214 qemu_free(tftp_prefix
);
217 tftp_prefix
= qemu_strdup(tftp_path
);
219 qemu_free(bootp_filename
);
220 bootp_filename
= NULL
;
222 bootp_filename
= qemu_strdup(bootfile
);
224 vdhcp_startaddr
= vdhcp_start
;
225 vnameserver_addr
= vnameserver
;
228 register_savevm("slirp", 0, 1, slirp_state_save
, slirp_state_load
, NULL
);
231 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
232 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
233 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
236 * curtime kept to an accuracy of 1ms
239 static void updtime(void)
244 curtime
= (u_int
)tb
.time
* (u_int
)1000;
245 curtime
+= (u_int
)tb
.millitm
;
248 static void updtime(void)
250 gettimeofday(&tt
, NULL
);
252 curtime
= (u_int
)tt
.tv_sec
* (u_int
)1000;
253 curtime
+= (u_int
)tt
.tv_usec
/ (u_int
)1000;
255 if ((tt
.tv_usec
% 1000) >= 500)
260 void slirp_select_fill(int *pnfds
,
261 fd_set
*readfds
, fd_set
*writefds
, fd_set
*xfds
)
263 struct socket
*so
, *so_next
;
264 struct timeval timeout
;
269 global_readfds
= NULL
;
270 global_writefds
= NULL
;
280 * *_slowtimo needs calling if there are IP fragments
281 * in the fragment queue, or there are TCP connections active
283 do_slowtimo
= ((tcb
.so_next
!= &tcb
) ||
284 (&ipq
.ip_link
!= ipq
.ip_link
.next
));
286 for (so
= tcb
.so_next
; so
!= &tcb
; so
= so_next
) {
287 so_next
= so
->so_next
;
290 * See if we need a tcp_fasttimo
292 if (time_fasttimo
== 0 && so
->so_tcpcb
->t_flags
& TF_DELACK
)
293 time_fasttimo
= curtime
; /* Flag when we want a fasttimo */
296 * NOFDREF can include still connecting to local-host,
297 * newly socreated() sockets etc. Don't want to select these.
299 if (so
->so_state
& SS_NOFDREF
|| so
->s
== -1)
303 * Set for reading sockets which are accepting
305 if (so
->so_state
& SS_FACCEPTCONN
) {
306 FD_SET(so
->s
, readfds
);
312 * Set for writing sockets which are connecting
314 if (so
->so_state
& SS_ISFCONNECTING
) {
315 FD_SET(so
->s
, writefds
);
321 * Set for writing if we are connected, can send more, and
322 * we have something to send
324 if (CONN_CANFSEND(so
) && so
->so_rcv
.sb_cc
) {
325 FD_SET(so
->s
, writefds
);
330 * Set for reading (and urgent data) if we are connected, can
331 * receive more, and we have room for it XXX /2 ?
333 if (CONN_CANFRCV(so
) && (so
->so_snd
.sb_cc
< (so
->so_snd
.sb_datalen
/2))) {
334 FD_SET(so
->s
, readfds
);
343 for (so
= udb
.so_next
; so
!= &udb
; so
= so_next
) {
344 so_next
= so
->so_next
;
347 * See if it's timed out
350 if (so
->so_expire
<= curtime
) {
354 do_slowtimo
= 1; /* Let socket expire */
358 * When UDP packets are received from over the
359 * link, they're sendto()'d straight away, so
360 * no need for setting for writing
361 * Limit the number of packets queued by this session
362 * to 4. Note that even though we try and limit this
363 * to 4 packets, the session could have more queued
364 * if the packets needed to be fragmented
367 if ((so
->so_state
& SS_ISFCONNECTED
) && so
->so_queued
<= 4) {
368 FD_SET(so
->s
, readfds
);
375 * Setup timeout to use minimum CPU usage, especially when idle
379 * First, see the timeout needed by *timo
382 timeout
.tv_usec
= -1;
384 * If a slowtimo is needed, set timeout to 500ms from the last
385 * slow timeout. If a fast timeout is needed, set timeout within
386 * 200ms of when it was requested.
389 /* XXX + 10000 because some select()'s aren't that accurate */
390 timeout
.tv_usec
= ((500 - (curtime
- last_slowtimo
)) * 1000) + 10000;
391 if (timeout
.tv_usec
< 0)
393 else if (timeout
.tv_usec
> 510000)
394 timeout
.tv_usec
= 510000;
396 /* Can only fasttimo if we also slowtimo */
398 tmp_time
= (200 - (curtime
- time_fasttimo
)) * 1000;
402 /* Choose the smallest of the 2 */
403 if (tmp_time
< timeout
.tv_usec
)
404 timeout
.tv_usec
= (u_int
)tmp_time
;
410 void slirp_select_poll(fd_set
*readfds
, fd_set
*writefds
, fd_set
*xfds
)
412 struct socket
*so
, *so_next
;
415 global_readfds
= readfds
;
416 global_writefds
= writefds
;
423 * See if anything has timed out
426 if (time_fasttimo
&& ((curtime
- time_fasttimo
) >= 2)) {
430 if (do_slowtimo
&& ((curtime
- last_slowtimo
) >= 499)) {
433 last_slowtimo
= curtime
;
444 for (so
= tcb
.so_next
; so
!= &tcb
; so
= so_next
) {
445 so_next
= so
->so_next
;
448 * FD_ISSET is meaningless on these sockets
449 * (and they can crash the program)
451 if (so
->so_state
& SS_NOFDREF
|| so
->s
== -1)
456 * This will soread as well, so no need to
457 * test for readfds below if this succeeds
459 if (FD_ISSET(so
->s
, xfds
))
462 * Check sockets for reading
464 else if (FD_ISSET(so
->s
, readfds
)) {
466 * Check for incoming connections
468 if (so
->so_state
& SS_FACCEPTCONN
) {
474 /* Output it if we read something */
476 tcp_output(sototcpcb(so
));
480 * Check sockets for writing
482 if (FD_ISSET(so
->s
, writefds
)) {
484 * Check for non-blocking, still-connecting sockets
486 if (so
->so_state
& SS_ISFCONNECTING
) {
488 so
->so_state
&= ~SS_ISFCONNECTING
;
490 ret
= send(so
->s
, (const void *) &ret
, 0, 0);
492 /* XXXXX Must fix, zero bytes is a NOP */
493 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
||
494 errno
== EINPROGRESS
|| errno
== ENOTCONN
)
498 so
->so_state
= SS_NOFDREF
;
500 /* else so->so_state &= ~SS_ISFCONNECTING; */
505 tcp_input((struct mbuf
*)NULL
, sizeof(struct ip
), so
);
510 * XXXXX If we wrote something (a lot), there
511 * could be a need for a window update.
512 * In the worst case, the remote will send
513 * a window probe to get things going again
518 * Probe a still-connecting, non-blocking socket
519 * to check if it's still alive
522 if (so
->so_state
& SS_ISFCONNECTING
) {
523 ret
= recv(so
->s
, (char *)&ret
, 0,0);
527 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
||
528 errno
== EINPROGRESS
|| errno
== ENOTCONN
)
529 continue; /* Still connecting, continue */
532 so
->so_state
= SS_NOFDREF
;
534 /* tcp_input will take care of it */
536 ret
= send(so
->s
, &ret
, 0,0);
539 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
||
540 errno
== EINPROGRESS
|| errno
== ENOTCONN
)
543 so
->so_state
= SS_NOFDREF
;
545 so
->so_state
&= ~SS_ISFCONNECTING
;
548 tcp_input((struct mbuf
*)NULL
, sizeof(struct ip
),so
);
549 } /* SS_ISFCONNECTING */
555 * Incoming packets are sent straight away, they're not buffered.
556 * Incoming UDP data isn't buffered either.
558 for (so
= udb
.so_next
; so
!= &udb
; so
= so_next
) {
559 so_next
= so
->so_next
;
561 if (so
->s
!= -1 && FD_ISSET(so
->s
, readfds
)) {
568 * See if we can start outputting
570 if (if_queued
&& link_up
)
573 /* clear global file descriptor sets.
574 * these reside on the stack in vl.c
575 * so they're unusable if we're not in
576 * slirp_select_fill or slirp_select_poll.
578 global_readfds
= NULL
;
579 global_writefds
= NULL
;
586 #define ETH_P_IP 0x0800 /* Internet Protocol packet */
587 #define ETH_P_ARP 0x0806 /* Address Resolution packet */
589 #define ARPOP_REQUEST 1 /* ARP request */
590 #define ARPOP_REPLY 2 /* ARP reply */
594 unsigned char h_dest
[ETH_ALEN
]; /* destination eth addr */
595 unsigned char h_source
[ETH_ALEN
]; /* source ether addr */
596 unsigned short h_proto
; /* packet type ID field */
601 unsigned short ar_hrd
; /* format of hardware address */
602 unsigned short ar_pro
; /* format of protocol address */
603 unsigned char ar_hln
; /* length of hardware address */
604 unsigned char ar_pln
; /* length of protocol address */
605 unsigned short ar_op
; /* ARP opcode (command) */
608 * Ethernet looks like this : This bit is variable sized however...
610 unsigned char ar_sha
[ETH_ALEN
]; /* sender hardware address */
611 uint32_t ar_sip
; /* sender IP address */
612 unsigned char ar_tha
[ETH_ALEN
]; /* target hardware address */
613 uint32_t ar_tip
; /* target IP address */
614 } __attribute__((packed
));
616 static void arp_input(const uint8_t *pkt
, int pkt_len
)
618 struct ethhdr
*eh
= (struct ethhdr
*)pkt
;
619 struct arphdr
*ah
= (struct arphdr
*)(pkt
+ ETH_HLEN
);
620 uint8_t arp_reply
[ETH_HLEN
+ sizeof(struct arphdr
)];
621 struct ethhdr
*reh
= (struct ethhdr
*)arp_reply
;
622 struct arphdr
*rah
= (struct arphdr
*)(arp_reply
+ ETH_HLEN
);
624 struct ex_list
*ex_ptr
;
626 ar_op
= ntohs(ah
->ar_op
);
629 if ((ah
->ar_tip
& vnetwork_mask
.s_addr
) == vnetwork_addr
.s_addr
) {
630 if (ah
->ar_tip
== vnameserver_addr
.s_addr
||
631 ah
->ar_tip
== vhost_addr
.s_addr
)
633 for (ex_ptr
= exec_list
; ex_ptr
; ex_ptr
= ex_ptr
->ex_next
) {
634 if (ex_ptr
->ex_addr
.s_addr
== ah
->ar_tip
)
639 /* XXX: make an ARP request to have the client address */
640 memcpy(client_ethaddr
, eh
->h_source
, ETH_ALEN
);
642 /* ARP request for alias/dns mac address */
643 memcpy(reh
->h_dest
, pkt
+ ETH_ALEN
, ETH_ALEN
);
644 memcpy(reh
->h_source
, special_ethaddr
, ETH_ALEN
- 4);
645 memcpy(&reh
->h_source
[2], &ah
->ar_tip
, 4);
646 reh
->h_proto
= htons(ETH_P_ARP
);
648 rah
->ar_hrd
= htons(1);
649 rah
->ar_pro
= htons(ETH_P_IP
);
650 rah
->ar_hln
= ETH_ALEN
;
652 rah
->ar_op
= htons(ARPOP_REPLY
);
653 memcpy(rah
->ar_sha
, reh
->h_source
, ETH_ALEN
);
654 rah
->ar_sip
= ah
->ar_tip
;
655 memcpy(rah
->ar_tha
, ah
->ar_sha
, ETH_ALEN
);
656 rah
->ar_tip
= ah
->ar_sip
;
657 slirp_output(arp_reply
, sizeof(arp_reply
));
661 /* reply to request of client mac address ? */
662 if (!memcmp(client_ethaddr
, zero_ethaddr
, ETH_ALEN
) &&
663 ah
->ar_sip
== client_ipaddr
.s_addr
) {
664 memcpy(client_ethaddr
, ah
->ar_sha
, ETH_ALEN
);
672 void slirp_input(const uint8_t *pkt
, int pkt_len
)
677 if (pkt_len
< ETH_HLEN
)
680 proto
= ntohs(*(uint16_t *)(pkt
+ 12));
683 arp_input(pkt
, pkt_len
);
689 /* Note: we add to align the IP header */
690 if (M_FREEROOM(m
) < pkt_len
+ 2) {
691 m_inc(m
, pkt_len
+ 2);
693 m
->m_len
= pkt_len
+ 2;
694 memcpy(m
->m_data
+ 2, pkt
, pkt_len
);
696 m
->m_data
+= 2 + ETH_HLEN
;
697 m
->m_len
-= 2 + ETH_HLEN
;
706 /* output the IP packet to the ethernet device */
707 void if_encap(const uint8_t *ip_data
, int ip_data_len
)
710 struct ethhdr
*eh
= (struct ethhdr
*)buf
;
712 if (ip_data_len
+ ETH_HLEN
> sizeof(buf
))
715 if (!memcmp(client_ethaddr
, zero_ethaddr
, ETH_ALEN
)) {
716 uint8_t arp_req
[ETH_HLEN
+ sizeof(struct arphdr
)];
717 struct ethhdr
*reh
= (struct ethhdr
*)arp_req
;
718 struct arphdr
*rah
= (struct arphdr
*)(arp_req
+ ETH_HLEN
);
719 const struct ip
*iph
= (const struct ip
*)ip_data
;
721 /* If the client addr is not known, there is no point in
722 sending the packet to it. Normally the sender should have
723 done an ARP request to get its MAC address. Here we do it
724 in place of sending the packet and we hope that the sender
725 will retry sending its packet. */
726 memset(reh
->h_dest
, 0xff, ETH_ALEN
);
727 memcpy(reh
->h_source
, special_ethaddr
, ETH_ALEN
- 4);
728 memcpy(&reh
->h_source
[2], &vhost_addr
, 4);
729 reh
->h_proto
= htons(ETH_P_ARP
);
730 rah
->ar_hrd
= htons(1);
731 rah
->ar_pro
= htons(ETH_P_IP
);
732 rah
->ar_hln
= ETH_ALEN
;
734 rah
->ar_op
= htons(ARPOP_REQUEST
);
736 memcpy(rah
->ar_sha
, special_ethaddr
, ETH_ALEN
- 4);
737 memcpy(&rah
->ar_sha
[2], &vhost_addr
, 4);
739 rah
->ar_sip
= vhost_addr
.s_addr
;
740 /* target hw addr (none) */
741 memset(rah
->ar_tha
, 0, ETH_ALEN
);
743 rah
->ar_tip
= iph
->ip_dst
.s_addr
;
744 client_ipaddr
= iph
->ip_dst
;
745 slirp_output(arp_req
, sizeof(arp_req
));
747 memcpy(eh
->h_dest
, client_ethaddr
, ETH_ALEN
);
748 memcpy(eh
->h_source
, special_ethaddr
, ETH_ALEN
- 4);
749 /* XXX: not correct */
750 memcpy(&eh
->h_source
[2], &vhost_addr
, 4);
751 eh
->h_proto
= htons(ETH_P_IP
);
752 memcpy(buf
+ sizeof(struct ethhdr
), ip_data
, ip_data_len
);
753 slirp_output(buf
, ip_data_len
+ ETH_HLEN
);
757 /* Unlistens a redirection
759 * Return value: number of redirs removed */
760 int slirp_remove_hostfwd(int is_udp
, int host_port
)
763 struct socket
*head
= (is_udp
? &udb
: &tcb
);
764 struct sockaddr_in addr
;
765 int port
= htons(host_port
);
770 for (so
= head
->so_next
; so
!= head
; so
= so
->so_next
) {
771 addr_len
= sizeof(addr
);
772 if (getsockname(so
->s
, (struct sockaddr
*)&addr
, &addr_len
) == 0 &&
773 addr
.sin_port
== port
) {
784 int slirp_add_hostfwd(int is_udp
, int host_port
,
785 struct in_addr guest_addr
, int guest_port
)
787 if (!guest_addr
.s_addr
) {
788 guest_addr
= vdhcp_startaddr
;
791 if (!udp_listen(htons(host_port
), guest_addr
.s_addr
,
792 htons(guest_port
), 0))
795 if (!solisten(htons(host_port
), guest_addr
.s_addr
,
796 htons(guest_port
), 0))
802 int slirp_add_exec(int do_pty
, const void *args
, struct in_addr guest_addr
,
805 if (!guest_addr
.s_addr
) {
807 vnetwork_addr
.s_addr
| (htonl(0x0204) & ~vnetwork_mask
.s_addr
);
809 if ((guest_addr
.s_addr
& vnetwork_mask
.s_addr
) != vnetwork_addr
.s_addr
||
810 guest_addr
.s_addr
== vhost_addr
.s_addr
||
811 guest_addr
.s_addr
== vnameserver_addr
.s_addr
) {
814 return add_exec(&exec_list
, do_pty
, (char *)args
, guest_addr
,
818 ssize_t
slirp_send(struct socket
*so
, const void *buf
, size_t len
, int flags
)
820 if (so
->s
== -1 && so
->extra
) {
821 qemu_chr_write(so
->extra
, buf
, len
);
825 return send(so
->s
, buf
, len
, flags
);
828 static struct socket
*
829 slirp_find_ctl_socket(struct in_addr guest_addr
, int guest_port
)
833 for (so
= tcb
.so_next
; so
!= &tcb
; so
= so
->so_next
) {
834 if (so
->so_faddr
.s_addr
== guest_addr
.s_addr
&&
835 htons(so
->so_fport
) == guest_port
) {
842 size_t slirp_socket_can_recv(struct in_addr guest_addr
, int guest_port
)
850 so
= slirp_find_ctl_socket(guest_addr
, guest_port
);
852 if (!so
|| so
->so_state
& SS_NOFDREF
)
855 if (!CONN_CANFRCV(so
) || so
->so_snd
.sb_cc
>= (so
->so_snd
.sb_datalen
/2))
858 return sopreprbuf(so
, iov
, NULL
);
861 void slirp_socket_recv(struct in_addr guest_addr
, int guest_port
,
862 const uint8_t *buf
, int size
)
865 struct socket
*so
= slirp_find_ctl_socket(guest_addr
, guest_port
);
870 ret
= soreadbuf(so
, (const char *)buf
, size
);
873 tcp_output(sototcpcb(so
));
876 static void slirp_tcp_save(QEMUFile
*f
, struct tcpcb
*tp
)
880 qemu_put_sbe16(f
, tp
->t_state
);
881 for (i
= 0; i
< TCPT_NTIMERS
; i
++)
882 qemu_put_sbe16(f
, tp
->t_timer
[i
]);
883 qemu_put_sbe16(f
, tp
->t_rxtshift
);
884 qemu_put_sbe16(f
, tp
->t_rxtcur
);
885 qemu_put_sbe16(f
, tp
->t_dupacks
);
886 qemu_put_be16(f
, tp
->t_maxseg
);
887 qemu_put_sbyte(f
, tp
->t_force
);
888 qemu_put_be16(f
, tp
->t_flags
);
889 qemu_put_be32(f
, tp
->snd_una
);
890 qemu_put_be32(f
, tp
->snd_nxt
);
891 qemu_put_be32(f
, tp
->snd_up
);
892 qemu_put_be32(f
, tp
->snd_wl1
);
893 qemu_put_be32(f
, tp
->snd_wl2
);
894 qemu_put_be32(f
, tp
->iss
);
895 qemu_put_be32(f
, tp
->snd_wnd
);
896 qemu_put_be32(f
, tp
->rcv_wnd
);
897 qemu_put_be32(f
, tp
->rcv_nxt
);
898 qemu_put_be32(f
, tp
->rcv_up
);
899 qemu_put_be32(f
, tp
->irs
);
900 qemu_put_be32(f
, tp
->rcv_adv
);
901 qemu_put_be32(f
, tp
->snd_max
);
902 qemu_put_be32(f
, tp
->snd_cwnd
);
903 qemu_put_be32(f
, tp
->snd_ssthresh
);
904 qemu_put_sbe16(f
, tp
->t_idle
);
905 qemu_put_sbe16(f
, tp
->t_rtt
);
906 qemu_put_be32(f
, tp
->t_rtseq
);
907 qemu_put_sbe16(f
, tp
->t_srtt
);
908 qemu_put_sbe16(f
, tp
->t_rttvar
);
909 qemu_put_be16(f
, tp
->t_rttmin
);
910 qemu_put_be32(f
, tp
->max_sndwnd
);
911 qemu_put_byte(f
, tp
->t_oobflags
);
912 qemu_put_byte(f
, tp
->t_iobc
);
913 qemu_put_sbe16(f
, tp
->t_softerror
);
914 qemu_put_byte(f
, tp
->snd_scale
);
915 qemu_put_byte(f
, tp
->rcv_scale
);
916 qemu_put_byte(f
, tp
->request_r_scale
);
917 qemu_put_byte(f
, tp
->requested_s_scale
);
918 qemu_put_be32(f
, tp
->ts_recent
);
919 qemu_put_be32(f
, tp
->ts_recent_age
);
920 qemu_put_be32(f
, tp
->last_ack_sent
);
923 static void slirp_sbuf_save(QEMUFile
*f
, struct sbuf
*sbuf
)
927 qemu_put_be32(f
, sbuf
->sb_cc
);
928 qemu_put_be32(f
, sbuf
->sb_datalen
);
929 off
= (uint32_t)(sbuf
->sb_wptr
- sbuf
->sb_data
);
930 qemu_put_sbe32(f
, off
);
931 off
= (uint32_t)(sbuf
->sb_rptr
- sbuf
->sb_data
);
932 qemu_put_sbe32(f
, off
);
933 qemu_put_buffer(f
, (unsigned char*)sbuf
->sb_data
, sbuf
->sb_datalen
);
936 static void slirp_socket_save(QEMUFile
*f
, struct socket
*so
)
938 qemu_put_be32(f
, so
->so_urgc
);
939 qemu_put_be32(f
, so
->so_faddr
.s_addr
);
940 qemu_put_be32(f
, so
->so_laddr
.s_addr
);
941 qemu_put_be16(f
, so
->so_fport
);
942 qemu_put_be16(f
, so
->so_lport
);
943 qemu_put_byte(f
, so
->so_iptos
);
944 qemu_put_byte(f
, so
->so_emu
);
945 qemu_put_byte(f
, so
->so_type
);
946 qemu_put_be32(f
, so
->so_state
);
947 slirp_sbuf_save(f
, &so
->so_rcv
);
948 slirp_sbuf_save(f
, &so
->so_snd
);
949 slirp_tcp_save(f
, so
->so_tcpcb
);
952 static void slirp_state_save(QEMUFile
*f
, void *opaque
)
954 struct ex_list
*ex_ptr
;
956 for (ex_ptr
= exec_list
; ex_ptr
; ex_ptr
= ex_ptr
->ex_next
)
957 if (ex_ptr
->ex_pty
== 3) {
959 so
= slirp_find_ctl_socket(ex_ptr
->ex_addr
, ntohs(ex_ptr
->ex_fport
));
963 qemu_put_byte(f
, 42);
964 slirp_socket_save(f
, so
);
969 static void slirp_tcp_load(QEMUFile
*f
, struct tcpcb
*tp
)
973 tp
->t_state
= qemu_get_sbe16(f
);
974 for (i
= 0; i
< TCPT_NTIMERS
; i
++)
975 tp
->t_timer
[i
] = qemu_get_sbe16(f
);
976 tp
->t_rxtshift
= qemu_get_sbe16(f
);
977 tp
->t_rxtcur
= qemu_get_sbe16(f
);
978 tp
->t_dupacks
= qemu_get_sbe16(f
);
979 tp
->t_maxseg
= qemu_get_be16(f
);
980 tp
->t_force
= qemu_get_sbyte(f
);
981 tp
->t_flags
= qemu_get_be16(f
);
982 tp
->snd_una
= qemu_get_be32(f
);
983 tp
->snd_nxt
= qemu_get_be32(f
);
984 tp
->snd_up
= qemu_get_be32(f
);
985 tp
->snd_wl1
= qemu_get_be32(f
);
986 tp
->snd_wl2
= qemu_get_be32(f
);
987 tp
->iss
= qemu_get_be32(f
);
988 tp
->snd_wnd
= qemu_get_be32(f
);
989 tp
->rcv_wnd
= qemu_get_be32(f
);
990 tp
->rcv_nxt
= qemu_get_be32(f
);
991 tp
->rcv_up
= qemu_get_be32(f
);
992 tp
->irs
= qemu_get_be32(f
);
993 tp
->rcv_adv
= qemu_get_be32(f
);
994 tp
->snd_max
= qemu_get_be32(f
);
995 tp
->snd_cwnd
= qemu_get_be32(f
);
996 tp
->snd_ssthresh
= qemu_get_be32(f
);
997 tp
->t_idle
= qemu_get_sbe16(f
);
998 tp
->t_rtt
= qemu_get_sbe16(f
);
999 tp
->t_rtseq
= qemu_get_be32(f
);
1000 tp
->t_srtt
= qemu_get_sbe16(f
);
1001 tp
->t_rttvar
= qemu_get_sbe16(f
);
1002 tp
->t_rttmin
= qemu_get_be16(f
);
1003 tp
->max_sndwnd
= qemu_get_be32(f
);
1004 tp
->t_oobflags
= qemu_get_byte(f
);
1005 tp
->t_iobc
= qemu_get_byte(f
);
1006 tp
->t_softerror
= qemu_get_sbe16(f
);
1007 tp
->snd_scale
= qemu_get_byte(f
);
1008 tp
->rcv_scale
= qemu_get_byte(f
);
1009 tp
->request_r_scale
= qemu_get_byte(f
);
1010 tp
->requested_s_scale
= qemu_get_byte(f
);
1011 tp
->ts_recent
= qemu_get_be32(f
);
1012 tp
->ts_recent_age
= qemu_get_be32(f
);
1013 tp
->last_ack_sent
= qemu_get_be32(f
);
1017 static int slirp_sbuf_load(QEMUFile
*f
, struct sbuf
*sbuf
)
1019 uint32_t off
, sb_cc
, sb_datalen
;
1021 sb_cc
= qemu_get_be32(f
);
1022 sb_datalen
= qemu_get_be32(f
);
1024 sbreserve(sbuf
, sb_datalen
);
1026 if (sbuf
->sb_datalen
!= sb_datalen
)
1029 sbuf
->sb_cc
= sb_cc
;
1031 off
= qemu_get_sbe32(f
);
1032 sbuf
->sb_wptr
= sbuf
->sb_data
+ off
;
1033 off
= qemu_get_sbe32(f
);
1034 sbuf
->sb_rptr
= sbuf
->sb_data
+ off
;
1035 qemu_get_buffer(f
, (unsigned char*)sbuf
->sb_data
, sbuf
->sb_datalen
);
1040 static int slirp_socket_load(QEMUFile
*f
, struct socket
*so
)
1042 if (tcp_attach(so
) < 0)
1045 so
->so_urgc
= qemu_get_be32(f
);
1046 so
->so_faddr
.s_addr
= qemu_get_be32(f
);
1047 so
->so_laddr
.s_addr
= qemu_get_be32(f
);
1048 so
->so_fport
= qemu_get_be16(f
);
1049 so
->so_lport
= qemu_get_be16(f
);
1050 so
->so_iptos
= qemu_get_byte(f
);
1051 so
->so_emu
= qemu_get_byte(f
);
1052 so
->so_type
= qemu_get_byte(f
);
1053 so
->so_state
= qemu_get_be32(f
);
1054 if (slirp_sbuf_load(f
, &so
->so_rcv
) < 0)
1056 if (slirp_sbuf_load(f
, &so
->so_snd
) < 0)
1058 slirp_tcp_load(f
, so
->so_tcpcb
);
1063 static int slirp_state_load(QEMUFile
*f
, void *opaque
, int version_id
)
1065 struct ex_list
*ex_ptr
;
1068 while ((r
= qemu_get_byte(f
))) {
1070 struct socket
*so
= socreate();
1075 ret
= slirp_socket_load(f
, so
);
1080 if ((so
->so_faddr
.s_addr
& vnetwork_mask
.s_addr
) !=
1081 vnetwork_addr
.s_addr
) {
1084 for (ex_ptr
= exec_list
; ex_ptr
; ex_ptr
= ex_ptr
->ex_next
) {
1085 if (ex_ptr
->ex_pty
== 3 &&
1086 so
->so_faddr
.s_addr
== ex_ptr
->ex_addr
.s_addr
&&
1087 so
->so_fport
== ex_ptr
->ex_fport
) {
1094 so
->extra
= (void *)ex_ptr
->ex_exec
;