*/
#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "net/slirp.h"
#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "slirp/libslirp.h"
-#include "slirp/ip6.h"
#include "chardev/char-fe.h"
#include "sysemu/sysemu.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
+#include "util.h"
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
{
} SlirpState;
static struct slirp_config_str *slirp_configs;
-static QTAILQ_HEAD(slirp_stacks, SlirpState) slirp_stacks =
+static QTAILQ_HEAD(, SlirpState) slirp_stacks =
QTAILQ_HEAD_INITIALIZER(slirp_stacks);
static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp);
static inline void slirp_smb_cleanup(SlirpState *s) { }
#endif
-void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
+static void net_slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
{
SlirpState *s = opaque;
.cleanup = net_slirp_cleanup,
};
+static void net_slirp_guest_error(const char *msg)
+{
+ qemu_log_mask(LOG_GUEST_ERROR, "%s", msg);
+}
+
+static int64_t net_slirp_clock_get_ns(void)
+{
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
+static const SlirpCb slirp_cb = {
+ .output = net_slirp_output,
+ .guest_error = net_slirp_guest_error,
+ .clock_get_ns = net_slirp_clock_get_ns,
+};
+
static int net_slirp_init(NetClientState *peer, const char *model,
const char *name, int restricted,
bool ipv4, const char *vnetwork, const char *vhost,
const char *vnameserver, const char *vnameserver6,
const char *smb_export, const char *vsmbserver,
const char **dnssearch, const char *vdomainname,
+ const char *tftp_server_name,
Error **errp)
{
/* default settings according to historic slirp */
}
#endif
-#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
- /* No inet_pton helper before Vista... */
- if (vprefix6) {
- /* Unsupported */
- error_setg(errp, "IPv6 prefix not supported");
- return -1;
- }
- memset(&ip6_prefix, 0, sizeof(ip6_prefix));
- ip6_prefix.s6_addr[0] = 0xfe;
- ip6_prefix.s6_addr[1] = 0xc0;
-#else
if (!vprefix6) {
vprefix6 = "fec0::";
}
error_setg(errp, "Failed to parse IPv6 prefix");
return -1;
}
-#endif
if (!vprefix6_len) {
vprefix6_len = 64;
}
if (vhost6) {
-#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
- error_setg(errp, "IPv6 host not supported");
- return -1;
-#else
if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
error_setg(errp, "Failed to parse IPv6 host");
return -1;
error_setg(errp, "IPv6 Host doesn't belong to network");
return -1;
}
-#endif
} else {
ip6_host = ip6_prefix;
ip6_host.s6_addr[15] |= 2;
}
if (vnameserver6) {
-#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
- error_setg(errp, "IPv6 DNS not supported");
- return -1;
-#else
if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
error_setg(errp, "Failed to parse IPv6 DNS");
return -1;
error_setg(errp, "IPv6 DNS doesn't belong to network");
return -1;
}
-#endif
} else {
ip6_dns = ip6_prefix;
ip6_dns.s6_addr[15] |= 3;
return -1;
}
+ if (vdomainname && strlen(vdomainname) > 255) {
+ error_setg(errp, "'domainname' parameter cannot exceed 255 bytes");
+ return -1;
+ }
+
+ if (vhostname && strlen(vhostname) > 255) {
+ error_setg(errp, "'vhostname' parameter cannot exceed 255 bytes");
+ return -1;
+ }
+
+ if (tftp_server_name && strlen(tftp_server_name) > 255) {
+ error_setg(errp, "'tftp-server-name' parameter cannot exceed 255 bytes");
+ return -1;
+ }
nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
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, vdomainname, s);
+ vhostname, tftp_server_name,
+ tftp_export, bootfile, dhcp,
+ dns, ip6_dns, dnssearch, vdomainname,
+ &slirp_cb, s);
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
for (config = slirp_configs; config; config = config->next) {
monitor_printf(mon, "unrecognized (hub-id, stackname) pair\n");
return NULL;
}
+ warn_report("Using 'hub-id' is deprecated, specify the netdev id "
+ "directly instead");
} else {
nc = qemu_find_netdev(name);
if (!nc) {
CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
g_free(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) {
+ if (slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 139) < 0 ||
+ slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 445) < 0) {
slirp_smb_cleanup(s);
g_free(smb_cmdline);
error_setg(errp, "Conflicting/invalid smbserver address");
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) {
+ if (slirp_add_exec(s->slirp, NULL, &p[4], &server, port) < 0) {
error_setg(errp, "Conflicting/invalid host:port in guest "
"forwarding rule '%s'", config_str);
return -1;
}
} else {
Error *err = NULL;
- Chardev *chr = qemu_chr_new(buf, p);
+ /*
+ * FIXME: sure we want to support implicit
+ * muxed monitors here?
+ */
+ Chardev *chr = qemu_chr_new_mux_mon(buf, p);
if (!chr) {
error_setg(errp, "Could not open guest forwarding device '%s'",
return -1;
}
- if (slirp_add_exec(s->slirp, 3, &fwd->hd, &server, port) < 0) {
+ if (slirp_add_exec(s->slirp, &fwd->hd, NULL, &server, port) < 0) {
error_setg(errp, "Conflicting/invalid host:port in guest "
"forwarding rule '%s'", config_str);
g_free(fwd);
QTAILQ_FOREACH(s, &slirp_stacks, entry) {
int id;
bool got_hub_id = net_hub_id_for_client(&s->nc, &id) == 0;
- monitor_printf(mon, "Hub %d (%s):\n",
+ char *info = slirp_connection_info(s->slirp);
+ monitor_printf(mon, "Hub %d (%s):\n%s",
got_hub_id ? id : -1,
- s->nc.name);
- slirp_connection_info(s->slirp, mon);
+ s->nc.name, info);
+ g_free(info);
}
}
user->ipv6_host, user->hostname, user->tftp,
user->bootfile, user->dhcpstart,
user->dns, user->ipv6_dns, user->smb,
- user->smbserver, dnssearch, user->domainname, errp);
+ user->smbserver, dnssearch, user->domainname,
+ user->tftp_server_name, errp);
while (slirp_configs) {
config = slirp_configs;