From: Jan Kiszka Date: Wed, 24 Jun 2009 12:42:31 +0000 (+0200) Subject: slirp: Allocate/free stack instance dynamically X-Git-Tag: 0.10.0-0sb10~879 X-Git-Url: http://git.maemo.org/git/?a=commitdiff_plain;h=ad0d8c4c326c87ee3f193f90f31ec4af0fce5598;p=qemu 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 Signed-off-by: Anthony Liguori --- diff --git a/net.c b/net.c index 3b20ba5..389be4a 100644 --- a/net.c +++ b/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; - - if (slirp_in_use) { - /* slirp only supports a single instance so far */ - 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 */ + /* 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 }; + struct in_addr smbsrv = { .s_addr = 0 }; #endif - char buf[20]; - uint32_t addr; - int shift; - char *end; + SlirpState *s; + 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 (!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 */ - } + 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 { - 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) { + 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 { - mask.s_addr = htonl(0xffffffff << (32 - shift)); } + } 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); } + 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 (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 (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; - } + 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; - } + 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; + 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; + 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); + 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 (!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; } diff --git a/slirp/libslirp.h b/slirp/libslirp.h index 521de3e..3bcc392 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -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); diff --git a/slirp/main.h b/slirp/main.h index 90deb58..28d92d8 100644 --- a/slirp/main.h +++ b/slirp/main.h @@ -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; diff --git a/slirp/slirp.c b/slirp/slirp.c index 7e86124..43aba3d 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -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; } diff --git a/slirp/slirp.h b/slirp/slirp.h index cb1a746..5d8861c 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -259,7 +259,7 @@ struct Slirp { void *opaque; }; -extern Slirp slirp_instance; +extern Slirp *slirp_instance; #ifndef NULL #define NULL (void *)0