diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/l2tpv3.c | 5 | ||||
-rw-r--r-- | net/net.c | 40 | ||||
-rw-r--r-- | net/queue.c | 3 | ||||
-rw-r--r-- | net/slirp.c | 19 | ||||
-rw-r--r-- | net/socket.c | 13 | ||||
-rw-r--r-- | net/tap-bsd.c | 70 | ||||
-rw-r--r-- | net/tap.c | 4 | ||||
-rw-r--r-- | net/tap_int.h | 3 |
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) { @@ -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; @@ -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); |