#include "slirp/libslirp.h"
#include "slirp/ip6.h"
#include "sysemu/char.h"
+#include "sysemu/sysemu.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
{
NetClientState nc;
QTAILQ_ENTRY(SlirpState) entry;
Slirp *slirp;
+ Notifier exit_notifier;
#ifndef _WIN32
char smb_dir[128];
#endif
return size;
}
+static void slirp_smb_exit(Notifier *n, void *data)
+{
+ SlirpState *s = container_of(n, SlirpState, exit_notifier);
+ slirp_smb_cleanup(s);
+}
+
static void net_slirp_cleanup(NetClientState *nc)
{
SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
slirp_cleanup(s->slirp);
+ if (s->exit_notifier.notify) {
+ qemu_remove_exit_notifier(&s->exit_notifier);
+ }
slirp_smb_cleanup(s);
QTAILQ_REMOVE(&slirp_stacks, s, entry);
}
static NetClientInfo net_slirp_info = {
- .type = NET_CLIENT_OPTIONS_KIND_USER,
+ .type = NET_CLIENT_DRIVER_USER,
.size = sizeof(SlirpState),
.receive = net_slirp_receive,
.cleanup = net_slirp_cleanup,
static int net_slirp_init(NetClientState *peer, const char *model,
const char *name, int restricted,
- const char *vnetwork, const char *vhost,
- const char *vprefix6, int vprefix6_len,
+ bool ipv4, const char *vnetwork, const char *vhost,
+ bool ipv6, const char *vprefix6, int vprefix6_len,
const char *vhost6,
const char *vhostname, const char *tftp_export,
const char *bootfile, const char *vdhcp_start,
char *end;
struct slirp_config_str *config;
+ if (!ipv4 && (vnetwork || vhost || vnameserver)) {
+ return -1;
+ }
+
+ if (!ipv6 && (vprefix6 || vhost6 || vnameserver6)) {
+ return -1;
+ }
+
+ if (!ipv4 && !ipv6) {
+ /* It doesn't make sense to disable both */
+ return -1;
+ }
+
if (!tftp_export) {
tftp_export = legacy_tftp_prefix;
}
s = DO_UPCAST(SlirpState, nc, nc);
- s->slirp = slirp_init(restricted, net, mask, host,
- ip6_prefix, vprefix6_len, ip6_host,
+ s->slirp = slirp_init(restricted, ipv4, net, mask, host,
+ ipv6, ip6_prefix, vprefix6_len, ip6_host,
vhostname, tftp_export, bootfile, dhcp,
dns, ip6_dns, dnssearch, s);
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
}
#endif
+ s->exit_notifier.notify = slirp_smb_exit;
+ qemu_add_exit_notifier(&s->exit_notifier);
return 0;
error:
#endif /* !defined(_WIN32) */
struct GuestFwd {
- CharDriverState *hd;
+ CharBackend hd;
struct in_addr server;
int port;
Slirp *slirp;
return -1;
}
} else {
- fwd = g_new(struct GuestFwd, 1);
- fwd->hd = qemu_chr_new(buf, p, NULL);
- if (!fwd->hd) {
+ Error *err = NULL;
+ Chardev *chr = qemu_chr_new(buf, p);
+
+ if (!chr) {
error_report("could not open guest forwarding device '%s'", buf);
+ return -1;
+ }
+
+ fwd = g_new(struct GuestFwd, 1);
+ qemu_chr_fe_init(&fwd->hd, chr, &err);
+ if (err) {
+ error_report_err(err);
g_free(fwd);
return -1;
}
- if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) {
+ if (slirp_add_exec(s->slirp, 3, &fwd->hd, &server, port) < 0) {
error_report("conflicting/invalid host:port in guest forwarding "
"rule '%s'", config_str);
g_free(fwd);
fwd->port = port;
fwd->slirp = s->slirp;
- qemu_chr_fe_claim_no_fail(fwd->hd);
- qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
- NULL, fwd);
+ qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
+ NULL, fwd, NULL, true);
}
return 0;
return ret;
}
-int net_init_slirp(const NetClientOptions *opts, const char *name,
+int net_init_slirp(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp)
{
/* FIXME error_setg(errp, ...) on failure */
int ret;
const NetdevUserOptions *user;
const char **dnssearch;
+ bool ipv4 = true, ipv6 = true;
+
+ assert(netdev->type == NET_CLIENT_DRIVER_USER);
+ user = &netdev->u.user;
- assert(opts->type == NET_CLIENT_OPTIONS_KIND_USER);
- user = opts->u.user;
+ if ((user->has_ipv6 && user->ipv6 && !user->has_ipv4) ||
+ (user->has_ipv4 && !user->ipv4)) {
+ ipv4 = 0;
+ }
+ if ((user->has_ipv4 && user->ipv4 && !user->has_ipv6) ||
+ (user->has_ipv6 && !user->ipv6)) {
+ ipv6 = 0;
+ }
vnet = user->has_net ? g_strdup(user->net) :
user->has_ip ? g_strdup_printf("%s/24", user->ip) :
net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
net_init_slirp_configs(user->guestfwd, 0);
- ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet,
- user->host, user->ip6_prefix, user->ip6_prefixlen,
- user->ip6_host, user->hostname, user->tftp,
+ ret = net_slirp_init(peer, "user", name, user->q_restrict,
+ ipv4, vnet, user->host,
+ ipv6, user->ipv6_prefix, user->ipv6_prefixlen,
+ user->ipv6_host, user->hostname, user->tftp,
user->bootfile, user->dhcpstart,
- user->dns, user->ip6_dns, user->smb,
+ user->dns, user->ipv6_dns, user->smb,
user->smbserver, dnssearch);
while (slirp_configs) {