Commit e619b147 authored by Stefan Hajnoczi's avatar Stefan Hajnoczi
Browse files

Merge remote-tracking branch 'sthibault/tags/samuel-thibault' into staging



slirp updates

# gpg: Signature made Sat 29 Apr 2017 05:45:24 PM BST
# gpg:                using RSA key 0xB0A51BF58C9179C5
# gpg: Good signature from "Samuel Thibault <samuel.thibault@aquilenet.fr>"
# gpg:                 aka "Samuel Thibault <sthibault@debian.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@gnu.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@inria.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@labri.fr>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@ens-lyon.org>"
# gpg:                 aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>"
# Primary key fingerprint: 900C B024 B679 31D4 0F82  304B D017 8C76 7D06 9EE6
#      Subkey fingerprint: AEBF 7448 FAB9 453A 4552  390E B0A5 1BF5 8C91 79C5

* sthibault/tags/samuel-thibault:
  slirp: VMStatify remaining except for loop
  slirp: VMStatify socket level
  slirp: Common lhost/fhost union
  slirp: VMStatify sbuf
  slirp: VMState conversion; tcpcb
  slirp: fix pinging the virtual ipv4 DNS server
  slirp: tftp, copy sockaddr_size
  slirp/smb: Replace constant strings by glib string
  slirp: allow host port 0 for hostfwd

Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parents 38bb54f3 eb5d4f53
Loading
Loading
Loading
Loading
+18 −14
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ typedef struct SlirpState {
    Slirp *slirp;
    Notifier exit_notifier;
#ifndef _WIN32
    char smb_dir[128];
    gchar *smb_dir;
#endif
} SlirpState;

