aboutsummaryrefslogtreecommitdiff
path: root/slirp/slirp.c
diff options
context:
space:
mode:
Diffstat (limited to 'slirp/slirp.c')
-rw-r--r--slirp/slirp.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/slirp/slirp.c b/slirp/slirp.c
index ce4a1b714c..c1361ab108 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -23,6 +23,7 @@
*/
#include "qemu-common.h"
#include "slirp.h"
+#include "hw/hw.h"
/* host address */
struct in_addr our_addr;
@@ -166,6 +167,9 @@ static void slirp_cleanup(void)
}
#endif
+static void slirp_state_save(QEMUFile *f, void *opaque);
+static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
+
void slirp_init(int restrict, char *special_ip)
{
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
@@ -201,6 +205,7 @@ void slirp_init(int restrict, char *special_ip)
inet_aton(slirp_special_ip, &special_addr);
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
getouraddr();
+ register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
}
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -809,3 +814,225 @@ void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
if (ret > 0)
tcp_output(sototcpcb(so));
}
+
+static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
+{
+ int i;
+
+ qemu_put_sbe16(f, tp->t_state);
+ for (i = 0; i < TCPT_NTIMERS; i++)
+ qemu_put_sbe16(f, tp->t_timer[i]);
+ qemu_put_sbe16(f, tp->t_rxtshift);
+ qemu_put_sbe16(f, tp->t_rxtcur);
+ qemu_put_sbe16(f, tp->t_dupacks);
+ qemu_put_be16(f, tp->t_maxseg);
+ qemu_put_sbyte(f, tp->t_force);
+ qemu_put_be16(f, tp->t_flags);
+ qemu_put_be32(f, tp->snd_una);
+ qemu_put_be32(f, tp->snd_nxt);
+ qemu_put_be32(f, tp->snd_up);
+ qemu_put_be32(f, tp->snd_wl1);
+ qemu_put_be32(f, tp->snd_wl2);
+ qemu_put_be32(f, tp->iss);
+ qemu_put_be32(f, tp->snd_wnd);
+ qemu_put_be32(f, tp->rcv_wnd);
+ qemu_put_be32(f, tp->rcv_nxt);
+ qemu_put_be32(f, tp->rcv_up);
+ qemu_put_be32(f, tp->irs);
+ qemu_put_be32(f, tp->rcv_adv);
+ qemu_put_be32(f, tp->snd_max);
+ qemu_put_be32(f, tp->snd_cwnd);
+ qemu_put_be32(f, tp->snd_ssthresh);
+ qemu_put_sbe16(f, tp->t_idle);
+ qemu_put_sbe16(f, tp->t_rtt);
+ qemu_put_be32(f, tp->t_rtseq);
+ qemu_put_sbe16(f, tp->t_srtt);
+ qemu_put_sbe16(f, tp->t_rttvar);
+ qemu_put_be16(f, tp->t_rttmin);
+ qemu_put_be32(f, tp->max_sndwnd);
+ qemu_put_byte(f, tp->t_oobflags);
+ qemu_put_byte(f, tp->t_iobc);
+ qemu_put_sbe16(f, tp->t_softerror);
+ qemu_put_byte(f, tp->snd_scale);
+ qemu_put_byte(f, tp->rcv_scale);
+ qemu_put_byte(f, tp->request_r_scale);
+ qemu_put_byte(f, tp->requested_s_scale);
+ qemu_put_be32(f, tp->ts_recent);
+ qemu_put_be32(f, tp->ts_recent_age);
+ qemu_put_be32(f, tp->last_ack_sent);
+}
+
+static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
+{
+ uint32_t off;
+
+ qemu_put_be32(f, sbuf->sb_cc);
+ qemu_put_be32(f, sbuf->sb_datalen);
+ off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
+ qemu_put_sbe32(f, off);
+ off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
+ qemu_put_sbe32(f, off);
+ qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
+}
+
+static void slirp_socket_save(QEMUFile *f, struct socket *so)
+{
+ qemu_put_be32(f, so->so_urgc);
+ qemu_put_be32(f, so->so_faddr.s_addr);
+ qemu_put_be32(f, so->so_laddr.s_addr);
+ qemu_put_be16(f, so->so_fport);
+ qemu_put_be16(f, so->so_lport);
+ qemu_put_byte(f, so->so_iptos);
+ qemu_put_byte(f, so->so_emu);
+ qemu_put_byte(f, so->so_type);
+ qemu_put_be32(f, so->so_state);
+ slirp_sbuf_save(f, &so->so_rcv);
+ slirp_sbuf_save(f, &so->so_snd);
+ slirp_tcp_save(f, so->so_tcpcb);
+}
+
+static void slirp_state_save(QEMUFile *f, void *opaque)
+{
+ struct ex_list *ex_ptr;
+
+ for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+ if (ex_ptr->ex_pty == 3) {
+ struct socket *so;
+ so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
+ if (!so)
+ continue;
+
+ qemu_put_byte(f, 42);
+ slirp_socket_save(f, so);
+ }
+ qemu_put_byte(f, 0);
+}
+
+static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
+{
+ int i;
+
+ tp->t_state = qemu_get_sbe16(f);
+ for (i = 0; i < TCPT_NTIMERS; i++)
+ tp->t_timer[i] = qemu_get_sbe16(f);
+ tp->t_rxtshift = qemu_get_sbe16(f);
+ tp->t_rxtcur = qemu_get_sbe16(f);
+ tp->t_dupacks = qemu_get_sbe16(f);
+ tp->t_maxseg = qemu_get_be16(f);
+ tp->t_force = qemu_get_sbyte(f);
+ tp->t_flags = qemu_get_be16(f);
+ tp->snd_una = qemu_get_be32(f);
+ tp->snd_nxt = qemu_get_be32(f);
+ tp->snd_up = qemu_get_be32(f);
+ tp->snd_wl1 = qemu_get_be32(f);
+ tp->snd_wl2 = qemu_get_be32(f);
+ tp->iss = qemu_get_be32(f);
+ tp->snd_wnd = qemu_get_be32(f);
+ tp->rcv_wnd = qemu_get_be32(f);
+ tp->rcv_nxt = qemu_get_be32(f);
+ tp->rcv_up = qemu_get_be32(f);
+ tp->irs = qemu_get_be32(f);
+ tp->rcv_adv = qemu_get_be32(f);
+ tp->snd_max = qemu_get_be32(f);
+ tp->snd_cwnd = qemu_get_be32(f);
+ tp->snd_ssthresh = qemu_get_be32(f);
+ tp->t_idle = qemu_get_sbe16(f);
+ tp->t_rtt = qemu_get_sbe16(f);
+ tp->t_rtseq = qemu_get_be32(f);
+ tp->t_srtt = qemu_get_sbe16(f);
+ tp->t_rttvar = qemu_get_sbe16(f);
+ tp->t_rttmin = qemu_get_be16(f);
+ tp->max_sndwnd = qemu_get_be32(f);
+ tp->t_oobflags = qemu_get_byte(f);
+ tp->t_iobc = qemu_get_byte(f);
+ tp->t_softerror = qemu_get_sbe16(f);
+ tp->snd_scale = qemu_get_byte(f);
+ tp->rcv_scale = qemu_get_byte(f);
+ tp->request_r_scale = qemu_get_byte(f);
+ tp->requested_s_scale = qemu_get_byte(f);
+ tp->ts_recent = qemu_get_be32(f);
+ tp->ts_recent_age = qemu_get_be32(f);
+ tp->last_ack_sent = qemu_get_be32(f);
+ tcp_template(tp);
+}
+
+static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
+{
+ uint32_t off, sb_cc, sb_datalen;
+
+ sb_cc = qemu_get_be32(f);
+ sb_datalen = qemu_get_be32(f);
+
+ sbreserve(sbuf, sb_datalen);
+
+ if (sbuf->sb_datalen != sb_datalen)
+ return -ENOMEM;
+
+ sbuf->sb_cc = sb_cc;
+
+ off = qemu_get_sbe32(f);
+ sbuf->sb_wptr = sbuf->sb_data + off;
+ off = qemu_get_sbe32(f);
+ sbuf->sb_rptr = sbuf->sb_data + off;
+ qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
+
+ return 0;
+}
+
+static int slirp_socket_load(QEMUFile *f, struct socket *so)
+{
+ if (tcp_attach(so) < 0)
+ return -ENOMEM;
+
+ so->so_urgc = qemu_get_be32(f);
+ so->so_faddr.s_addr = qemu_get_be32(f);
+ so->so_laddr.s_addr = qemu_get_be32(f);
+ so->so_fport = qemu_get_be16(f);
+ so->so_lport = qemu_get_be16(f);
+ so->so_iptos = qemu_get_byte(f);
+ so->so_emu = qemu_get_byte(f);
+ so->so_type = qemu_get_byte(f);
+ so->so_state = qemu_get_be32(f);
+ if (slirp_sbuf_load(f, &so->so_rcv) < 0)
+ return -ENOMEM;
+ if (slirp_sbuf_load(f, &so->so_snd) < 0)
+ return -ENOMEM;
+ slirp_tcp_load(f, so->so_tcpcb);
+
+ return 0;
+}
+
+static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
+{
+ struct ex_list *ex_ptr;
+ int r;
+
+ while ((r = qemu_get_byte(f))) {
+ int ret;
+ struct socket *so = socreate();
+
+ if (!so)
+ return -ENOMEM;
+
+ ret = slirp_socket_load(f, so);
+
+ if (ret < 0)
+ return ret;
+
+ if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr)
+ return -EINVAL;
+
+ for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+ if (ex_ptr->ex_pty == 3 &&
+ (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr &&
+ so->so_fport == ex_ptr->ex_fport)
+ break;
+
+ if (!ex_ptr)
+ return -EINVAL;
+
+ so->extra = ex_ptr->ex_exec;
+ }
+
+ return 0;
+}