Commit ad0d8c4c326c87ee3f193f90f31ec4af0fce5598

Authored by Jan Kiszka
Committed by Anthony Liguori
1 parent 9f8bd042

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>
@@ -729,11 +729,13 @@ static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t siz @@ -729,11 +729,13 @@ static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t siz
729 return size; 729 return size;
730 } 730 }
731 731
732 -static int slirp_in_use;  
733 -  
734 static void net_slirp_cleanup(VLANClientState *vc) 732 static void net_slirp_cleanup(VLANClientState *vc)
735 { 733 {
736 - slirp_in_use = 0; 734 + SlirpState *s = vc->opaque;
  735 +
  736 + slirp_cleanup(s->slirp);
  737 + slirp_state = NULL;
  738 + qemu_free(s);
737 } 739 }
738 740
739 static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model, 741 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, @@ -744,137 +746,129 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
744 const char *vnameserver, const char *smb_export, 746 const char *vnameserver, const char *smb_export,
745 const char *vsmbserver) 747 const char *vsmbserver)
746 { 748 {
747 - SlirpState *s = slirp_state;  
748 -  
749 - if (slirp_in_use) {  
750 - /* slirp only supports a single instance so far */  
751 - return -1;  
752 - }  
753 - if (!s) {  
754 - /* default settings according to historic slirp */  
755 - struct in_addr net = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */  
756 - struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */  
757 - struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */  
758 - struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */  
759 - struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */ 749 + /* default settings according to historic slirp */
  750 + struct in_addr net = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
  751 + struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
  752 + struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
  753 + struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
  754 + struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
760 #ifndef _WIN32 755 #ifndef _WIN32
761 - struct in_addr smbsrv = { .s_addr = 0 }; 756 + struct in_addr smbsrv = { .s_addr = 0 };
762 #endif 757 #endif
763 - char buf[20];  
764 - uint32_t addr;  
765 - int shift;  
766 - char *end; 758 + SlirpState *s;
  759 + char buf[20];
  760 + uint32_t addr;
  761 + int shift;
  762 + char *end;
767 763
768 - if (!tftp_export) {  
769 - tftp_export = legacy_tftp_prefix;  
770 - }  
771 - if (!bootfile) {  
772 - bootfile = legacy_bootp_filename;  
773 - } 764 + if (!tftp_export) {
  765 + tftp_export = legacy_tftp_prefix;
  766 + }
  767 + if (!bootfile) {
  768 + bootfile = legacy_bootp_filename;
  769 + }
774 770
775 - if (vnetwork) {  
776 - if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {  
777 - if (!inet_aton(vnetwork, &net)) {  
778 - return -1;  
779 - }  
780 - addr = ntohl(net.s_addr);  
781 - if (!(addr & 0x80000000)) {  
782 - mask.s_addr = htonl(0xff000000); /* class A */  
783 - } else if ((addr & 0xfff00000) == 0xac100000) {  
784 - mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */  
785 - } else if ((addr & 0xc0000000) == 0x80000000) {  
786 - mask.s_addr = htonl(0xffff0000); /* class B */  
787 - } else if ((addr & 0xffff0000) == 0xc0a80000) {  
788 - mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */  
789 - } else if ((addr & 0xffff0000) == 0xc6120000) {  
790 - mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */  
791 - } else if ((addr & 0xe0000000) == 0xe0000000) {  
792 - mask.s_addr = htonl(0xffffff00); /* class C */  
793 - } else {  
794 - mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */  
795 - } 771 + if (vnetwork) {
  772 + if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
  773 + if (!inet_aton(vnetwork, &net)) {
  774 + return -1;
  775 + }
  776 + addr = ntohl(net.s_addr);
  777 + if (!(addr & 0x80000000)) {
  778 + mask.s_addr = htonl(0xff000000); /* class A */
  779 + } else if ((addr & 0xfff00000) == 0xac100000) {
  780 + mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
  781 + } else if ((addr & 0xc0000000) == 0x80000000) {
  782 + mask.s_addr = htonl(0xffff0000); /* class B */
  783 + } else if ((addr & 0xffff0000) == 0xc0a80000) {
  784 + mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
  785 + } else if ((addr & 0xffff0000) == 0xc6120000) {
  786 + mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
  787 + } else if ((addr & 0xe0000000) == 0xe0000000) {
  788 + mask.s_addr = htonl(0xffffff00); /* class C */
796 } else { 789 } else {
797 - if (!inet_aton(buf, &net)) {  
798 - return -1;  
799 - }  
800 - shift = strtol(vnetwork, &end, 10);  
801 - if (*end != '\0') {  
802 - if (!inet_aton(vnetwork, &mask)) {  
803 - return -1;  
804 - }  
805 - } else if (shift < 4 || shift > 32) { 790 + mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
  791 + }
  792 + } else {
  793 + if (!inet_aton(buf, &net)) {
  794 + return -1;
  795 + }
  796 + shift = strtol(vnetwork, &end, 10);
  797 + if (*end != '\0') {
  798 + if (!inet_aton(vnetwork, &mask)) {
806 return -1; 799 return -1;
807 - } else {  
808 - mask.s_addr = htonl(0xffffffff << (32 - shift));  
809 } 800 }
  801 + } else if (shift < 4 || shift > 32) {
  802 + return -1;
  803 + } else {
  804 + mask.s_addr = htonl(0xffffffff << (32 - shift));
810 } 805 }
811 - net.s_addr &= mask.s_addr;  
812 - host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);  
813 - dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);  
814 - dns.s_addr = net.s_addr | (htonl(0x0203) & ~mask.s_addr);  
815 } 806 }
  807 + net.s_addr &= mask.s_addr;
  808 + host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
  809 + dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
  810 + dns.s_addr = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
  811 + }