@@ -487,7 +487,7 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str,
        goto fail_syntax;
    }
    host_port = strtol(buf, &end, 0);
    if (*end != '\0' || host_port < 1 || host_port > 65535) {
    if (*end != '\0' || host_port < 0 || host_port > 65535) {
        goto fail_syntax;
    }

@@ -558,11 +558,10 @@ int net_slirp_redir(const char *redir_str)
/* automatic user mode samba server configuration */
static void slirp_smb_cleanup(SlirpState *s)
{
    char cmd[128];
    int ret;

    if (s->smb_dir[0] != '\0') {
        snprintf(cmd, sizeof(cmd), "rm -rf %s", s->smb_dir);
    if (s->smb_dir) {
        gchar *cmd = g_strdup_printf("rm -rf %s", s->smb_dir);
        ret = system(cmd);
        if (ret == -1 || !WIFEXITED(ret)) {
            error_report("'%s' failed.", cmd);
@@ -570,15 +569,17 @@ static void slirp_smb_cleanup(SlirpState *s)
            error_report("'%s' failed. Error code: %d",
                         cmd, WEXITSTATUS(ret));
        }
        s->smb_dir[0] = '\0';
        g_free(cmd);
        g_free(s->smb_dir);
        s->smb_dir = NULL;
    }
}

static int slirp_smb(SlirpState* s, const char *exported_dir,
                     struct in_addr vserver_addr)
{
    char smb_conf[128];
    char smb_cmdline[128];
    char *smb_conf;
    char *smb_cmdline;
    struct passwd *passwd;
    FILE *f;

@@ -600,19 +601,19 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
        return -1;
    }

    snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.XXXXXX");
    if (!mkdtemp(s->smb_dir)) {
        error_report("could not create samba server dir '%s'", s->smb_dir);
        s->smb_dir[0] = 0;
    s->smb_dir = g_dir_make_tmp("qemu-smb.XXXXXX", NULL);
    if (!s->smb_dir) {
        error_report("could not create samba server dir");
        return -1;
    }
    snprintf(smb_conf, sizeof(smb_conf), "%s/%s", s->smb_dir, "smb.conf");
    smb_conf = g_strdup_printf("%s/%s", s->smb_dir, "smb.conf");

    f = fopen(smb_conf, "w");
    if (!f) {
        slirp_smb_cleanup(s);
        error_report("could not create samba server configuration file '%s'",
                     smb_conf);
        g_free(smb_conf);
        return -1;
    }
    fprintf(f,
@@ -651,15 +652,18 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
            );
    fclose(f);

    snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -l %s -s %s",
    smb_cmdline = g_strdup_printf("%s -l %s -s %s",
             CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
    g_free(smb_conf);

    if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0 ||
        slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 445) < 0) {
        slirp_smb_cleanup(s);
        g_free(smb_cmdline);
        error_report("conflicting/invalid smbserver address");
        return -1;
    }
    g_free(smb_cmdline);
    return 0;
}

+3 −2
Original line number Diff line number Diff line
@@ -152,7 +152,8 @@ icmp_input(struct mbuf *m, int hlen)
  switch (icp->icmp_type) {
  case ICMP_ECHO:
    ip->ip_len += hlen;	             /* since ip_input subtracts this */
    if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
    if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr ||
        ip->ip_dst.s_addr == slirp->vnameserver_addr.s_addr) {
        icmp_reflect(m);
    } else if (slirp->restricted) {
        goto freeit;
+2 −2
Original line number Diff line number Diff line
@@ -12,8 +12,8 @@
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)

struct sbuf {
	u_int	sb_cc;		/* actual chars in buffer */
	u_int	sb_datalen;	/* Length of data  */
	uint32_t sb_cc;		/* actual chars in buffer */
	uint32_t sb_datalen;	/* Length of data  */
	char	*sb_wptr;	/* write pointer. points to where the next
				 * bytes should be written in the sbuf */
	char	*sb_rptr;	/* read pointer. points to where the next
+272 −222
Original line number Diff line number Diff line
@@ -1133,259 +1133,317 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
        tcp_output(sototcpcb(so));
}

static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
static int slirp_tcp_post_load(void *opaque, int version)
{
    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;
    tcp_template((struct tcpcb *)opaque);

    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);
    return 0;
}

static void slirp_socket_save(QEMUFile *f, struct socket *so)
{
    qemu_put_be32(f, so->so_urgc);
    qemu_put_be16(f, so->so_ffamily);
    switch (so->so_ffamily) {
    case AF_INET:
        qemu_put_be32(f, so->so_faddr.s_addr);
        qemu_put_be16(f, so->so_fport);
        break;
    default:
        error_report("so_ffamily unknown, unable to save so_faddr and"
                     " so_fport");
    }
    qemu_put_be16(f, so->so_lfamily);
    switch (so->so_lfamily) {
    case AF_INET:
        qemu_put_be32(f, so->so_laddr.s_addr);
        qemu_put_be16(f, so->so_lport);
        break;
    default:
        error_report("so_ffamily unknown, unable to save so_laddr and"
                     " so_lport");
static const VMStateDescription vmstate_slirp_tcp = {
    .name = "slirp-tcp",
    .version_id = 0,
    .post_load = slirp_tcp_post_load,
    .fields = (VMStateField[]) {
        VMSTATE_INT16(t_state, struct tcpcb),
        VMSTATE_INT16_ARRAY(t_timer, struct tcpcb, TCPT_NTIMERS),
        VMSTATE_INT16(t_rxtshift, struct tcpcb),
        VMSTATE_INT16(t_rxtcur, struct tcpcb),
        VMSTATE_INT16(t_dupacks, struct tcpcb),
        VMSTATE_UINT16(t_maxseg, struct tcpcb),
        VMSTATE_UINT8(t_force, struct tcpcb),
        VMSTATE_UINT16(t_flags, struct tcpcb),
        VMSTATE_UINT32(snd_una, struct tcpcb),
        VMSTATE_UINT32(snd_nxt, struct tcpcb),
        VMSTATE_UINT32(snd_up, struct tcpcb),
        VMSTATE_UINT32(snd_wl1, struct tcpcb),
        VMSTATE_UINT32(snd_wl2, struct tcpcb),
        VMSTATE_UINT32(iss, struct tcpcb),
        VMSTATE_UINT32(snd_wnd, struct tcpcb),
        VMSTATE_UINT32(rcv_wnd, struct tcpcb),
        VMSTATE_UINT32(rcv_nxt, struct tcpcb),
        VMSTATE_UINT32(rcv_up, struct tcpcb),
        VMSTATE_UINT32(irs, struct tcpcb),
        VMSTATE_UINT32(rcv_adv, struct tcpcb),
        VMSTATE_UINT32(snd_max, struct tcpcb),
        VMSTATE_UINT32(snd_cwnd, struct tcpcb),
        VMSTATE_UINT32(snd_ssthresh, struct tcpcb),
        VMSTATE_INT16(t_idle, struct tcpcb),
        VMSTATE_INT16(t_rtt, struct tcpcb),
        VMSTATE_UINT32(t_rtseq, struct tcpcb),
        VMSTATE_INT16(t_srtt, struct tcpcb),
        VMSTATE_INT16(t_rttvar, struct tcpcb),
        VMSTATE_UINT16(t_rttmin, struct tcpcb),
        VMSTATE_UINT32(max_sndwnd, struct tcpcb),
        VMSTATE_UINT8(t_oobflags, struct tcpcb),
        VMSTATE_UINT8(t_iobc, struct tcpcb),
        VMSTATE_INT16(t_softerror, struct tcpcb),
        VMSTATE_UINT8(snd_scale, struct tcpcb),
        VMSTATE_UINT8(rcv_scale, struct tcpcb),
        VMSTATE_UINT8(request_r_scale, struct tcpcb),
        VMSTATE_UINT8(requested_s_scale, struct tcpcb),
        VMSTATE_UINT32(ts_recent, struct tcpcb),
        VMSTATE_UINT32(ts_recent_age, struct tcpcb),
        VMSTATE_UINT32(last_ack_sent, struct tcpcb),
        VMSTATE_END_OF_LIST()
    }
    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);
};

/* The sbuf has a pair of pointers that are migrated as offsets;
 * we calculate the offsets and restore the pointers using
 * pre_save/post_load on a tmp structure.
 */
struct sbuf_tmp {
    struct sbuf *parent;
    uint32_t roff, woff;
};

static void sbuf_tmp_pre_save(void *opaque)
{
    struct sbuf_tmp *tmp = opaque;
    tmp->woff = tmp->parent->sb_wptr - tmp->parent->sb_data;
    tmp->roff = tmp->parent->sb_rptr - tmp->parent->sb_data;
}

static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
static int sbuf_tmp_post_load(void *opaque, int version)
{
    int i;
    struct sbuf_tmp *tmp = opaque;
    uint32_t requested_len = tmp->parent->sb_datalen;

    /* Allocate the buffer space used by the field after the tmp */
    sbreserve(tmp->parent, tmp->parent->sb_datalen);

    for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
        qemu_put_be16(f, slirp->bootp_clients[i].allocated);
        qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
    if (tmp->parent->sb_datalen != requested_len) {
        return -ENOMEM;
    }
    if (tmp->woff >= requested_len ||
        tmp->roff >= requested_len) {
        error_report("invalid sbuf offsets r/w=%u/%u len=%u",
                     tmp->roff, tmp->woff, requested_len);
        return -EINVAL;
    }

static void slirp_state_save(QEMUFile *f, void *opaque)
{
    Slirp *slirp = opaque;
    struct ex_list *ex_ptr;
    tmp->parent->sb_wptr = tmp->parent->sb_data + tmp->woff;
    tmp->parent->sb_rptr = tmp->parent->sb_data + tmp->roff;

    for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
        if (ex_ptr->ex_pty == 3) {
            struct socket *so;
            so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
                                       ntohs(ex_ptr->ex_fport));
            if (!so)
                continue;
    return 0;
}

            qemu_put_byte(f, 42);
            slirp_socket_save(f, so);

static const VMStateDescription vmstate_slirp_sbuf_tmp = {
    .name = "slirp-sbuf-tmp",
    .post_load = sbuf_tmp_post_load,
    .pre_save  = sbuf_tmp_pre_save,
    .version_id = 0,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(woff, struct sbuf_tmp),
        VMSTATE_UINT32(roff, struct sbuf_tmp),
        VMSTATE_END_OF_LIST()
    }
    qemu_put_byte(f, 0);
};

    qemu_put_be16(f, slirp->ip_id);
static const VMStateDescription vmstate_slirp_sbuf = {
    .name = "slirp-sbuf",
    .version_id = 0,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(sb_cc, struct sbuf),
        VMSTATE_UINT32(sb_datalen, struct sbuf),
        VMSTATE_WITH_TMP(struct sbuf, struct sbuf_tmp, vmstate_slirp_sbuf_tmp),
        VMSTATE_VBUFFER_UINT32(sb_data, struct sbuf, 0, NULL, sb_datalen),
        VMSTATE_END_OF_LIST()
    }
};

    slirp_bootp_save(f, slirp);
static bool slirp_older_than_v4(void *opaque, int version_id)
{
    return version_id < 4;
}

static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
static bool slirp_family_inet(void *opaque, int version_id)
{
    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)
    union slirp_sockaddr *ssa = (union slirp_sockaddr *)opaque;
    return ssa->ss.ss_family == AF_INET;
}

