#include "net/slirp.h"
-#ifndef _WIN32
+#if defined(CONFIG_SMBD_COMMAND)
#include <pwd.h>
#include <sys/wait.h>
#endif
+#include "net/eth.h"
#include "net/net.h"
#include "clients.h"
#include "hub.h"
#include "qapi/qmp/qdict.h"
#include "util.h"
#include "migration/register.h"
+#include "migration/vmstate.h"
#include "migration/qemu-file-types.h"
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
Slirp *slirp;
Notifier poll_notifier;
Notifier exit_notifier;
-#ifndef _WIN32
+#if defined(CONFIG_SMBD_COMMAND)
gchar *smb_dir;
#endif
GSList *fwd;
static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp);
static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp);
-#ifndef _WIN32
+#if defined(CONFIG_SMBD_COMMAND)
static int slirp_smb(SlirpState *s, const char *exported_dir,
struct in_addr vserver_addr, Error **errp);
static void slirp_smb_cleanup(SlirpState *s);
void *opaque)
{
SlirpState *s = opaque;
+ uint8_t min_pkt[ETH_ZLEN];
+ size_t min_pktsz = sizeof(min_pkt);
+
+ if (net_peer_needs_padding(&s->nc)) {
+ if (eth_pad_short_frame(min_pkt, &min_pktsz, pkt, pkt_len)) {
+ pkt = min_pkt;
+ pkt_len = min_pktsz;
+ }
+ }
return qemu_send_packet(&s->nc, pkt, pkt_len);
}
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
+typedef struct SlirpTimer SlirpTimer;
+struct SlirpTimer {
+ QEMUTimer timer;
+#if SLIRP_CHECK_VERSION(4,7,0)
+ Slirp *slirp;
+ SlirpTimerId id;
+ void *cb_opaque;
+#endif
+};
+
+#if SLIRP_CHECK_VERSION(4,7,0)
+static void net_slirp_init_completed(Slirp *slirp, void *opaque)
+{
+ SlirpState *s = opaque;
+ s->slirp = slirp;
+}
+
+static void net_slirp_timer_cb(void *opaque)
+{
+ SlirpTimer *t = opaque;
+ slirp_handle_timer(t->slirp, t->id, t->cb_opaque);
+}
+
+static void *net_slirp_timer_new_opaque(SlirpTimerId id,
+ void *cb_opaque, void *opaque)
+{
+ SlirpState *s = opaque;
+ SlirpTimer *t = g_new(SlirpTimer, 1);
+ t->slirp = s->slirp;
+ t->id = id;
+ t->cb_opaque = cb_opaque;
+ timer_init_full(&t->timer, NULL, QEMU_CLOCK_VIRTUAL,
+ SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
+ net_slirp_timer_cb, t);
+ return t;
+}
+#else
static void *net_slirp_timer_new(SlirpTimerCb cb,
void *cb_opaque, void *opaque)
{
- return timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
- SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
- cb, cb_opaque);
+ SlirpTimer *t = g_new(SlirpTimer, 1);
+ timer_init_full(&t->timer, NULL, QEMU_CLOCK_VIRTUAL,
+ SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
+ cb, cb_opaque);
+ return t;
}
+#endif
static void net_slirp_timer_free(void *timer, void *opaque)
{
- timer_free(timer);
+ SlirpTimer *t = timer;
+ timer_del(&t->timer);
+ g_free(t);
}
static void net_slirp_timer_mod(void *timer, int64_t expire_timer,
void *opaque)
{
- timer_mod(timer, expire_timer);
+ SlirpTimer *t = timer;
+ timer_mod(&t->timer, expire_timer);
}
static void net_slirp_register_poll_fd(int fd, void *opaque)
{
- qemu_fd_register(fd);
+#ifdef WIN32
+ AioContext *ctxt = qemu_get_aio_context();
+
+ if (WSAEventSelect(fd, event_notifier_get_handle(&ctxt->notifier),
+ FD_READ | FD_ACCEPT | FD_CLOSE |
+ FD_CONNECT | FD_WRITE | FD_OOB) != 0) {
+ error_setg_win32(&error_warn, WSAGetLastError(), "failed to WSAEventSelect()");
+ }
+#endif
}
static void net_slirp_unregister_poll_fd(int fd, void *opaque)
{
- /* no qemu_fd_unregister */
+#ifdef WIN32
+ if (WSAEventSelect(fd, NULL, 0) != 0) {
+ error_setg_win32(&error_warn, WSAGetLastError(), "failed to WSAEventSelect()");
+ }
+#endif
}
static void net_slirp_notify(void *opaque)
.send_packet = net_slirp_send_packet,
.guest_error = net_slirp_guest_error,
.clock_get_ns = net_slirp_clock_get_ns,
+#if SLIRP_CHECK_VERSION(4,7,0)
+ .init_completed = net_slirp_init_completed,
+ .timer_new_opaque = net_slirp_timer_new_opaque,
+#else
.timer_new = net_slirp_timer_new,
+#endif
.timer_free = net_slirp_timer_free,
.timer_mod = net_slirp_timer_mod,
.register_poll_fd = net_slirp_register_poll_fd,
struct in6_addr ip6_prefix;
struct in6_addr ip6_host;
struct in6_addr ip6_dns;
-#ifndef _WIN32
+#if defined(CONFIG_SMBD_COMMAND)
struct in_addr smbsrv = { .s_addr = 0 };
#endif
+ SlirpConfig cfg = { 0 };
NetClientState *nc;
SlirpState *s;
char buf[20];
int shift;
char *end;
struct slirp_config_str *config;
- NetdevUserOptions *stored;
- StringList **stored_hostfwd;
- StringList **stored_guestfwd;
if (!ipv4 && (vnetwork || vhost || vnameserver)) {
error_setg(errp, "IPv4 disabled but netmask/host/dns provided");
return -1;
}
-#ifndef _WIN32
+#if defined(CONFIG_SMBD_COMMAND)
if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
error_setg(errp, "Failed to parse SMB address");
return -1;
nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
- /* Store startup parameters */
- nc->stored_config = g_new0(NetdevInfo, 1);
- nc->stored_config->type = NET_BACKEND_USER;
- stored = &nc->stored_config->u.user;
-
- if (vhostname) {
- stored->has_hostname = true;
- stored->hostname = g_strdup(vhostname);
- }
-
- stored->has_q_restrict = true;
- stored->q_restrict = restricted;
-
- stored->has_ipv4 = true;
- stored->ipv4 = ipv4;
-
- stored->has_ipv6 = true;
- stored->ipv6 = ipv6;
-
- if (ipv4) {
- uint8_t *net_bytes = (uint8_t *)&net;
- uint8_t *mask_bytes = (uint8_t *)&mask;
-
- stored->has_net = true;
- stored->net = g_strdup_printf("%d.%d.%d.%d/%d.%d.%d.%d",
- net_bytes[0], net_bytes[1],
- net_bytes[2], net_bytes[3],
- mask_bytes[0], mask_bytes[1],
- mask_bytes[2], mask_bytes[3]);
-
- stored->has_host = true;
- stored->host = g_strdup(inet_ntoa(host));
- }
-
- if (tftp_export) {
- stored->has_tftp = true;
- stored->tftp = g_strdup(tftp_export);
- }
-
- if (bootfile) {
- stored->has_bootfile = true;
- stored->bootfile = g_strdup(bootfile);
- }
-
- if (vdhcp_start) {
- stored->has_dhcpstart = true;
- stored->dhcpstart = g_strdup(vdhcp_start);
- }
-
- if (ipv4) {
- stored->has_dns = true;
- stored->dns = g_strdup(inet_ntoa(dns));
- }
-
- if (dnssearch) {
- stored->has_dnssearch = true;
- StringList **stored_list = &stored->dnssearch;
-
- for (int i = 0; dnssearch[i]; i++) {
- String *element = g_new0(String, 1);
-
- element->str = g_strdup(dnssearch[i]);
- QAPI_LIST_APPEND(stored_list, element);
- }
- }
-
- if (vdomainname) {
- stored->has_domainname = true;
- stored->domainname = g_strdup(vdomainname);
- }
-
- if (ipv6) {
- char addrstr[INET6_ADDRSTRLEN];
- const char *res;
-
- stored->has_ipv6_prefix = true;
- stored->ipv6_prefix = g_strdup(vprefix6);
-
- stored->has_ipv6_prefixlen = true;
- stored->ipv6_prefixlen = vprefix6_len;
-
- res = inet_ntop(AF_INET6, &ip6_host,
- addrstr, sizeof(addrstr));
-
- stored->has_ipv6_host = true;
- stored->ipv6_host = g_strdup(res);
-
- res = inet_ntop(AF_INET6, &ip6_dns,
- addrstr, sizeof(addrstr));
-
- stored->has_ipv6_dns = true;
- stored->ipv6_dns = g_strdup(res);
- }
-
- if (smb_export) {
- stored->has_smb = true;
- stored->smb = g_strdup(smb_export);
- }
-
- if (vsmbserver) {
- stored->has_smbserver = true;
- stored->smbserver = g_strdup(vsmbserver);
- }
-
- if (tftp_server_name) {
- stored->has_tftp_server_name = true;
- stored->tftp_server_name = g_strdup(tftp_server_name);
- }
+ qemu_set_info_str(nc, "net=%s,restrict=%s", inet_ntoa(net),
+ restricted ? "on" : "off");
s = DO_UPCAST(SlirpState, nc, nc);
- s->slirp = slirp_init(restricted, ipv4, net, mask, host,
- ipv6, ip6_prefix, vprefix6_len, ip6_host,
- vhostname, tftp_server_name,
- tftp_export, bootfile, dhcp,
- dns, ip6_dns, dnssearch, vdomainname,
- &slirp_cb, s);
+ cfg.version = SLIRP_CHECK_VERSION(4,7,0) ? 4 : 1;
+ cfg.restricted = restricted;
+ cfg.in_enabled = ipv4;
+ cfg.vnetwork = net;
+ cfg.vnetmask = mask;
+ cfg.vhost = host;
+ cfg.in6_enabled = ipv6;
+ cfg.vprefix_addr6 = ip6_prefix;
+ cfg.vprefix_len = vprefix6_len;
+ cfg.vhost6 = ip6_host;
+ cfg.vhostname = vhostname;
+ cfg.tftp_server_name = tftp_server_name;
+ cfg.tftp_path = tftp_export;
+ cfg.bootfile = bootfile;
+ cfg.vdhcp_start = dhcp;
+ cfg.vnameserver = dns;
+ cfg.vnameserver6 = ip6_dns;
+ cfg.vdnssearch = dnssearch;
+ cfg.vdomainname = vdomainname;
+ s->slirp = slirp_new(&cfg, &slirp_cb, s);
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
/*
* specific version?
*/
g_assert(slirp_state_version() == 4);
- register_savevm_live("slirp", 0, slirp_state_version(),
- &savevm_slirp_state, s->slirp);
+ register_savevm_live("slirp", VMSTATE_INSTANCE_ID_ANY,
+ slirp_state_version(), &savevm_slirp_state, s->slirp);
s->poll_notifier.notify = net_slirp_poll_notify;
main_loop_poll_add_notifier(&s->poll_notifier);
- stored_hostfwd = &stored->hostfwd;
- stored_guestfwd = &stored->guestfwd;
-
for (config = slirp_configs; config; config = config->next) {
- String *element = g_new0(String, 1);
-
- element->str = g_strdup(config->str);
if (config->flags & SLIRP_CFG_HOSTFWD) {
if (slirp_hostfwd(s, config->str, errp) < 0) {
goto error;
}
- stored->has_hostfwd = true;
- QAPI_LIST_APPEND(stored_hostfwd, element);
} else {
if (slirp_guestfwd(s, config->str, errp) < 0) {
goto error;
}
- stored->has_guestfwd = true;
- QAPI_LIST_APPEND(stored_guestfwd, element);
}
}
-#ifndef _WIN32
+#if defined(CONFIG_SMBD_COMMAND)
if (smb_export) {
if (slirp_smb(s, smb_export, smbsrv, errp) < 0) {
goto error;
}
-#ifndef _WIN32
+#if defined(CONFIG_SMBD_COMMAND)
/* automatic user mode samba server configuration */
static void slirp_smb_cleanup(SlirpState *s)
return 0;
}
-#endif /* !defined(_WIN32) */
+#endif /* defined(CONFIG_SMBD_COMMAND) */
static int guestfwd_can_read(void *opaque)
{
ipv6 = 0;
}
- vnet = user->has_net ? g_strdup(user->net) :
- user->has_ip ? g_strdup_printf("%s/24", user->ip) :
+ vnet = user->net ? g_strdup(user->net) :
+ user->ip ? g_strdup_printf("%s/24", user->ip) :
NULL;
dnssearch = slirp_dnssearch(user->dnssearch);