816 812
817 - if (vhost && !inet_aton(vhost, &host)) {  
818 - return -1;  
819 - }  
820 - if ((host.s_addr & mask.s_addr) != net.s_addr) {  
821 - return -1;  
822 - } 813 + if (vhost && !inet_aton(vhost, &host)) {
  814 + return -1;
  815 + }
  816 + if ((host.s_addr & mask.s_addr) != net.s_addr) {
  817 + return -1;
  818 + }
823 819
824 - if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {  
825 - return -1;  
826 - }  
827 - if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||  
828 - dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {  
829 - return -1;  
830 - } 820 + if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
  821 + return -1;
  822 + }
  823 + if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
  824 + dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
  825 + return -1;
  826 + }
831 827
832 - if (vnameserver && !inet_aton(vnameserver, &dns)) {  
833 - return -1;  
834 - }  
835 - if ((dns.s_addr & mask.s_addr) != net.s_addr ||  
836 - dns.s_addr == host.s_addr) {  
837 - return -1;  
838 - } 828 + if (vnameserver && !inet_aton(vnameserver, &dns)) {
  829 + return -1;
  830 + }
  831 + if ((dns.s_addr & mask.s_addr) != net.s_addr ||
  832 + dns.s_addr == host.s_addr) {
  833 + return -1;
  834 + }
839 835
840 #ifndef _WIN32 836 #ifndef _WIN32
841 - if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {  
842 - return -1;  
843 - } 837 + if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
  838 + return -1;
  839 + }
844 #endif 840 #endif
845 841
846 - s = qemu_mallocz(sizeof(SlirpState));  
847 - s->slirp = slirp_init(restricted, net, mask, host, vhostname,  
848 - tftp_export, bootfile, dhcp, dns, s);  
849 - slirp_state = s; 842 + s = qemu_mallocz(sizeof(SlirpState));
  843 + s->slirp = slirp_init(restricted, net, mask, host, vhostname,
  844 + tftp_export, bootfile, dhcp, dns, s);
  845 + slirp_state = s;