static int slirp_socket_pre_load(void *opaque)
{
    uint32_t off, sb_cc, sb_datalen;
    struct socket *so = opaque;
    if (tcp_attach(so) < 0) {
        return -ENOMEM;
    }
    /* Older versions don't load these fields */
    so->so_ffamily = AF_INET;
    so->so_lfamily = AF_INET;
    return 0;
}

    sb_cc = qemu_get_be32(f);
    sb_datalen = qemu_get_be32(f);
#ifndef _WIN32
#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_UINT32_TEST(f, s, t)
#else
/* Win uses u_long rather than uint32_t - but it's still 32bits long */
#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_SINGLE_TEST(f, s, t, 0, \
                                       vmstate_info_uint32, u_long)
#endif

    sbreserve(sbuf, sb_datalen);
/* The OS provided ss_family field isn't that portable; it's size
 * and type varies (16/8 bit, signed, unsigned)
 * and the values it contains aren't fully portable.
 */
typedef struct SS_FamilyTmpStruct {
    union slirp_sockaddr    *parent;
    uint16_t                 portable_family;
} SS_FamilyTmpStruct;

    if (sbuf->sb_datalen != sb_datalen)
        return -ENOMEM;
#define SS_FAMILY_MIG_IPV4   2  /* Linux, BSD, Win... */
#define SS_FAMILY_MIG_IPV6  10  /* Linux */
#define SS_FAMILY_MIG_OTHER 0xffff

    sbuf->sb_cc = sb_cc;
