summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/l2tpv3.c5
-rw-r--r--net/net.c40
-rw-r--r--net/queue.c3
-rw-r--r--net/slirp.c19
-rw-r--r--net/socket.c13
-rw-r--r--net/tap-bsd.c70
-rw-r--r--net/tap.c4
-rw-r--r--net/tap_int.h3
8 files changed, 135 insertions, 22 deletions
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index 528d95b64..3b805a7a4 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -516,7 +516,7 @@ static void net_l2tpv3_cleanup(NetClientState *nc)
qemu_purge_queued_packets(nc);
l2tpv3_read_poll(s, false);
l2tpv3_write_poll(s, false);
- if (s->fd > 0) {
+ if (s->fd >= 0) {
close(s->fd);
}
destroy_vector(s->msgvec, MAX_L2TPV3_MSGCNT, IOVSIZE);
@@ -660,7 +660,6 @@ int net_init_l2tpv3(const NetClientOptions *opts,
if (fd == -1) {
fd = -errno;
error_report("l2tpv3_open : socket creation failed, errno = %d", -fd);
- freeaddrinfo(result);
goto outerr;
}
if (bind(fd, (struct sockaddr *) result->ai_addr, result->ai_addrlen)) {
@@ -746,7 +745,7 @@ int net_init_l2tpv3(const NetClientOptions *opts,
return 0;
outerr:
qemu_del_net_client(nc);
- if (fd > 0) {
+ if (fd >= 0) {
close(fd);
}
if (result) {
diff --git a/net/net.c b/net/net.c
index 6d930ea63..7acc162b4 100644
--- a/net/net.c
+++ b/net/net.c
@@ -41,12 +41,14 @@
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
+#include "sysemu/sysemu.h"
/* Net bridge is currently not supported for W32. */
#if !defined(_WIN32)
# define CONFIG_NET_BRIDGE
#endif
+static VMChangeStateEntry *net_change_state_entry;
static QTAILQ_HEAD(, NetClientState) net_clients;
const char *host_net_devices[] = {
@@ -452,6 +454,12 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
int qemu_can_send_packet(NetClientState *sender)
{
+ int vm_running = runstate_is_running();
+
+ if (!vm_running) {
+ return 0;
+ }
+
if (!sender->peer) {
return 1;
}
@@ -504,7 +512,8 @@ void qemu_purge_queued_packets(NetClientState *nc)
qemu_net_queue_purge(nc->peer->incoming_queue, nc);
}
-void qemu_flush_queued_packets(NetClientState *nc)
+static
+void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge)
{
nc->receive_disabled = 0;
@@ -518,9 +527,17 @@ void qemu_flush_queued_packets(NetClientState *nc)
* the file descriptor (for tap, for example).
*/
qemu_notify_event();
+ } else if (purge) {
+ /* Unable to empty the queue, purge remaining packets */
+ qemu_net_queue_purge(nc->incoming_queue, nc);
}
}
+void qemu_flush_queued_packets(NetClientState *nc)
+{
+ qemu_flush_or_purge_queued_packets(nc, false);
+}
+
static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
unsigned flags,
const uint8_t *buf, int size,
@@ -1168,6 +1185,22 @@ void qmp_set_link(const char *name, bool up, Error **errp)
}
}
+static void net_vm_change_state_handler(void *opaque, int running,
+ RunState state)
+{
+ /* Complete all queued packets, to guarantee we don't modify
+ * state later when VM is not running.
+ */
+ if (!running) {
+ NetClientState *nc;
+ NetClientState *tmp;
+
+ QTAILQ_FOREACH_SAFE(nc, &net_clients, next, tmp) {
+ qemu_flush_or_purge_queued_packets(nc, true);
+ }
+ }
+}
+
void net_cleanup(void)
{
NetClientState *nc;
@@ -1183,6 +1216,8 @@ void net_cleanup(void)
qemu_del_net_client(nc);
}
}
+
+ qemu_del_vm_change_state_handler(net_change_state_entry);
}
void net_check_clients(void)
@@ -1268,6 +1303,9 @@ int net_init_clients(void)
#endif
}
+ net_change_state_entry =
+ qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
+
QTAILQ_INIT(&net_clients);
if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1)
diff --git a/net/queue.c b/net/queue.c
index 859d02a13..f94831871 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -233,6 +233,9 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from)
if (packet->sender == from) {
QTAILQ_REMOVE(&queue->packets, packet, entry);
queue->nq_count--;
+ if (packet->sent_cb) {
+ packet->sent_cb(packet->sender, 0);
+ }
g_free(packet);
}
}
diff --git a/net/slirp.c b/net/slirp.c
index 647039ec3..377d7ef8c 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -345,8 +345,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
host_port = atoi(p);
- err = slirp_remove_hostfwd(QTAILQ_FIRST(&slirp_stacks)->slirp, is_udp,
- host_addr, host_port);
+ err = slirp_remove_hostfwd(s->slirp, is_udp, host_addr, host_port);
monitor_printf(mon, "host forwarding rule for %s %s\n", src_str,
err ? "not found" : "removed");
@@ -524,15 +523,21 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
fprintf(f,
"[global]\n"
"private dir=%s\n"
- "socket address=127.0.0.1\n"
+ "interfaces=127.0.0.1\n"
+ "bind interfaces only=yes\n"
"pid directory=%s\n"
"lock directory=%s\n"
"state directory=%s\n"
+ "cache directory=%s\n"
"ncalrpc dir=%s/ncalrpc\n"
"log file=%s/log.smbd\n"
"smb passwd file=%s/smbpasswd\n"
"security = user\n"
"map to guest = Bad User\n"
+ "load printers = no\n"
+ "printing = bsd\n"
+ "disable spoolss = yes\n"
+ "usershare max shares = 0\n"
"[qemu]\n"
"path=%s\n"
"read only=no\n"
@@ -545,13 +550,14 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
s->smb_dir,
s->smb_dir,
s->smb_dir,
+ s->smb_dir,
exported_dir,
passwd->pw_name
);
fclose(f);
- snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
- CONFIG_SMBD_COMMAND, smb_conf);
+ snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -l %s -s %s",
+ CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
if (slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139) < 0 ||
slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 445) < 0) {
@@ -637,17 +643,16 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
goto fail_syntax;
}
- fwd = g_malloc(sizeof(struct GuestFwd));
snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) {
if (slirp_add_exec(s->slirp, 0, &p[4], &server, port) < 0) {
error_report("conflicting/invalid host:port in guest forwarding "
"rule '%s'", config_str);
- g_free(fwd);
return -1;
}
} else {
+ fwd = g_malloc(sizeof(struct GuestFwd));
fwd->hd = qemu_chr_new(buf, p, NULL);
if (!fwd->hd) {
error_report("could not open guest forwarding device '%s'", buf);
diff --git a/net/socket.c b/net/socket.c
index fb21e20a5..68a93cd7e 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -352,7 +352,7 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
{
struct sockaddr_in saddr;
int newfd;
- socklen_t saddr_len;
+ socklen_t saddr_len = sizeof(saddr);
NetClientState *nc;
NetSocketState *s;
@@ -389,11 +389,6 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
nc = qemu_new_net_client(&net_dgram_socket_info, peer, model, name);
- snprintf(nc->info_str, sizeof(nc->info_str),
- "socket: fd=%d (%s mcast=%s:%d)",
- fd, is_connected ? "cloned" : "",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
-
s = DO_UPCAST(NetSocketState, nc, nc);
s->fd = fd;
@@ -404,6 +399,12 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer,
/* mcast: save bound address as dst */
if (is_connected) {
s->dgram_dst = saddr;
+ snprintf(nc->info_str, sizeof(nc->info_str),
+ "socket: fd=%d (cloned mcast=%s:%d)",
+ fd, inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ } else {
+ snprintf(nc->info_str, sizeof(nc->info_str),
+ "socket: fd=%d", fd);
}
return s;
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index 90f8a0227..bf91bd03f 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -27,12 +27,13 @@
#include "sysemu/sysemu.h"
#include "qemu/error-report.h"
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || defined(__FreeBSD__)
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_tap.h>
#endif
+#ifndef __FreeBSD__
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required)
{
@@ -108,6 +109,73 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
return fd;
}
+#else /* __FreeBSD__ */
+
+#define PATH_NET_TAP "/dev/tap"
+
+int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
+ int vnet_hdr_required, int mq_required)
+{
+ int fd, s, ret;
+ struct ifreq ifr;
+
+ TFR(fd = open(PATH_NET_TAP, O_RDWR));
+ if (fd < 0) {
+ error_report("could not open %s: %s", PATH_NET_TAP, strerror(errno));
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ ret = ioctl(fd, TAPGIFNAME, (void *)&ifr);
+ if (ret < 0) {
+ error_report("could not get tap interface name");
+ goto error;
+ }
+
+ if (ifname[0] != '\0') {
+ /* User requested the interface to have a specific name */
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s < 0) {
+ error_report("could not open socket to set interface name");
+ goto error;
+ }
+ ifr.ifr_data = ifname;
+ ret = ioctl(s, SIOCSIFNAME, (void *)&ifr);
+ close(s);
+ if (ret < 0) {
+ error_report("could not set tap interface name");
+ goto error;
+ }
+ } else {
+ pstrcpy(ifname, ifname_size, ifr.ifr_name);
+ }
+
+ if (*vnet_hdr) {
+ /* BSD doesn't have IFF_VNET_HDR */
+ *vnet_hdr = 0;
+
+ if (vnet_hdr_required && !*vnet_hdr) {
+ error_report("vnet_hdr=1 requested, but no kernel "
+ "support for IFF_VNET_HDR available");
+ goto error;
+ }
+ }
+ if (mq_required) {
+ error_report("mq_required requested, but not kernel support"
+ "for IFF_MULTI_QUEUE available");
+ goto error;
+ }
+
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ return fd;
+
+error:
+ close(fd);
+ return -1;
+}
+#endif /* __FreeBSD__ */
+
int tap_set_sndbuf(int fd, const NetdevTapOptions *tap)
{
return 0;
diff --git a/net/tap.c b/net/tap.c
index a40f7f023..bde6b58b1 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -598,7 +598,6 @@ static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
s = net_tap_fd_init(peer, model, name, fd, vnet_hdr);
if (!s) {
- close(fd);
return -1;
}
@@ -797,6 +796,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (net_init_tap_one(tap, peer, "bridge", name, ifname,
script, downscript, vhostfdname,
vnet_hdr, fd)) {
+ close(fd);
return -1;
}
} else {
@@ -824,6 +824,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
if (queues > 1 && i == 0 && !tap->has_ifname) {
if (tap_fd_get_ifname(fd, ifname)) {
error_report("Fail to get ifname");
+ close(fd);
return -1;
}
}
@@ -832,6 +833,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
i >= 1 ? "no" : script,
i >= 1 ? "no" : downscript,
vhostfdname, vnet_hdr, fd)) {
+ close(fd);
return -1;
}
}
diff --git a/net/tap_int.h b/net/tap_int.h
index 86bb224bc..79afdf2d5 100644
--- a/net/tap_int.h
+++ b/net/tap_int.h
@@ -29,9 +29,6 @@
#include "qemu-common.h"
#include "qapi-types.h"
-#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
-#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
-
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required);