850 846
851 - while (slirp_configs) {  
852 - struct slirp_config_str *config = slirp_configs; 847 + while (slirp_configs) {
  848 + struct slirp_config_str *config = slirp_configs;
853 849
854 - if (config->flags & SLIRP_CFG_HOSTFWD) {  
855 - slirp_hostfwd(s, mon, config->str,  
856 - config->flags & SLIRP_CFG_LEGACY);  
857 - } else {  
858 - slirp_guestfwd(s, mon, config->str,  
859 - config->flags & SLIRP_CFG_LEGACY);  
860 - }  
861 - slirp_configs = config->next;  
862 - qemu_free(config); 850 + if (config->flags & SLIRP_CFG_HOSTFWD) {
  851 + slirp_hostfwd(s, mon, config->str,
  852 + config->flags & SLIRP_CFG_LEGACY);
  853 + } else {
  854 + slirp_guestfwd(s, mon, config->str,
  855 + config->flags & SLIRP_CFG_LEGACY);
863 } 856 }
  857 + slirp_configs = config->next;
  858 + qemu_free(config);
  859 + }
864 #ifndef _WIN32 860 #ifndef _WIN32
865 - if (!smb_export) {  
866 - smb_export = legacy_smb_export;  
867 - }  
868 - if (smb_export) {  
869 - slirp_smb(s, smb_export, smbsrv);  
870 - }  
871 -#endif 861 + if (!smb_export) {
  862 + smb_export = legacy_smb_export;
  863 + }
  864 + if (smb_export) {
  865 + slirp_smb(s, smb_export, smbsrv);
872 } 866 }
  867 +#endif
873 868
874 s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL, 869 s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL,
875 net_slirp_cleanup, s); 870 net_slirp_cleanup, s);
876 s->vc->info_str[0] = '\0'; 871 s->vc->info_str[0] = '\0';
877 - slirp_in_use = 1;  
878 return 0; 872 return 0;
879 } 873 }
880 874
slirp/libslirp.h
@@ -13,6 +13,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, @@ -13,6 +13,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
13 const char *vhostname, const char *tftp_path, 13 const char *vhostname, const char *tftp_path,
14 const char *bootfile, struct in_addr vdhcp_start, 14 const char *bootfile, struct in_addr vdhcp_start,
15 struct in_addr vnameserver, void *opaque); 15 struct in_addr vnameserver, void *opaque);
  16 +void slirp_cleanup(Slirp *slirp);
16 17
17 void slirp_select_fill(int *pnfds, 18 void slirp_select_fill(int *pnfds,
18 fd_set *readfds, fd_set *writefds, fd_set *xfds); 19 fd_set *readfds, fd_set *writefds, fd_set *xfds);
slirp/main.h
@@ -11,7 +11,6 @@ @@ -11,7 +11,6 @@
11 11
12 #define TOWRITEMAX 512 12 #define TOWRITEMAX 512
13 13
14 -extern int link_up;  
15 extern int slirp_socket; 14 extern int slirp_socket;
16 extern int slirp_socket_unit; 15 extern int slirp_socket_unit;
17 extern int slirp_socket_port; 16 extern int slirp_socket_port;
slirp/slirp.c
@@ -40,8 +40,6 @@ static const uint8_t special_ethaddr[6] = { @@ -40,8 +40,6 @@ static const uint8_t special_ethaddr[6] = {
40 40
41 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 }; 41 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
42 42
43 -int link_up; // FIXME: kill this  
44 -  
45 /* XXX: suppress those select globals */ 43 /* XXX: suppress those select globals */
46 fd_set *global_readfds, *global_writefds, *global_xfds; 44 fd_set *global_readfds, *global_writefds, *global_xfds;
47 45
@@ -49,7 +47,7 @@ u_int curtime; @@ -49,7 +47,7 @@ u_int curtime;
49 static u_int time_fasttimo, last_slowtimo; 47 static u_int time_fasttimo, last_slowtimo;
50 static int do_slowtimo; 48 static int do_slowtimo;
51 49
52 -Slirp slirp_instance; 50 +Slirp *slirp_instance;
53 51
54 #ifdef _WIN32 52 #ifdef _WIN32
55 53
@@ -193,11 +191,10 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, @@ -193,11 +191,10 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
193 const char *bootfile, struct in_addr vdhcp_start, 191 const char *bootfile, struct in_addr vdhcp_start,
194 struct in_addr vnameserver, void *opaque) 192 struct in_addr vnameserver, void *opaque)
195 { 193 {
196 - Slirp *slirp = &slirp_instance; 194 + Slirp *slirp = qemu_mallocz(sizeof(Slirp));
197 195
198 slirp_init_once(); 196 slirp_init_once();
199 197
200 - link_up = 1;  
201 slirp->restricted = restricted; 198 slirp->restricted = restricted;
202 199
203 if_init(slirp); 200 if_init(slirp);
@@ -213,13 +210,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, @@ -213,13 +210,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
213 pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname), 210 pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
214 vhostname); 211 vhostname);
215 } 212 }
216 - qemu_free(slirp->tftp_prefix);  
217 - slirp->tftp_prefix = NULL;  
218 if (tftp_path) { 213 if (tftp_path) {
219 slirp->tftp_prefix = qemu_strdup(tftp_path); 214 slirp->tftp_prefix = qemu_strdup(tftp_path);
220 } 215 }
221 - qemu_free(slirp->bootp_filename);  
222 - slirp->bootp_filename = NULL;  
223 if (bootfile) { 216 if (bootfile) {
224 slirp->bootp_filename = qemu_strdup(bootfile); 217 slirp->bootp_filename = qemu_strdup(bootfile);
225 } 218 }
@@ -230,9 +223,22 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, @@ -230,9 +223,22 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
230 223
231 register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp); 224 register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
232 225
  226 + slirp_instance = slirp;
  227 +