static void ss_family_pre_save(void *opaque)
{
    SS_FamilyTmpStruct *tss = opaque;

    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);
    tss->portable_family = SS_FAMILY_MIG_OTHER;

    return 0;
    if (tss->parent->ss.ss_family == AF_INET) {
        tss->portable_family = SS_FAMILY_MIG_IPV4;
    } else if (tss->parent->ss.ss_family == AF_INET6) {
        tss->portable_family = SS_FAMILY_MIG_IPV6;
    }
}

static int slirp_socket_load(QEMUFile *f, struct socket *so, int version_id)
static int ss_family_post_load(void *opaque, int version_id)
{
    if (tcp_attach(so) < 0)
        return -ENOMEM;
    SS_FamilyTmpStruct *tss = opaque;

    so->so_urgc = qemu_get_be32(f);
    if (version_id <= 3) {
        so->so_ffamily = AF_INET;
        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);
    } else {
        so->so_ffamily = qemu_get_be16(f);
        switch (so->so_ffamily) {
        case AF_INET:
            so->so_faddr.s_addr = qemu_get_be32(f);
            so->so_fport = qemu_get_be16(f);
    switch (tss->portable_family) {
    case SS_FAMILY_MIG_IPV4:
        tss->parent->ss.ss_family = AF_INET;
        break;
        default:
            error_report(
                "so_ffamily unknown, unable to restore so_faddr and so_lport");
        }
        so->so_lfamily = qemu_get_be16(f);
        switch (so->so_lfamily) {
        case AF_INET:
            so->so_laddr.s_addr = qemu_get_be32(f);
            so->so_lport = qemu_get_be16(f);
    case SS_FAMILY_MIG_IPV6:
    case 23: /* compatibility: AF_INET6 from mingw */
    case 28: /* compatibility: AF_INET6 from FreeBSD sys/socket.h */
        tss->parent->ss.ss_family = AF_INET6;
        break;
    default:
            error_report(
                "so_ffamily unknown, unable to restore so_laddr and so_lport");
        }
        error_report("invalid ss_family type %x", tss->portable_family);
        return -EINVAL;
    }
    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 void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
static const VMStateDescription vmstate_slirp_ss_family = {
    .name = "slirp-socket-addr/ss_family",
    .pre_save  = ss_family_pre_save,
    .post_load = ss_family_post_load,
    .fields = (VMStateField[]) {
        VMSTATE_UINT16(portable_family, SS_FamilyTmpStruct),
        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_slirp_socket_addr = {
    .name = "slirp-socket-addr",
    .version_id = 4,
    .fields = (VMStateField[]) {
        VMSTATE_WITH_TMP(union slirp_sockaddr, SS_FamilyTmpStruct,
                            vmstate_slirp_ss_family),
        VMSTATE_SIN4_ADDR(sin.sin_addr.s_addr, union slirp_sockaddr,
                            slirp_family_inet),
        VMSTATE_UINT16_TEST(sin.sin_port, union slirp_sockaddr,
                            slirp_family_inet),

#if 0
        /* Untested: Needs checking by someone with IPv6 test */
        VMSTATE_BUFFER_TEST(sin6.sin6_addr, union slirp_sockaddr,
                            slirp_family_inet6),
        VMSTATE_UINT16_TEST(sin6.sin6_port, union slirp_sockaddr,
                            slirp_family_inet6),
        VMSTATE_UINT32_TEST(sin6.sin6_flowinfo, union slirp_sockaddr,
                            slirp_family_inet6),
        VMSTATE_UINT32_TEST(sin6.sin6_scope_id, union slirp_sockaddr,
                            slirp_family_inet6),
#endif

        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_slirp_socket = {
    .name = "slirp-socket",
    .version_id = 4,
    .pre_load = slirp_socket_pre_load,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(so_urgc, struct socket),
        /* Pre-v4 versions */
        VMSTATE_SIN4_ADDR(so_faddr.s_addr, struct socket,
                            slirp_older_than_v4),
        VMSTATE_SIN4_ADDR(so_laddr.s_addr, struct socket,
                            slirp_older_than_v4),
        VMSTATE_UINT16_TEST(so_fport, struct socket, slirp_older_than_v4),
        VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4),
        /* v4 and newer */
        VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr,
                       union slirp_sockaddr),
        VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr,
                       union slirp_sockaddr),

        VMSTATE_UINT8(so_iptos, struct socket),
        VMSTATE_UINT8(so_emu, struct socket),
        VMSTATE_UINT8(so_type, struct socket),
        VMSTATE_INT32(so_state, struct socket),
        VMSTATE_STRUCT(so_rcv, struct socket, 0, vmstate_slirp_sbuf,
                       struct sbuf),
        VMSTATE_STRUCT(so_snd, struct socket, 0, vmstate_slirp_sbuf,
                       struct sbuf),
        VMSTATE_STRUCT_POINTER(so_tcpcb, struct socket, vmstate_slirp_tcp,
                       struct tcpcb),
        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_slirp_bootp_client = {
    .name = "slirp_bootpclient",
    .fields = (VMStateField[]) {
        VMSTATE_UINT16(allocated, BOOTPClient),
        VMSTATE_BUFFER(macaddr, BOOTPClient),
        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_slirp = {
    .name = "slirp",
    .version_id = 4,
    .fields = (VMStateField[]) {
        VMSTATE_UINT16_V(ip_id, Slirp, 2),
        VMSTATE_STRUCT_ARRAY(bootp_clients, Slirp, NB_BOOTP_CLIENTS, 3,
                             vmstate_slirp_bootp_client, BOOTPClient),
        VMSTATE_END_OF_LIST()
    }
};

static void slirp_state_save(QEMUFile *f, void *opaque)
{
    int i;
    Slirp *slirp = opaque;
    struct ex_list *ex_ptr;

    for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
        if (ex_ptr->ex_pty == 3) {
            struct socket *so;
            so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
                                       ntohs(ex_ptr->ex_fport));
            if (!so)
                continue;

    for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
        slirp->bootp_clients[i].allocated = qemu_get_be16(f);
        qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
            qemu_put_byte(f, 42);
            vmstate_save_state(f, &vmstate_slirp_socket, so, NULL);
        }
    qemu_put_byte(f, 0);

    vmstate_save_state(f, &vmstate_slirp, slirp, NULL);
}


static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
{
    Slirp *slirp = opaque;
@@ -1398,7 +1456,7 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
        if (!so)
            return -ENOMEM;

        ret = slirp_socket_load(f, so, version_id);
        ret = vmstate_load_state(f, &vmstate_slirp_socket, so, version_id);

        if (ret < 0)
            return ret;
@@ -1420,13 +1478,5 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
        so->extra = (void *)ex_ptr->ex_exec;
    }

    if (version_id >= 2) {
        slirp->ip_id = qemu_get_be16(f);
    }

    if (version_id >= 3) {
        slirp_bootp_load(f, slirp);
    }

    return 0;
    return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);
}
+11 −13
Original line number Diff line number Diff line
@@ -15,6 +15,12 @@
 * Our socket structure
 */

union slirp_sockaddr {
    struct sockaddr_storage ss;
    struct sockaddr_in sin;
    struct sockaddr_in6 sin6;
};

struct socket {
  struct socket *so_next,*so_prev;      /* For a linked list of sockets */

@@ -30,23 +36,15 @@ struct socket {
				    * PING reply's */
  struct tcpiphdr *so_ti;	   /* Pointer to the original ti within
				    * so_mconn, for non-blocking connections */
  int so_urgc;
  union {   /* foreign host */
      struct sockaddr_storage ss;
      struct sockaddr_in sin;
      struct sockaddr_in6 sin6;
  } fhost;
  uint32_t      so_urgc;
  union slirp_sockaddr fhost;      /* Foreign host */
#define so_faddr fhost.sin.sin_addr
#define so_fport fhost.sin.sin_port
#define so_faddr6 fhost.sin6.sin6_addr
#define so_fport6 fhost.sin6.sin6_port
#define so_ffamily fhost.ss.ss_family

  union {   /* local host */
      struct sockaddr_storage ss;
      struct sockaddr_in sin;
      struct sockaddr_in6 sin6;
  } lhost;
  union slirp_sockaddr lhost;      /* Local host */
#define so_laddr lhost.sin.sin_addr
#define so_lport lhost.sin.sin_port
#define so_laddr6 lhost.sin6.sin6_addr
@@ -56,8 +54,8 @@ struct socket {
  uint8_t	so_iptos;	/* Type of service */
  uint8_t	so_emu;		/* Is the socket emulated? */

  u_char	so_type;		/* Type of socket, UDP or TCP */
  int	so_state;		/* internal state flags SS_*, below */
  uint8_t       so_type;        /* Type of socket, UDP or TCP */
  int32_t       so_state;       /* internal state flags SS_*, below */

  struct 	tcpcb *so_tcpcb;	/* pointer to TCP protocol control block */
  u_int	so_expire;		/* When the socket will expire */
Loading