From nobody Sat May 4 15:50:21 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1555593870; cv=none; d=zoho.com; s=zohoarc; b=aPmEcB7ZGTG2MMS4Ed+xqMqAJrwjsHV025HpQjMIbzWSNUBiW8F5USqvJPaOiXAnm7FMAYiBXGLXgZe5Ca2PY/rLDO7luQgThy5faPLh+L5ZTpCjmgkX69uBl3nudnLtdliGSLO1SFWtVGhbOKYvGCfECAcluoE2johuya5pBU8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1555593870; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To:ARC-Authentication-Results; bh=npITYtNwNhAL+NUb1cEvw/A+vRrUkRGKwOjhiT72f3M=; b=TrNWc4lf7YZenleboBTcbDIq80zU89nIHT+XoGp60gPMU9PMLtzo/UxTs7GP6RekUiz9EAB7hcXnvTyy1TnPPi2NVfQp2HyFZVCs6YydMt36lbVPnuqCHn5IdwpWVwU9l8d/jnK87QYgVV99ba33tP/WpOWxiwkKtOWKLo9JFXw= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1555593870600363.1236392407675; Thu, 18 Apr 2019 06:24:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 621A8307DAC8; Thu, 18 Apr 2019 13:24:28 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 44EF710A3926; Thu, 18 Apr 2019 13:24:27 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 283413FB10; Thu, 18 Apr 2019 13:24:25 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x3IDONpf002406 for ; Thu, 18 Apr 2019 09:24:23 -0400 Received: by smtp.corp.redhat.com (Postfix) id 48B1C608D3; Thu, 18 Apr 2019 13:24:23 +0000 (UTC) Received: from localhost (ovpn-112-32.ams2.redhat.com [10.36.112.32]) by smtp.corp.redhat.com (Postfix) with ESMTP id 26EC860856; Thu, 18 Apr 2019 13:24:14 +0000 (UTC) From: marcandre.lureau@redhat.com To: libvir-list@redhat.com Date: Thu, 18 Apr 2019 15:24:13 +0200 Message-Id: <20190418132413.23447-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [libvirt] [PATCH] RFC: use a slirp helper process X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Thu, 18 Apr 2019 13:24:29 +0000 (UTC) From: Marc-Andr=C3=A9 Lureau I am throwing this away for discussions, and early feedback. With the upcoming release of libslirp[1], we have an opportunity to run SLIRP networking in a separate process. This will allow for stricter security policies for both qemu & slirp, as slirp is notoriously not very safe (discussed on ML, various CVEs, and even the code says so explicitly in the comments), yet people rely on it regularly. For network type "user", libvirt could spawn an helper process (an experimental version is [2]). It would setup a socket pair between qemu and the helper and use -net socket. qemu could then be built without libslirp! (imho, qemu should deprecate built-in -net user support, and doesn't need to grow its own sub-process handling) This libvirt patch is a bit rough, I am not sure where things should go. In particular, how to manage the subprocesses properly (security aspects, and lifecycle etc), and how to deal with migration (prevent migrating from non-helper to helper version etc). It seems guestfwd has been non-functional for a while. This is also something that the current experimental helper doesn't support atm. Doing all the various "channel" types that libvirt/qemu support would be tedious, and probably unnecessary. But the underlying libslirp library support redirections the same way qemu does today, so it could be added if necessary. At this point, the slirp-helper doesn't handle migration. But is it really worth it? From a guest POV, it would look like packet lost or disconnection. Adding migration handling is possible, to avoid a disconnection event. How should it be done? via a libvirt provided socket for storage? via its own file transferred by libvirt? via qemu somehow (qemu wouldn't really know about the external process but would copy around the migration bits?). Does the helper need to have a "standard" & capabilities, similar to what is proposed for vhost-user [3]? This would allow for easier competing implementation to emerge (I have plans in mind, not using libslirp). Thanks for the feedback! [1] https://gitlab.freedesktop.org/slirp/libslirp [2] https://github.com/elmarco/libslirp-rs [3] https://git.qemu.org/?p=3Dqemu.git;a=3Dblob;f=3Ddocs/interop/vhost-user= .json Signed-off-by: Marc-Andr=C3=A9 Lureau --- m4/virt-driver-qemu.m4 | 5 ++ src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf | 3 ++ src/qemu/qemu_capabilities.c | 6 +++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 38 +++++++++++--- src/qemu/qemu_command.h | 3 +- src/qemu/qemu_conf.c | 7 ++- src/qemu/qemu_conf.h | 1 + src/qemu/qemu_domain.c | 11 ++++ src/qemu/qemu_domain.h | 3 ++ src/qemu/qemu_hotplug.c | 5 +- src/qemu/qemu_interface.c | 80 ++++++++++++++++++++++++++++++ src/qemu/qemu_interface.h | 6 +++ src/qemu/test_libvirtd_qemu.aug.in | 1 + 15 files changed, 161 insertions(+), 10 deletions(-) diff --git a/m4/virt-driver-qemu.m4 b/m4/virt-driver-qemu.m4 index a1d05bbd7f..705b1f592b 100644 --- a/m4/virt-driver-qemu.m4 +++ b/m4/virt-driver-qemu.m4 @@ -105,6 +105,11 @@ AC_DEFUN([LIBVIRT_DRIVER_CHECK_QEMU], [ [/usr/bin:/usr/libexec]) AC_DEFINE_UNQUOTED([QEMU_PR_HELPER], ["$QEMU_PR_HELPER"], [QEMU PR helper]) + AC_PATH_PROG([SLIRP_HELPER], [slirp-helper], + [/usr/bin/slirp-helper], + [/usr/bin:/usr/libexec]) + AC_DEFINE_UNQUOTED([SLIRP_HELPER], ["$SLIRP_HELPER"], + [slirp helper]) ]) =20 AC_DEFUN([LIBVIRT_DRIVER_RESULT_QEMU], [ diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index b311f02da6..15206454e0 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -88,6 +88,7 @@ module Libvirtd_qemu =3D | bool_entry "clear_emulator_capabilities" | str_entry "bridge_helper" | str_entry "pr_helper" + | str_entry "slirp_helper" | bool_entry "set_process_name" | int_entry "max_processes" | int_entry "max_files" diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 334b4cd4ee..725ae791c5 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -810,6 +810,9 @@ # used whenever are enabled for SCSI LUN devices. #pr_helper =3D "/usr/bin/qemu-pr-helper" =20 +# Path to the SLIRP networking helper. +#slirp_helper =3D "/usr/bin/slirp-helper" + # User for the swtpm TPM Emulator # # Default is 'tss'; this is the same user that tcsd (TrouSerS) installs diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f8ea66b577..86cef7b9ab 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -524,6 +524,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "scsi-disk.device_id", "virtio-pci-non-transitional", "overcommit", + "net-socket-dgram", ); =20 =20 @@ -4212,6 +4213,11 @@ virQEMUCapsInitQMPVersionCaps(virQEMUCapsPtr qemuCap= s) ARCH_IS_PPC64(qemuCaps->arch)) { virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_PSERIES_MAX_CPU_COMPAT); } + + /* -net socket,fd=3D with dgram socket (for ex, with slirp helper) */ + if (qemuCaps->version >=3D 3001092) { + virQEMUCapsSet(qemuCaps, QEMU_CAPS_NET_SOCKET_DGRAM); + } } =20 =20 diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 23ecef8c63..9db4c1bf2d 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -506,6 +506,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for = syntax-check */ QEMU_CAPS_SCSI_DISK_DEVICE_ID, /* 'device_id' property of scsi disk */ QEMU_CAPS_VIRTIO_PCI_TRANSITIONAL, /* virtio *-pci-{non-}transitional = devices */ QEMU_CAPS_OVERCOMMIT, /* -overcommit */ + QEMU_CAPS_NET_SOCKET_DGRAM, =20 QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9df7b7e8ea..6a047fa8f9 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4066,7 +4066,8 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, char **tapfd, size_t tapfdSize, char **vhostfd, - size_t vhostfdSize) + size_t vhostfdSize, + char *slirpfd) { bool is_tap =3D false; virBuffer buf =3D VIR_BUFFER_INITIALIZER; @@ -4137,6 +4138,12 @@ qemuBuildHostNetStr(virDomainNetDefPtr net, break; =20 case VIR_DOMAIN_NET_TYPE_USER: + if (slirpfd) { + virBufferAsprintf(&buf, "socket,fd=3D%s,", + slirpfd); + break; + } + virBufferAddLit(&buf, "user,"); for (i =3D 0; i < net->guestIP.nips; i++) { const virNetDevIPAddr *ip =3D net->guestIP.ips[i]; @@ -8721,10 +8728,10 @@ qemuInterfaceVhostuserConnect(virQEMUDriverPtr driv= er, =20 static int qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, + virDomainObjPtr vm, virLogManagerPtr logManager, virSecurityManagerPtr secManager, virCommandPtr cmd, - virDomainDefPtr def, virDomainNetDefPtr net, virQEMUCapsPtr qemuCaps, unsigned int bootindex, @@ -8733,6 +8740,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, size_t *nnicindexes, int **nicindexes) { + virDomainDefPtr def =3D vm->def; int ret =3D -1; char *nic =3D NULL; char *host =3D NULL; @@ -8743,12 +8751,13 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driv= er, size_t vhostfdSize =3D 0; char **tapfdName =3D NULL; char **vhostfdName =3D NULL; + int slirpfd =3D -1; + char *slirpfdName =3D NULL; virDomainNetType actualType =3D virDomainNetGetActualType(net); virNetDevBandwidthPtr actualBandwidth; bool requireNicdev =3D false; size_t i; =20 - if (!bootindex) bootindex =3D net->info.bootIndex; =20 @@ -8971,6 +8980,18 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr drive= r, goto cleanup; } =20 + if (actualType =3D=3D VIR_DOMAIN_NET_TYPE_USER && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_NET_SOCKET_DGRAM) && + !standalone) { + if (qemuInterfaceOpenSlirp(driver, vm, net, &slirpfd) < 0) { + goto cleanup; + } + virCommandPassFD(cmd, slirpfd, + VIR_COMMAND_PASS_FD_CLOSE_PARENT); + if (virAsprintf(&slirpfdName, "%d", slirpfd) < 0) + goto cleanup; + } + for (i =3D 0; i < tapfdSize; i++) { if (qemuSecuritySetTapFDLabel(driver->securityManager, def, tapfd[i]) < 0) @@ -8993,7 +9014,8 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, =20 if (!(host =3D qemuBuildHostNetStr(net, driver, tapfdName, tapfdSize, - vhostfdName, vhostfdSize))) + vhostfdName, vhostfdSize, + slirpfdName))) goto cleanup; virCommandAddArgList(cmd, "-netdev", host, NULL); =20 @@ -9032,6 +9054,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, virSetError(saved_err); virFreeError(saved_err); } + VIR_FREE(slirpfdName); for (i =3D 0; vhostfd && i < vhostfdSize && vhostfd[i] >=3D 0; i++) { if (ret < 0) VIR_FORCE_CLOSE(vhostfd[i]); @@ -9061,10 +9084,10 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driv= er, */ static int qemuBuildNetCommandLine(virQEMUDriverPtr driver, + virDomainObjPtr vm, virLogManagerPtr logManager, virSecurityManagerPtr secManager, virCommandPtr cmd, - virDomainDefPtr def, virQEMUCapsPtr qemuCaps, virNetDevVPortProfileOp vmop, bool standalone, @@ -9075,6 +9098,7 @@ qemuBuildNetCommandLine(virQEMUDriverPtr driver, size_t i; int last_good_net =3D -1; virErrorPtr originalError =3D NULL; + virDomainDefPtr def =3D vm->def; =20 if (def->nnets) { unsigned int bootNet =3D 0; @@ -9090,7 +9114,7 @@ qemuBuildNetCommandLine(virQEMUDriverPtr driver, for (i =3D 0; i < def->nnets; i++) { virDomainNetDefPtr net =3D def->nets[i]; =20 - if (qemuBuildInterfaceCommandLine(driver, logManager, secManag= er, cmd, def, net, + if (qemuBuildInterfaceCommandLine(driver, vm, logManager, secM= anager, cmd, net, qemuCaps, bootNet, vmop, standalone, nnicindexes, nicindexes) < 0) @@ -10818,7 +10842,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, if (qemuBuildFSDevCommandLine(cmd, def, qemuCaps) < 0) goto error; =20 - if (qemuBuildNetCommandLine(driver, logManager, secManager, cmd, def, + if (qemuBuildNetCommandLine(driver, vm, logManager, secManager, cmd, qemuCaps, vmop, standalone, nnicindexes, nicindexes, &bootHostdevNet) = < 0) goto error; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 9565a7a377..93696cb8d0 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -88,7 +88,8 @@ char *qemuBuildHostNetStr(virDomainNetDefPtr net, char **tapfd, size_t tapfdSize, char **vhostfd, - size_t vhostfdSize); + size_t vhostfdSize, + char *slirpfd); =20 /* Current, best practice */ char *qemuBuildNicDevStr(virDomainDefPtr def, diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index daea11dacb..e3cc0921a6 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -297,7 +297,8 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool priv= ileged) } =20 if (VIR_STRDUP(cfg->bridgeHelperName, QEMU_BRIDGE_HELPER) < 0 || - VIR_STRDUP(cfg->prHelperName, QEMU_PR_HELPER) < 0) + VIR_STRDUP(cfg->prHelperName, QEMU_PR_HELPER) < 0 || + VIR_STRDUP(cfg->slirpHelperName, SLIRP_HELPER) < 0) goto error; =20 cfg->clearEmulatorCapabilities =3D true; @@ -387,6 +388,7 @@ static void virQEMUDriverConfigDispose(void *obj) VIR_FREE(cfg->hugetlbfs); VIR_FREE(cfg->bridgeHelperName); VIR_FREE(cfg->prHelperName); + VIR_FREE(cfg->slirpHelperName); =20 VIR_FREE(cfg->saveImageFormat); VIR_FREE(cfg->dumpImageFormat); @@ -681,6 +683,9 @@ virQEMUDriverConfigLoadProcessEntry(virQEMUDriverConfig= Ptr cfg, if (virConfGetValueString(conf, "pr_helper", &cfg->prHelperName) < 0) return -1; =20 + if (virConfGetValueString(conf, "slirp_helper", &cfg->slirpHelperName)= < 0) + return -1; + if (virConfGetValueBool(conf, "set_process_name", &cfg->setProcessName= ) < 0) return -1; if (virConfGetValueUInt(conf, "max_processes", &cfg->maxProcesses) < 0) diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 983e74a3cf..7ae09f8f8c 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -160,6 +160,7 @@ struct _virQEMUDriverConfig { =20 char *bridgeHelperName; char *prHelperName; + char *slirpHelperName; =20 bool macFilter; =20 diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index f9f5ffc22b..626702c3ed 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2345,6 +2345,15 @@ qemuDomainObjPrivateXMLFormatPR(virBufferPtr buf, } =20 =20 +static void +qemuDomainObjPrivateXMLFormatSlirp(virBufferPtr buf, + qemuDomainObjPrivatePtr priv) +{ + if (priv->slirpPid) + virBufferAddLit(buf, "\n"); +} + + static int qemuDomainObjPrivateXMLFormatNBDMigrationSource(virBufferPtr buf, virStorageSourcePtr src, @@ -2555,6 +2564,8 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, =20 qemuDomainObjPrivateXMLFormatPR(buf, priv); =20 + qemuDomainObjPrivateXMLFormatSlirp(buf, priv); + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV)) virBufferAsprintf(buf, "\n", priv->noden= ameindex); =20 diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 06640a9510..f7937bf436 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -365,6 +365,9 @@ struct _qemuDomainObjPrivate { /* true if qemu-pr-helper process is running for the domain */ bool prDaemonRunning; =20 + /* todo: list of running slirp processes */ + pid_t slirpPid; + /* counter for generating node names for qemu disks */ unsigned long long nodenameindex; =20 diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index a4f7d111b1..f6ee9815ab 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1355,6 +1355,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, qemuDomainObjPrivatePtr priv =3D vm->privateData; virDomainDeviceDef dev =3D { VIR_DOMAIN_DEVICE_NET, { .net =3D net } }; virErrorPtr originalError =3D NULL; + char *slirpfdName =3D NULL; char **tapfdName =3D NULL; int *tapfd =3D NULL; size_t tapfdSize =3D 0; @@ -1592,7 +1593,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, =20 if (!(netstr =3D qemuBuildHostNetStr(net, driver, tapfdName, tapfdSize, - vhostfdName, vhostfdSize))) + vhostfdName, vhostfdSize, + slirpfdName))) goto cleanup; =20 qemuDomainObjEnterMonitor(driver, vm); @@ -1720,6 +1722,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, VIR_FREE(vhostfdName); VIR_FREE(charDevAlias); virObjectUnref(conn); + VIR_FREE(slirpfdName); virDomainCCWAddressSetFree(ccwaddrs); =20 return ret; diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index c8effa68f4..55423d6895 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -603,6 +603,86 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def, } =20 =20 +/** + * qemuInterfaceOpenSlirp: + * @net: network definition + * @slirpfd: slirp connection + * + * Returns: 0 on success + * -1 on failure + */ +int +qemuInterfaceOpenSlirp(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainNetDefPtr net, + int *slirpfd) +{ + int i, pair[2] =3D { -1, -1 }; + VIR_AUTOPTR(virCommand) cmd =3D NULL; + VIR_AUTOFREE(char *) cmdstr =3D NULL; + VIR_AUTOFREE(char *) addr =3D NULL; + virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); + qemuDomainObjPrivatePtr priv =3D vm->privateData; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) { + virReportSystemError(errno, "%s", _("failed to create socket")); + goto error; + } + + cmd =3D virCommandNew(cfg->slirpHelperName); + virCommandAddArgFormat(cmd, "--fd=3D%d", pair[1]); + virCommandPassFD(cmd, pair[1], + VIR_COMMAND_PASS_FD_CLOSE_PARENT); + + for (i =3D 0; i < net->guestIP.nips; i++) { + const virNetDevIPAddr *ip =3D net->guestIP.ips[i]; + const char *opt =3D ""; + + if (!(addr =3D virSocketAddrFormat(&ip->address))) + goto error; + + if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET)) + opt =3D "--net"; + if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6)) + opt =3D "--prefix-ipv6"; + + virCommandAddArgFormat(cmd, "%s=3D%s", opt, addr); + VIR_FREE(addr); + + if (ip->prefix) { + if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET)) { + virSocketAddr netmask; + VIR_AUTOFREE(char *) netmaskStr =3D NULL; + + if (virSocketAddrPrefixToNetmask(ip->prefix, &netmask, AF_= INET) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to translate prefix %d to net= mask"), + ip->prefix); + goto error; + } + if (!(netmaskStr =3D virSocketAddrFormat(&netmask))) + goto error; + virCommandAddArgFormat(cmd, "--mask=3D%s", netmaskStr); + } + if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6)) + virCommandAddArgFormat(cmd, "--prefix-length-ipv6=3D%u", i= p->prefix); + } + } + + virCommandClearCaps(cmd); + if (virCommandRunAsync(cmd, &priv->slirpPid) < 0) { + goto error; + } + + *slirpfd =3D pair[0]; + return 0; + +error: + VIR_FORCE_CLOSE(pair[0]); + return -1; +} + + /** * qemuInterfaceOpenVhostNet: * @def: domain definition diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h index f3ec540eda..de6195462b 100644 --- a/src/qemu/qemu_interface.h +++ b/src/qemu/qemu_interface.h @@ -55,4 +55,10 @@ int qemuInterfaceOpenVhostNet(virDomainDefPtr def, virDomainNetDefPtr net, int *vhostfd, size_t *vhostfdSize); + +int qemuInterfaceOpenSlirp(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainNetDefPtr net, + int *slirpfd); + #endif /* LIBVIRT_QEMU_INTERFACE_H */ diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qe= mu.aug.in index fea1d308b7..5796e5d1eb 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -102,5 +102,6 @@ module Test_libvirtd_qemu =3D } { "memory_backing_dir" =3D "/var/lib/libvirt/qemu/ram" } { "pr_helper" =3D "/usr/bin/qemu-pr-helper" } +{ "slirp_helper" =3D "/usr/bin/slirp-helper" } { "swtpm_user" =3D "tss" } { "swtpm_group" =3D "tss" } --=20 2.21.0.313.ge35b8cb8e2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list