mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 09:55:55 +00:00
slirp updates
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEErr90SPq5RTpFUjkOsKUb9YyRecUFAlkEwyQACgkQsKUb9YyR ecUMQA/8D2F0OXuphid1kyfpFv5aX1SxWJiQ1hdY9Zjt/OOL+5pC9xseoVMf5GOK 5y8JmoTMu/xzPHLWAZxAIU8cVulx3Ck4/KKgJk1zyxozZul2pAsDwZgG7AUzu8E/ bLzMtdvW8zaNYVnxWuqBtZ39AgqBAo9SRYY4dGUAInEVIWXpfzeIxk3tMUUlcp4g Xwig4rKIsxqkBFgMDwwsRuVU6aS3rRjwrTa5/uHe4Z0Aob5nxS7uFhSXUC8wd1vN KPjHppUhrG4bfXF8A5vMrSJ68frPLnxw43P7V3PMLnNG7ys5+NI3o8FkJKHL20dx Y3dL06YdIsOybE0S+8unzl6XjVKvtEOG0UEKRK53DcYUEBUSEA27UsChOaVwsO5S qaRIMFWhyDaB+0zpQMnHhEzC+8RDKoseBtkEwr0rWWlmEVtlDRoCtsniExK9BFUJ c4d2z5eDuYire1MSN3lx5tU/F5dJj5AwH83Wkk6+RKUfs2kpvcHklzIPtcN//ZG7 OyIxQfCfAOpNoifdumsh0xuq1Q2MhCmB1vEhfHcR4L2y+ifRUgQ80l88fvwhUMTG np/Yg/SNvBjTRjanor7YIhFYLcnev2NK9z/kLv2hJhOaIdFa9fh/KgW2VUFFnLG6 /HVN6/Zk5+4+DczXeh3EbMknHTBgz8N/UUnjCwHUSeJZnUr9PSo= =0pFA -----END PGP SIGNATURE----- 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: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
e619b14746
32
net/slirp.c
32
net/slirp.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,8 +152,9 @@ 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) {
|
||||
icmp_reflect(m);
|
||||
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;
|
||||
} else {
|
||||
|
|
|
@ -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
|
||||
|
|
506
slirp/slirp.c
506
slirp/slirp.c
|
@ -1133,107 +1133,294 @@ 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;
|
||||
tcp_template((struct tcpcb *)opaque);
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
|
||||
{
|
||||
uint32_t off;
|
||||
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_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);
|
||||
/* 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_socket_save(QEMUFile *f, struct socket *so)
|
||||
static int sbuf_tmp_post_load(void *opaque, int version)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
tmp->parent->sb_wptr = tmp->parent->sb_data + tmp->woff;
|
||||
tmp->parent->sb_rptr = tmp->parent->sb_data + tmp->roff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
}
|
||||
};
|
||||
|
||||
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()
|
||||
}
|
||||
};
|
||||
|
||||
static bool slirp_older_than_v4(void *opaque, int version_id)
|
||||
{
|
||||
return version_id < 4;
|
||||
}
|
||||
|
||||
static bool slirp_family_inet(void *opaque, int version_id)
|
||||
{
|
||||
union slirp_sockaddr *ssa = (union slirp_sockaddr *)opaque;
|
||||
return ssa->ss.ss_family == AF_INET;
|
||||
}
|
||||
|
||||
static int slirp_socket_pre_load(void *opaque)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
/* 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;
|
||||
|
||||
#define SS_FAMILY_MIG_IPV4 2 /* Linux, BSD, Win... */
|
||||
#define SS_FAMILY_MIG_IPV6 10 /* Linux */
|
||||
#define SS_FAMILY_MIG_OTHER 0xffff
|
||||
|
||||
static void ss_family_pre_save(void *opaque)
|
||||
{
|
||||
SS_FamilyTmpStruct *tss = opaque;
|
||||
|
||||
tss->portable_family = SS_FAMILY_MIG_OTHER;
|
||||
|
||||
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 ss_family_post_load(void *opaque, int version_id)
|
||||
{
|
||||
SS_FamilyTmpStruct *tss = opaque;
|
||||
|
||||
switch (tss->portable_family) {
|
||||
case SS_FAMILY_MIG_IPV4:
|
||||
tss->parent->ss.ss_family = AF_INET;
|
||||
break;
|
||||
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 save so_faddr and"
|
||||
" so_fport");
|
||||
error_report("invalid ss_family type %x", tss->portable_family);
|
||||
return -EINVAL;
|
||||
}
|
||||
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");
|
||||
}
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
|
||||
{
|
||||
int i;
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
|
@ -1249,142 +1436,13 @@ static void slirp_state_save(QEMUFile *f, void *opaque)
|
|||
continue;
|
||||
|
||||
qemu_put_byte(f, 42);
|
||||
slirp_socket_save(f, so);
|
||||
vmstate_save_state(f, &vmstate_slirp_socket, so, NULL);
|
||||
}
|
||||
qemu_put_byte(f, 0);
|
||||
|
||||
qemu_put_be16(f, slirp->ip_id);
|
||||
|
||||
slirp_bootp_save(f, slirp);
|
||||
vmstate_save_state(f, &vmstate_slirp, slirp, NULL);
|
||||
}
|
||||
|
||||
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, int version_id)
|
||||
{
|
||||
if (tcp_attach(so) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
error_report(
|
||||
"so_ffamily unknown, unable to restore so_laddr and so_lport");
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -48,7 +48,7 @@ struct tcpcb {
|
|||
short t_rxtcur; /* current retransmit value */
|
||||
short t_dupacks; /* consecutive dup acks recd */
|
||||
u_short t_maxseg; /* maximum segment size */
|
||||
char t_force; /* 1 if forcing out a byte */
|
||||
uint8_t t_force; /* 1 if forcing out a byte */
|
||||
u_short t_flags;
|
||||
#define TF_ACKNOW 0x0001 /* ack peer immediately */
|
||||
#define TF_DELACK 0x0002 /* ack, but try to delay it */
|
||||
|
@ -109,8 +109,8 @@ struct tcpcb {
|
|||
uint32_t max_sndwnd; /* largest window peer has offered */
|
||||
|
||||
/* out-of-band data */
|
||||
char t_oobflags; /* have some */
|
||||
char t_iobc; /* input character */
|
||||
uint8_t t_oobflags; /* have some */
|
||||
uint8_t t_iobc; /* input character */
|
||||
#define TCPOOB_HAVEDATA 0x01
|
||||
#define TCPOOB_HADDATA 0x02
|
||||
short t_softerror; /* possible error not yet reported */
|
||||
|
|
|
@ -70,7 +70,7 @@ static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas,
|
|||
|
||||
found:
|
||||
memset(spt, 0, sizeof(*spt));
|
||||
spt->client_addr = *srcsas;
|
||||
memcpy(&spt->client_addr, srcsas, sockaddr_size(srcsas));
|
||||
spt->fd = -1;
|
||||
spt->block_size = 512;
|
||||
spt->client_port = tp->udp.uh_sport;
|
||||
|
|
Loading…
Reference in a new issue