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 729 return size;
730 730 }
731 731  
732   -static int slirp_in_use;
733   -
734 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 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 746 const char *vnameserver, const char *smb_export,
745 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 755 #ifndef _WIN32
761   - struct in_addr smbsrv = { .s_addr = 0 };
  756 + struct in_addr smbsrv = { .s_addr = 0 };
762 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 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 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 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 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 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 869 s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL,
875 870 net_slirp_cleanup, s);
876 871 s->vc->info_str[0] = '\0';
877   - slirp_in_use = 1;
878 872 return 0;
879 873 }
880 874  
... ...
slirp/libslirp.h
... ... @@ -13,6 +13,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
13 13 const char *vhostname, const char *tftp_path,
14 14 const char *bootfile, struct in_addr vdhcp_start,
15 15 struct in_addr vnameserver, void *opaque);
  16 +void slirp_cleanup(Slirp *slirp);
16 17  
17 18 void slirp_select_fill(int *pnfds,
18 19 fd_set *readfds, fd_set *writefds, fd_set *xfds);
... ...
slirp/main.h
... ... @@ -11,7 +11,6 @@
11 11  
12 12 #define TOWRITEMAX 512
13 13  
14   -extern int link_up;
15 14 extern int slirp_socket;
16 15 extern int slirp_socket_unit;
17 16 extern int slirp_socket_port;
... ...
slirp/slirp.c
... ... @@ -40,8 +40,6 @@ static const uint8_t special_ethaddr[6] = {
40 40  
41 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 43 /* XXX: suppress those select globals */
46 44 fd_set *global_readfds, *global_writefds, *global_xfds;
47 45  
... ... @@ -49,7 +47,7 @@ u_int curtime;
49 47 static u_int time_fasttimo, last_slowtimo;
50 48 static int do_slowtimo;
51 49  
52   -Slirp slirp_instance;
  50 +Slirp *slirp_instance;
53 51  
54 52 #ifdef _WIN32
55 53  
... ... @@ -193,11 +191,10 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
193 191 const char *bootfile, struct in_addr vdhcp_start,
194 192 struct in_addr vnameserver, void *opaque)
195 193 {
196   - Slirp *slirp = &slirp_instance;
  194 + Slirp *slirp = qemu_mallocz(sizeof(Slirp));
197 195  
198 196 slirp_init_once();
199 197  
200   - link_up = 1;
201 198 slirp->restricted = restricted;
202 199  
203 200 if_init(slirp);
... ... @@ -213,13 +210,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
213 210 pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
214 211 vhostname);
215 212 }
216   - qemu_free(slirp->tftp_prefix);
217   - slirp->tftp_prefix = NULL;
218 213 if (tftp_path) {
219 214 slirp->tftp_prefix = qemu_strdup(tftp_path);
220 215 }
221   - qemu_free(slirp->bootp_filename);
222   - slirp->bootp_filename = NULL;
223 216 if (bootfile) {
224 217 slirp->bootp_filename = qemu_strdup(bootfile);
225 218 }
... ... @@ -230,9 +223,22 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
230 223  
231 224 register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
232 225  
  226 + slirp_instance = slirp;
  227 +
233 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 242 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
237 243 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
238 244 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
... ... @@ -263,11 +269,11 @@ static void updtime(void)
263 269 void slirp_select_fill(int *pnfds,
264 270 fd_set *readfds, fd_set *writefds, fd_set *xfds)
265 271 {
266   - Slirp *slirp = &slirp_instance;
  272 + Slirp *slirp = slirp_instance;
267 273 struct socket *so, *so_next;
268 274 int nfds;
269 275  
270   - if (!link_up) {
  276 + if (!slirp_instance) {
271 277 return;
272 278 }
273 279  
... ... @@ -384,11 +390,11 @@ void slirp_select_fill(int *pnfds,
384 390 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
385 391 int select_error)
386 392 {
387   - Slirp *slirp = &slirp_instance;
  393 + Slirp *slirp = slirp_instance;
388 394 struct socket *so, *so_next;
389 395 int ret;
390 396  
391   - if (!link_up) {
  397 + if (!slirp_instance) {
392 398 return;
393 399 }
394 400  
... ...
slirp/slirp.h
... ... @@ -259,7 +259,7 @@ struct Slirp {
259 259 void *opaque;
260 260 };
261 261  
262   -extern Slirp slirp_instance;
  262 +extern Slirp *slirp_instance;
263 263  
264 264 #ifndef NULL
265 265 #define NULL (void *)0
... ...