233 return slirp; 228 return slirp;
234 } 229 }
235 230
  231 +void slirp_cleanup(Slirp *slirp)
  232 +{
  233 + unregister_savevm("slirp", slirp);
  234 +
  235 + qemu_free(slirp->tftp_prefix);
  236 + qemu_free(slirp->bootp_filename);
  237 + qemu_free(slirp);
  238 +
  239 + slirp_instance = NULL;
  240 +}
  241 +
236 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) 242 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
237 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) 243 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
238 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x) 244 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
@@ -263,11 +269,11 @@ static void updtime(void) @@ -263,11 +269,11 @@ static void updtime(void)
263 void slirp_select_fill(int *pnfds, 269 void slirp_select_fill(int *pnfds,
264 fd_set *readfds, fd_set *writefds, fd_set *xfds) 270 fd_set *readfds, fd_set *writefds, fd_set *xfds)
265 { 271 {
266 - Slirp *slirp = &slirp_instance; 272 + Slirp *slirp = slirp_instance;
267 struct socket *so, *so_next; 273 struct socket *so, *so_next;
268 int nfds; 274 int nfds;
269 275
270 - if (!link_up) { 276 + if (!slirp_instance) {
271 return; 277 return;
272 } 278 }
273 279
@@ -384,11 +390,11 @@ void slirp_select_fill(int *pnfds, @@ -384,11 +390,11 @@ void slirp_select_fill(int *pnfds,
384 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, 390 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
385 int select_error) 391 int select_error)
386 { 392 {
387 - Slirp *slirp = &slirp_instance; 393 + Slirp *slirp = slirp_instance;
388 struct socket *so, *so_next; 394 struct socket *so, *so_next;
389 int ret; 395 int ret;
390 396
391 - if (!link_up) { 397 + if (!slirp_instance) {
392 return; 398 return;
393 } 399 }
394 400
slirp/slirp.h
@@ -259,7 +259,7 @@ struct Slirp { @@ -259,7 +259,7 @@ struct Slirp {
259 void *opaque; 259 void *opaque;
260 }; 260 };
261 261
262 -extern Slirp slirp_instance; 262 +extern Slirp *slirp_instance;
263 263
264 #ifndef NULL 264 #ifndef NULL
265 #define NULL (void *)0 265 #define NULL (void *)0