|
@@ -329,6 +329,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
|
|
const char *name,
|
|
|
IOReadHandler *fd_read,
|
|
|
IOCanRWHandler *fd_can_read,
|
|
|
+ NetCleanup *cleanup,
|
|
|
void *opaque)
|
|
|
{
|
|
|
VLANClientState *vc, **pvc;
|
|
@@ -340,6 +341,7 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
|
|
vc->name = assign_name(vc, model);
|
|
|
vc->fd_read = fd_read;
|
|
|
vc->fd_can_read = fd_can_read;
|
|
|
+ vc->cleanup = cleanup;
|
|
|
vc->opaque = opaque;
|
|
|
vc->vlan = vlan;
|
|
|
|
|
@@ -358,6 +360,9 @@ void qemu_del_vlan_client(VLANClientState *vc)
|
|
|
while (*pvc != NULL)
|
|
|
if (*pvc == vc) {
|
|
|
*pvc = vc->next;
|
|
|
+ if (vc->cleanup) {
|
|
|
+ vc->cleanup(vc);
|
|
|
+ }
|
|
|
free(vc->name);
|
|
|
free(vc->model);
|
|
|
free(vc);
|
|
@@ -517,7 +522,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
|
|
|
slirp_init(slirp_restrict, slirp_ip);
|
|
|
}
|
|
|
slirp_vc = qemu_new_vlan_client(vlan, model, name,
|
|
|
- slirp_receive, NULL, NULL);
|
|
|
+ slirp_receive, NULL, NULL, NULL);
|
|
|
slirp_vc->info_str[0] = '\0';
|
|
|
return 0;
|
|
|
}
|
|
@@ -698,6 +703,8 @@ typedef struct TAPState {
|
|
|
char down_script_arg[128];
|
|
|
} TAPState;
|
|
|
|
|
|
+static int launch_script(const char *setup_script, const char *ifname, int fd);
|
|
|
+
|
|
|
static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov,
|
|
|
int iovcnt)
|
|
|
{
|
|
@@ -744,6 +751,18 @@ static void tap_send(void *opaque)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void tap_cleanup(VLANClientState *vc)
|
|
|
+{
|
|
|
+ TAPState *s = vc->opaque;
|
|
|
+
|
|
|
+ if (s->down_script[0])
|
|
|
+ launch_script(s->down_script, s->down_script_arg, s->fd);
|
|
|
+
|
|
|
+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
|
|
+ close(s->fd);
|
|
|
+ qemu_free(s);
|
|
|
+}
|
|
|
+
|
|
|
/* fd support */
|
|
|
|
|
|
static TAPState *net_tap_fd_init(VLANState *vlan,
|
|
@@ -755,7 +774,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
|
|
|
|
|
|
s = qemu_mallocz(sizeof(TAPState));
|
|
|
s->fd = fd;
|
|
|
- s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive, NULL, s);
|
|
|
+ s->vc = qemu_new_vlan_client(vlan, model, name, tap_receive,
|
|
|
+ NULL, tap_cleanup, s);
|
|
|
s->vc->fd_readv = tap_receive_iov;
|
|
|
qemu_set_fd_handler(s->fd, tap_send, NULL, s);
|
|
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd);
|
|
@@ -1054,6 +1074,14 @@ static void vde_from_qemu(void *opaque, const uint8_t *buf, int size)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void vde_cleanup(VLANClientState *vc)
|
|
|
+{
|
|
|
+ VDEState *s = vc->opaque;
|
|
|
+ qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL);
|
|
|
+ vde_close(s->vde);
|
|
|
+ qemu_free(s);
|
|
|
+}
|
|
|
+
|
|
|
static int net_vde_init(VLANState *vlan, const char *model,
|
|
|
const char *name, const char *sock,
|
|
|
int port, const char *group, int mode)
|
|
@@ -1074,7 +1102,8 @@ static int net_vde_init(VLANState *vlan, const char *model,
|
|
|
free(s);
|
|
|
return -1;
|
|
|
}
|
|
|
- s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu, NULL, s);
|
|
|
+ s->vc = qemu_new_vlan_client(vlan, model, name, vde_from_qemu,
|
|
|
+ NULL, vde_cleanup, s);
|
|
|
qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);
|
|
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d",
|
|
|
sock, vde_datafd(s->vde));
|
|
@@ -1259,6 +1288,14 @@ fail:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+static void net_socket_cleanup(VLANClientState *vc)
|
|
|
+{
|
|
|
+ NetSocketState *s = vc->opaque;
|
|
|
+ qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
|
|
|
+ close(s->fd);
|
|
|
+ qemu_free(s);
|
|
|
+}
|
|
|
+
|
|
|
static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
|
|
|
const char *model,
|
|
|
const char *name,
|
|
@@ -1303,7 +1340,8 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
|
|
|
s = qemu_mallocz(sizeof(NetSocketState));
|
|
|
s->fd = fd;
|
|
|
|
|
|
- s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram, NULL, s);
|
|
|
+ s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive_dgram,
|
|
|
+ NULL, net_socket_cleanup, s);
|
|
|
qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
|
|
|
|
|
|
/* mcast: save bound address as dst */
|
|
@@ -1330,8 +1368,8 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
|
|
|
NetSocketState *s;
|
|
|
s = qemu_mallocz(sizeof(NetSocketState));
|
|
|
s->fd = fd;
|
|
|
- s->vc = qemu_new_vlan_client(vlan, model, name,
|
|
|
- net_socket_receive, NULL, s);
|
|
|
+ s->vc = qemu_new_vlan_client(vlan, model, name, net_socket_receive,
|
|
|
+ NULL, net_socket_cleanup, s);
|
|
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
|
|
"socket: fd=%d", fd);
|
|
|
if (is_connected) {
|
|
@@ -1893,27 +1931,18 @@ void net_cleanup(void)
|
|
|
{
|
|
|
VLANState *vlan;
|
|
|
|
|
|
-#if !defined(_WIN32)
|
|
|
/* close network clients */
|
|
|
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
|
|
|
- VLANClientState *vc;
|
|
|
+ VLANClientState *vc = vlan->first_client;
|
|
|
|
|
|
- for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
|
|
- if (vc->fd_read == tap_receive) {
|
|
|
- TAPState *s = vc->opaque;
|
|
|
+ while (vc) {
|
|
|
+ VLANClientState *next = vc->next;
|
|
|
|
|
|
- if (s->down_script[0])
|
|
|
- launch_script(s->down_script, s->down_script_arg, s->fd);
|
|
|
- }
|
|
|
-#if defined(CONFIG_VDE)
|
|
|
- if (vc->fd_read == vde_from_qemu) {
|
|
|
- VDEState *s = vc->opaque;
|
|
|
- vde_close(s->vde);
|
|
|
- }
|
|
|
-#endif
|
|
|
+ qemu_del_vlan_client(vc);
|
|
|
+
|
|
|
+ vc = next;
|
|
|
}
|
|
|
}
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
void net_client_check(void)
|