mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 01:43:39 +00:00
slirp: Allocate/free stack instance dynamically
Allocate the internal slirp state dynamically and provide and call slirp_cleanup to properly release it after use. This patch finally unbreaks slirp release and re-instantiation via host_net_* monitor commands. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
9f8bd0421d
commit
ad0d8c4c32
246
net.c
246
net.c
|
@ -729,11 +729,13 @@ static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t siz
|
|||
return size;
|
||||
}
|
||||
|
||||
static int slirp_in_use;
|
||||
|
||||
static void net_slirp_cleanup(VLANClientState *vc)
|
||||
{
|
||||
slirp_in_use = 0;
|
||||
SlirpState *s = vc->opaque;
|
||||
|
||||
slirp_cleanup(s->slirp);
|
||||
slirp_state = NULL;
|
||||
qemu_free(s);
|
||||
}
|
||||
|
||||
static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
|
||||
|
@ -744,137 +746,129 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
|
|||
const char *vnameserver, const char *smb_export,
|
||||
const char *vsmbserver)
|
||||
{
|
||||
SlirpState *s = slirp_state;
|
||||
/* default settings according to historic slirp */
|
||||
struct in_addr net = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
|
||||
struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
|
||||
struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
|
||||
struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
|
||||
struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
|
||||
#ifndef _WIN32
|
||||
struct in_addr smbsrv = { .s_addr = 0 };
|
||||
#endif
|
||||
SlirpState *s;
|
||||
char buf[20];
|
||||
uint32_t addr;
|
||||
int shift;
|
||||
char *end;
|
||||
|
||||
if (slirp_in_use) {
|
||||
/* slirp only supports a single instance so far */
|
||||
if (!tftp_export) {
|
||||
tftp_export = legacy_tftp_prefix;
|
||||
}
|
||||
if (!bootfile) {
|
||||
bootfile = legacy_bootp_filename;
|
||||
}
|
||||
|
||||
if (vnetwork) {
|
||||
if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
|
||||
if (!inet_aton(vnetwork, &net)) {
|
||||
return -1;
|
||||
}
|
||||
addr = ntohl(net.s_addr);
|
||||
if (!(addr & 0x80000000)) {
|
||||
mask.s_addr = htonl(0xff000000); /* class A */
|
||||
} else if ((addr & 0xfff00000) == 0xac100000) {
|
||||
mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
|
||||
} else if ((addr & 0xc0000000) == 0x80000000) {
|
||||
mask.s_addr = htonl(0xffff0000); /* class B */
|
||||
} else if ((addr & 0xffff0000) == 0xc0a80000) {
|
||||
mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
|
||||
} else if ((addr & 0xffff0000) == 0xc6120000) {
|
||||
mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
|
||||
} else if ((addr & 0xe0000000) == 0xe0000000) {
|
||||
mask.s_addr = htonl(0xffffff00); /* class C */
|
||||
} else {
|
||||
mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
|
||||
}
|
||||
} else {
|
||||
if (!inet_aton(buf, &net)) {
|
||||
return -1;
|
||||
}
|
||||
shift = strtol(vnetwork, &end, 10);
|
||||
if (*end != '\0') {
|
||||
if (!inet_aton(vnetwork, &mask)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (shift < 4 || shift > 32) {
|
||||
return -1;
|
||||
} else {
|
||||
mask.s_addr = htonl(0xffffffff << (32 - shift));
|
||||
}
|
||||
}
|
||||
net.s_addr &= mask.s_addr;
|
||||
host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
|
||||
dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
|
||||
dns.s_addr = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
|
||||
}
|
||||
|
||||
if (vhost && !inet_aton(vhost, &host)) {
|
||||
return -1;
|
||||
}
|
||||
if (!s) {
|
||||
/* default settings according to historic slirp */
|
||||
struct in_addr net = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
|
||||
struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
|
||||
struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
|
||||
struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
|
||||
struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
|
||||
#ifndef _WIN32
|
||||
struct in_addr smbsrv = { .s_addr = 0 };
|
||||
#endif
|
||||
char buf[20];
|
||||
uint32_t addr;
|
||||
int shift;
|
||||
char *end;
|
||||
|
||||
if (!tftp_export) {
|
||||
tftp_export = legacy_tftp_prefix;
|
||||
}
|
||||
if (!bootfile) {
|
||||
bootfile = legacy_bootp_filename;
|
||||
}
|
||||
|
||||
if (vnetwork) {
|
||||
if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
|
||||
if (!inet_aton(vnetwork, &net)) {
|
||||
return -1;
|
||||
}
|
||||
addr = ntohl(net.s_addr);
|
||||
if (!(addr & 0x80000000)) {
|
||||
mask.s_addr = htonl(0xff000000); /* class A */
|
||||
} else if ((addr & 0xfff00000) == 0xac100000) {
|
||||
mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
|
||||
} else if ((addr & 0xc0000000) == 0x80000000) {
|
||||
mask.s_addr = htonl(0xffff0000); /* class B */
|
||||
} else if ((addr & 0xffff0000) == 0xc0a80000) {
|
||||
mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
|
||||
} else if ((addr & 0xffff0000) == 0xc6120000) {
|
||||
mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
|
||||
} else if ((addr & 0xe0000000) == 0xe0000000) {
|
||||
mask.s_addr = htonl(0xffffff00); /* class C */
|
||||
} else {
|
||||
mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
|
||||
}
|
||||
} else {
|
||||
if (!inet_aton(buf, &net)) {
|
||||
return -1;
|
||||
}
|
||||
shift = strtol(vnetwork, &end, 10);
|
||||
if (*end != '\0') {
|
||||
if (!inet_aton(vnetwork, &mask)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (shift < 4 || shift > 32) {
|
||||
return -1;
|
||||
} else {
|
||||
mask.s_addr = htonl(0xffffffff << (32 - shift));
|
||||
}
|
||||
}
|
||||
net.s_addr &= mask.s_addr;
|
||||
host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
|
||||
dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
|
||||
dns.s_addr = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
|
||||
}
|
||||
|
||||
if (vhost && !inet_aton(vhost, &host)) {
|
||||
return -1;
|
||||
}
|
||||
if ((host.s_addr & mask.s_addr) != net.s_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
|
||||
return -1;
|
||||
}
|
||||
if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
|
||||
dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vnameserver && !inet_aton(vnameserver, &dns)) {
|
||||
return -1;
|
||||
}
|
||||
if ((dns.s_addr & mask.s_addr) != net.s_addr ||
|
||||
dns.s_addr == host.s_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
s = qemu_mallocz(sizeof(SlirpState));
|
||||
s->slirp = slirp_init(restricted, net, mask, host, vhostname,
|
||||
tftp_export, bootfile, dhcp, dns, s);
|
||||
slirp_state = s;
|
||||
|
||||
while (slirp_configs) {
|
||||
struct slirp_config_str *config = slirp_configs;
|
||||
|
||||
if (config->flags & SLIRP_CFG_HOSTFWD) {
|
||||
slirp_hostfwd(s, mon, config->str,
|
||||
config->flags & SLIRP_CFG_LEGACY);
|
||||
} else {
|
||||
slirp_guestfwd(s, mon, config->str,
|
||||
config->flags & SLIRP_CFG_LEGACY);
|
||||
}
|
||||
slirp_configs = config->next;
|
||||
qemu_free(config);
|
||||
}
|
||||
#ifndef _WIN32
|
||||
if (!smb_export) {
|
||||
smb_export = legacy_smb_export;
|
||||
}
|
||||
if (smb_export) {
|
||||
slirp_smb(s, smb_export, smbsrv);
|
||||
}
|
||||
#endif
|
||||
if ((host.s_addr & mask.s_addr) != net.s_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
|
||||
return -1;
|
||||
}
|
||||
if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
|
||||
dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vnameserver && !inet_aton(vnameserver, &dns)) {
|
||||
return -1;
|
||||
}
|
||||
if ((dns.s_addr & mask.s_addr) != net.s_addr ||
|
||||
dns.s_addr == host.s_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
s = qemu_mallocz(sizeof(SlirpState));
|
||||
s->slirp = slirp_init(restricted, net, mask, host, vhostname,
|
||||
tftp_export, bootfile, dhcp, dns, s);
|
||||
slirp_state = s;
|
||||
|
||||
while (slirp_configs) {
|
||||
struct slirp_config_str *config = slirp_configs;
|
||||
|
||||
if (config->flags & SLIRP_CFG_HOSTFWD) {
|
||||
slirp_hostfwd(s, mon, config->str,
|
||||
config->flags & SLIRP_CFG_LEGACY);
|
||||
} else {
|
||||
slirp_guestfwd(s, mon, config->str,
|
||||
config->flags & SLIRP_CFG_LEGACY);
|
||||
}
|
||||
slirp_configs = config->next;
|
||||
qemu_free(config);
|
||||
}
|
||||
#ifndef _WIN32
|
||||
if (!smb_export) {
|
||||
smb_export = legacy_smb_export;
|
||||
}
|
||||
if (smb_export) {
|
||||
slirp_smb(s, smb_export, smbsrv);
|
||||
}
|
||||
#endif
|
||||
|
||||
s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL,
|
||||
net_slirp_cleanup, s);
|
||||
s->vc->info_str[0] = '\0';
|
||||
slirp_in_use = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
|
|||
const char *vhostname, const char *tftp_path,
|
||||
const char *bootfile, struct in_addr vdhcp_start,
|
||||
struct in_addr vnameserver, void *opaque);
|
||||
void slirp_cleanup(Slirp *slirp);
|
||||
|
||||
void slirp_select_fill(int *pnfds,
|
||||
fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#define TOWRITEMAX 512
|
||||
|
||||
extern int link_up;
|
||||
extern int slirp_socket;
|
||||
extern int slirp_socket_unit;
|
||||
extern int slirp_socket_port;
|
||||
|
|
|
@ -40,8 +40,6 @@ static const uint8_t special_ethaddr[6] = {
|
|||
|
||||
static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
int link_up; // FIXME: kill this
|
||||
|
||||
/* XXX: suppress those select globals */
|
||||
fd_set *global_readfds, *global_writefds, *global_xfds;
|
||||
|
||||
|
@ -49,7 +47,7 @@ u_int curtime;
|
|||
static u_int time_fasttimo, last_slowtimo;
|
||||
static int do_slowtimo;
|
||||
|
||||
Slirp slirp_instance;
|
||||
Slirp *slirp_instance;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
|
@ -193,11 +191,10 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
|
|||
const char *bootfile, struct in_addr vdhcp_start,
|
||||
struct in_addr vnameserver, void *opaque)
|
||||
{
|
||||
Slirp *slirp = &slirp_instance;
|
||||
Slirp *slirp = qemu_mallocz(sizeof(Slirp));
|
||||
|
||||
slirp_init_once();
|
||||
|
||||
link_up = 1;
|
||||
slirp->restricted = restricted;
|
||||
|
||||
if_init(slirp);
|
||||
|
@ -213,13 +210,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
|
|||
pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
|
||||
vhostname);
|
||||
}
|
||||
qemu_free(slirp->tftp_prefix);
|
||||
slirp->tftp_prefix = NULL;
|
||||
if (tftp_path) {
|
||||
slirp->tftp_prefix = qemu_strdup(tftp_path);
|
||||
}
|
||||
qemu_free(slirp->bootp_filename);
|
||||
slirp->bootp_filename = NULL;
|
||||
if (bootfile) {
|
||||
slirp->bootp_filename = qemu_strdup(bootfile);
|
||||
}
|
||||
|
@ -230,9 +223,22 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
|
|||
|
||||
register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
|
||||
|
||||
slirp_instance = slirp;
|
||||
|
||||
return slirp;
|
||||
}
|
||||
|
||||
void slirp_cleanup(Slirp *slirp)
|
||||
{
|
||||
unregister_savevm("slirp", slirp);
|
||||
|
||||
qemu_free(slirp->tftp_prefix);
|
||||
qemu_free(slirp->bootp_filename);
|
||||
qemu_free(slirp);
|
||||
|
||||
slirp_instance = NULL;
|
||||
}
|
||||
|
||||
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
|
||||
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
|
||||
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
|
||||
|
@ -263,11 +269,11 @@ static void updtime(void)
|
|||
void slirp_select_fill(int *pnfds,
|
||||
fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||
{
|
||||
Slirp *slirp = &slirp_instance;
|
||||
Slirp *slirp = slirp_instance;
|
||||
struct socket *so, *so_next;
|
||||
int nfds;
|
||||
|
||||
if (!link_up) {
|
||||
if (!slirp_instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -384,11 +390,11 @@ void slirp_select_fill(int *pnfds,
|
|||
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
|
||||
int select_error)
|
||||
{
|
||||
Slirp *slirp = &slirp_instance;
|
||||
Slirp *slirp = slirp_instance;
|
||||
struct socket *so, *so_next;
|
||||
int ret;
|
||||
|
||||
if (!link_up) {
|
||||
if (!slirp_instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ struct Slirp {
|
|||
void *opaque;
|
||||
};
|
||||
|
||||
extern Slirp slirp_instance;
|
||||
extern Slirp *slirp_instance;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
|
|
Loading…
Reference in a new issue