From nobody Sat Feb 7 11:05:26 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) client-ip=207.211.31.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 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=1594319839; cv=none; d=zohomail.com; s=zohoarc; b=l+jMITltuH46AGGOoKmEmsU7QxvRVUYM4U1NoH+k3dUuAioX/dBUxyoZo84U43OIGTW4HEmHw290EEs+7uoY9yfRu3R8r7kHu+GgrpX4oTsqYJuwXKQu+/Bt/FOUcdC7rQkNTUNsbgo1LcBXpyW62ydCVY50+80QW096m+uRUYY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1594319839; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=9gyIBViqYYAZrbldjgIkUDWuRRpCIpZAm18qz3kokT8=; b=VOwaRfBXdqBqLrrE1TeK3zo0keJIYu0czedQES+lkJroklg6SR2T5idiw9hO6FBfIncmc7a+VQanWJOlUlVvyKjYU9vM983Ri+kmO3rQmgAG0ghBgmSU8ZJFitELcKkY0R9GvQzX7eaWHDl0PqbcJ/ApwpIrzS5NlyD0+JCeAqg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by mx.zohomail.com with SMTPS id 1594319839493573.9842482836591; Thu, 9 Jul 2020 11:37:19 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-387-YQ5ZAKF2MlKTuazVaF0anQ-1; Thu, 09 Jul 2020 14:37:15 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B237F855AD1; Thu, 9 Jul 2020 18:37:08 +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 8BECE60C80; Thu, 9 Jul 2020 18:37:08 +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 5CB648435E; Thu, 9 Jul 2020 18:37:08 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 069Ib6b9023452 for ; Thu, 9 Jul 2020 14:37:06 -0400 Received: by smtp.corp.redhat.com (Postfix) id 2AE5560C80; Thu, 9 Jul 2020 18:37:06 +0000 (UTC) Received: from localhost.localdomain.com (unknown [10.36.110.45]) by smtp.corp.redhat.com (Postfix) with ESMTP id 387BF610F3; Thu, 9 Jul 2020 18:37:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1594319838; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=9gyIBViqYYAZrbldjgIkUDWuRRpCIpZAm18qz3kokT8=; b=VyjfUEm1Edomu4CoGcf89A3G4qCGuOFae/m/iNe8iBRa8Iy4PyGvz5B2EYdt2lfPkbAVje xCkaqx3cfQKmk2fUS8IfU2uOPbN2WH8xwcNmm8UMDjnfhwEdX6bfMZg4/soGeY2UpDTHvZ QNtBk+Y0QKOrMZNu+pJbl3hlTp8vdxQ= X-MC-Unique: YQ5ZAKF2MlKTuazVaF0anQ-1 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [libvirt PATCH 7/9] remote: introduce virtd-nc helper binary Date: Thu, 9 Jul 2020 19:36:44 +0100 Message-Id: <20200709183646.4016586-8-berrange@redhat.com> In-Reply-To: <20200709183646.4016586-1-berrange@redhat.com> References: <20200709183646.4016586-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) When accessing libvirtd over a SSH tunnel, the remote driver must spawn the remote 'nc' process, pointing it to the libvirtd socket path. This is problematic for a number of reasons: - The socket path varies according to the --prefix chosen at build time. The remote client is seeing the local prefix, but what we need is the remote prefix - The socket path varies according to remote env variables, such as the XDG_RUNTIME_DIR location. Again we see the local XDG_RUNTIME_DIR value, but what we need is the remote value (if any) - We can not able to autospawn the libvirtd daemon for session mode access To address these problems this patch introduces the 'virtd-nc' helper program which takes the URI for the remote driver as a CLI parameter. It then figures out the socket path to connect to using the same code as the remote driver does on the remote host. Signed-off-by: Daniel P. Berrang=C3=A9 --- build-aux/syntax-check.mk | 2 +- po/POTFILES.in | 1 + src/remote/Makefile.inc.am | 30 +++ src/remote/remote_nc.c | 424 +++++++++++++++++++++++++++++++++++++ src/rpc/virnetsocket.h | 1 + 5 files changed, 457 insertions(+), 1 deletion(-) create mode 100644 src/remote/remote_nc.c diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index d47a92b530..81b307ebe8 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -1967,7 +1967,7 @@ group-qemu-caps: # List all syntax-check exemptions: exclude_file_name_regexp--sc_avoid_strcase =3D ^tools/vsh\.h$$ =20 -_src1=3Dlibvirt-stream|qemu/qemu_monitor|util/vir(command|file|fdstream)|r= pc/virnetsocket|lxc/lxc_controller|locking/lock_daemon|logging/log_daemon +_src1=3Dlibvirt-stream|qemu/qemu_monitor|util/vir(command|file|fdstream)|r= pc/virnetsocket|lxc/lxc_controller|locking/lock_daemon|logging/log_daemon|r= emote/remote_nc _test1=3Dshunloadtest|virnettlscontexttest|virnettlssessiontest|vircgroupm= ock|commandhelper exclude_file_name_regexp--sc_avoid_write =3D \ ^(src/($(_src1))|tools/virsh-console|tests/($(_test1)))\.c$$ diff --git a/po/POTFILES.in b/po/POTFILES.in index 8fd391a63a..8fa47ec276 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -180,6 +180,7 @@ @SRCDIR@/src/remote/remote_daemon_dispatch.c @SRCDIR@/src/remote/remote_daemon_stream.c @SRCDIR@/src/remote/remote_driver.c +@SRCDIR@/src/remote/remote_nc.c @SRCDIR@/src/remote/remote_sockets.c @SRCDIR@/src/rpc/virkeepalive.c @SRCDIR@/src/rpc/virnetclient.c diff --git a/src/remote/Makefile.inc.am b/src/remote/Makefile.inc.am index 0ae97f4107..2527cc193f 100644 --- a/src/remote/Makefile.inc.am +++ b/src/remote/Makefile.inc.am @@ -221,6 +221,8 @@ if WITH_LIBVIRTD =20 sbin_PROGRAMS +=3D libvirtd virtproxyd =20 +libexec_PROGRAMS +=3D virt-nc + augeas_DATA +=3D \ remote/libvirtd.aug \ remote/virtproxyd.aug \ @@ -286,6 +288,34 @@ remote/virtproxyd.conf: remote/libvirtd.conf.in -e 's/[@]DAEMON_NAME[@]/virtproxyd/' \ $< > $@ =20 +virt_nc_SOURCES =3D \ + remote/remote_sockets.h \ + remote/remote_sockets.c \ + remote/remote_nc.c \ + $(NULL) + +virt_nc_CFLAGS =3D \ + $(LIBXML_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(WARN_CFLAGS) \ + $(PIE_CFLAGS) \ + -I$(srcdir)/access \ + -I$(srcdir)/rpc \ + $(NULL) + +virt_nc_LDFLAGS =3D \ + $(RELRO_LDFLAGS) \ + $(PIE_LDFLAGS) \ + $(NO_INDIRECT_LDFLAGS) \ + $(NO_UNDEFINED_LDFLAGS) \ + $(NULL) + +virt_nc_LDADD =3D \ + libvirt.la \ + $(LIBXML_LIBS) \ + $(NULL) + + INSTALL_DATA_DIRS +=3D remote =20 install-data-remote: diff --git a/src/remote/remote_nc.c b/src/remote/remote_nc.c new file mode 100644 index 0000000000..d304db1a04 --- /dev/null +++ b/src/remote/remote_nc.c @@ -0,0 +1,424 @@ +/* + * remote_nc.c: a netcat equivalent for remote driver tunnelling + * + * Copyright (C) 2020 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +#include + +#include + +#include "virnetsocket.h" +#include "viralloc.h" +#include "virlog.h" +#include "virgettext.h" +#include "virfile.h" + +#include "remote_sockets.h" + +#define VIR_FROM_THIS VIR_FROM_REMOTE + +VIR_LOG_INIT("remote.remote_nc"); + +struct virRemoteProxyBuffer { + size_t length; + size_t offset; + char *data; +}; + +typedef struct virRemoteProxy virRemoteProxy; +typedef virRemoteProxy *virRemoteProxyPtr; +struct virRemoteProxy { + bool quit; + virNetSocketPtr sock; + int stdinWatch; + int stdoutWatch; + + struct virRemoteProxyBuffer sockToTerminal; + struct virRemoteProxyBuffer terminalToSock; +}; + + +static void +virRemoteProxyShutdown(virRemoteProxyPtr proxy) +{ + if (proxy->sock) { + virNetSocketRemoveIOCallback(proxy->sock); + virNetSocketClose(proxy->sock); + virObjectUnref(proxy->sock); + proxy->sock =3D NULL; + } + VIR_FREE(proxy->sockToTerminal.data); + VIR_FREE(proxy->terminalToSock.data); + if (proxy->stdinWatch !=3D -1) + virEventRemoveHandle(proxy->stdinWatch); + if (proxy->stdoutWatch !=3D -1) + virEventRemoveHandle(proxy->stdoutWatch); + proxy->stdinWatch =3D -1; + proxy->stdoutWatch =3D -1; + if (!proxy->quit) + proxy->quit =3D true; +} + + +static void +virRemoteProxyEventOnSocket(virNetSocketPtr sock, + int events, void *opaque) +{ + virRemoteProxyPtr proxy =3D opaque; + + /* we got late event after proxy was shutdown */ + if (!proxy->sock) + return; + + if (events & VIR_EVENT_HANDLE_READABLE) { + size_t avail =3D proxy->sockToTerminal.length - + proxy->sockToTerminal.offset; + int got; + + if (avail < 1024) { + if (VIR_REALLOC_N(proxy->sockToTerminal.data, + proxy->sockToTerminal.length + 1024) < 0) { + virRemoteProxyShutdown(proxy); + return; + } + proxy->sockToTerminal.length +=3D 1024; + avail +=3D 1024; + } + + got =3D virNetSocketRead(sock, + proxy->sockToTerminal.data + + proxy->sockToTerminal.offset, + avail); + if (got =3D=3D -2) + return; /* blocking */ + if (got =3D=3D 0) { + VIR_DEBUG("EOF on socket, shutting down"); + virRemoteProxyShutdown(proxy); + return; + } + if (got < 0) { + virRemoteProxyShutdown(proxy); + return; + } + proxy->sockToTerminal.offset +=3D got; + if (proxy->sockToTerminal.offset) + virEventUpdateHandle(proxy->stdoutWatch, + VIR_EVENT_HANDLE_WRITABLE); + } + + if (events & VIR_EVENT_HANDLE_WRITABLE && + proxy->terminalToSock.offset) { + ssize_t done; + size_t avail; + done =3D virNetSocketWrite(proxy->sock, + proxy->terminalToSock.data, + proxy->terminalToSock.offset); + if (done =3D=3D -2) + return; /* blocking */ + if (done < 0) { + virRemoteProxyShutdown(proxy); + return; + } + memmove(proxy->terminalToSock.data, + proxy->terminalToSock.data + done, + proxy->terminalToSock.offset - done); + proxy->terminalToSock.offset -=3D done; + + avail =3D proxy->terminalToSock.length - proxy->terminalToSock.off= set; + if (avail > 1024) { + ignore_value(VIR_REALLOC_N(proxy->terminalToSock.data, + proxy->terminalToSock.offset + 1024= )); + proxy->terminalToSock.length =3D proxy->terminalToSock.offset = + 1024; + } + } + if (!proxy->terminalToSock.offset) + virNetSocketUpdateIOCallback(proxy->sock, + VIR_EVENT_HANDLE_READABLE); + + if (events & VIR_EVENT_HANDLE_ERROR || + events & VIR_EVENT_HANDLE_HANGUP) { + virRemoteProxyShutdown(proxy); + } +} + + +static void +virRemoteProxyEventOnStdin(int watch G_GNUC_UNUSED, + int fd G_GNUC_UNUSED, + int events, + void *opaque) +{ + virRemoteProxyPtr proxy =3D opaque; + + /* we got late event after console was shutdown */ + if (!proxy->sock) + return; + + if (events & VIR_EVENT_HANDLE_READABLE) { + size_t avail =3D proxy->terminalToSock.length - + proxy->terminalToSock.offset; + int got; + + if (avail < 1024) { + if (VIR_REALLOC_N(proxy->terminalToSock.data, + proxy->terminalToSock.length + 1024) < 0) { + virRemoteProxyShutdown(proxy); + return; + } + proxy->terminalToSock.length +=3D 1024; + avail +=3D 1024; + } + + got =3D read(fd, + proxy->terminalToSock.data + + proxy->terminalToSock.offset, + avail); + if (got < 0) { + if (errno !=3D EAGAIN) { + virReportSystemError(errno, "%s", _("cannot read from stdi= n")); + virRemoteProxyShutdown(proxy); + } + return; + } + if (got =3D=3D 0) { + VIR_DEBUG("EOF on stdin, shutting down"); + virRemoteProxyShutdown(proxy); + return; + } + + proxy->terminalToSock.offset +=3D got; + if (proxy->terminalToSock.offset) + virNetSocketUpdateIOCallback(proxy->sock, + VIR_EVENT_HANDLE_READABLE | + VIR_EVENT_HANDLE_WRITABLE); + } + + if (events & VIR_EVENT_HANDLE_ERROR) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error on stdin"= )); + virRemoteProxyShutdown(proxy); + return; + } + + if (events & VIR_EVENT_HANDLE_HANGUP) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdin")); + virRemoteProxyShutdown(proxy); + return; + } +} + + +static void +virRemoteProxyEventOnStdout(int watch G_GNUC_UNUSED, + int fd, + int events, + void *opaque) +{ + virRemoteProxyPtr proxy =3D opaque; + + /* we got late event after console was shutdown */ + if (!proxy->sock) + return; + + if (events & VIR_EVENT_HANDLE_WRITABLE && + proxy->sockToTerminal.offset) { + ssize_t done; + size_t avail; + done =3D write(fd, + proxy->sockToTerminal.data, + proxy->sockToTerminal.offset); + if (done < 0) { + if (errno !=3D EAGAIN) { + virReportSystemError(errno, "%s", _("cannot write to stdou= t")); + virRemoteProxyShutdown(proxy); + } + return; + } + memmove(proxy->sockToTerminal.data, + proxy->sockToTerminal.data + done, + proxy->sockToTerminal.offset - done); + proxy->sockToTerminal.offset -=3D done; + + avail =3D proxy->sockToTerminal.length - proxy->sockToTerminal.off= set; + if (avail > 1024) { + ignore_value(VIR_REALLOC_N(proxy->sockToTerminal.data, + proxy->sockToTerminal.offset + 1024= )); + proxy->sockToTerminal.length =3D proxy->sockToTerminal.offset = + 1024; + } + } + + if (!proxy->sockToTerminal.offset) + virEventUpdateHandle(proxy->stdoutWatch, 0); + + if (events & VIR_EVENT_HANDLE_ERROR) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("IO error stdout")); + virRemoteProxyShutdown(proxy); + return; + } + + if (events & VIR_EVENT_HANDLE_HANGUP) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF on stdout")); + virRemoteProxyShutdown(proxy); + return; + } +} + + +static int +virRemoteProxyRun(virNetSocketPtr sock) +{ + int ret =3D -1; + virRemoteProxy proxy =3D { + .sock =3D sock, + .stdinWatch =3D -1, + .stdoutWatch =3D -1, + }; + + virEventRegisterDefaultImpl(); + + if ((proxy.stdinWatch =3D virEventAddHandle(STDIN_FILENO, + VIR_EVENT_HANDLE_READABLE, + virRemoteProxyEventOnStdin, + &proxy, + NULL)) < 0) + goto cleanup; + + if ((proxy.stdoutWatch =3D virEventAddHandle(STDOUT_FILENO, + 0, + virRemoteProxyEventOnStdout, + &proxy, + NULL)) < 0) + goto cleanup; + + if (virNetSocketAddIOCallback(proxy.sock, + VIR_EVENT_HANDLE_READABLE, + virRemoteProxyEventOnSocket, + &proxy, + NULL) < 0) + goto cleanup; + + while (!proxy.quit) + virEventRunDefaultImpl(); + + if (virGetLastErrorCode() !=3D VIR_ERR_OK) + goto cleanup; + + ret =3D 0; + cleanup: + if (proxy.stdinWatch !=3D -1) + virEventRemoveHandle(proxy.stdinWatch); + if (proxy.stdoutWatch !=3D -1) + virEventRemoveHandle(proxy.stdoutWatch); + return ret; +} + +int main(int argc, char **argv) +{ + const char *uri_str =3D NULL; + g_autoptr(virURI) uri =3D NULL; + g_autofree char *driver =3D NULL; + remoteDriverTransport transport; + bool user =3D false; + bool autostart =3D false; + gboolean version =3D false; + gboolean readonly =3D false; + g_autofree char *sock_path =3D NULL; + g_autofree char *daemon_name =3D NULL; + g_autoptr(virNetSocket) sock =3D NULL; + GError *error =3D NULL; + g_autoptr(GOptionContext) context =3D NULL; + GOptionEntry entries[] =3D { + { "readonly", 'r', 0, G_OPTION_ARG_NONE, &readonly, "Connect read-= only", NULL }, + { "version", 'V', 0, G_OPTION_ARG_NONE, &version, "Display version= information", NULL }, + { NULL } + }; + + context =3D g_option_context_new("- libvirt socket proxy"); + g_option_context_add_main_entries(context, entries, PACKAGE); + if (!g_option_context_parse(context, &argc, &argv, &error)) { + g_printerr(_("option parsing failed: %s\n"), error->message); + exit(EXIT_FAILURE); + } + + if (version) { + g_print("%s (%s) %s\n", argv[0], PACKAGE_NAME, PACKAGE_VERSION); + exit(EXIT_SUCCESS); + } + + virSetErrorFunc(NULL, NULL); + virSetErrorLogPriorityFunc(NULL); + + if (virGettextInitialize() < 0 || + virErrorInitialize() < 0) { + g_printerr(_("%s: initialization failed\n"), argv[0]); + exit(EXIT_FAILURE); + } + + virFileActivateDirOverrideForProg(argv[0]); + + /* Initialize the log system */ + virLogSetFromEnv(); + + if (optind !=3D (argc - 1)) { + g_printerr("%s: expected a URI\n", argv[0]); + exit(EXIT_FAILURE); + } + + uri_str =3D argv[optind]; + VIR_DEBUG("Using URI %s", uri_str); + + if (!(uri =3D virURIParse(uri_str))) { + g_printerr(("%s: cannot parse '%s': %s\n"), + argv[0], uri_str, virGetLastErrorMessage()); + exit(EXIT_FAILURE); + } + + if (remoteSplitURIScheme(uri, &driver, &transport) < 0) { + g_printerr(_("%s: cannot parse URI transport '%s': %s\n"), + argv[0], uri_str, virGetLastErrorMessage()); + exit(EXIT_FAILURE); + } + + if (transport !=3D REMOTE_DRIVER_TRANSPORT_UNIX) { + g_printerr(_("%s: unexpected URI transport '%s'\n"), + argv[0], uri_str); + exit(EXIT_FAILURE); + } + + remoteGetURIDaemonInfo(uri, transport, &user, &autostart); + + sock_path =3D remoteGetUNIXSocket(transport, + REMOTE_DRIVER_MODE_AUTO, + driver, + !!readonly, + user, + &daemon_name); + + if (virNetSocketNewConnectUNIX(sock_path, autostart, daemon_name, &soc= k) < 0) { + g_printerr(_("%s: cannot connect to '%s': %s\n"), + argv[0], sock_path, virGetLastErrorMessage()); + exit(EXIT_FAILURE); + } + + if (virRemoteProxyRun(sock) < 0) { + g_printerr(_("%s: could not proxy traffic: %s\n"), + argv[0], virGetLastErrorMessage()); + exit(EXIT_FAILURE); + } + + exit(EXIT_SUCCESS); +} diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h index d39b270480..3996d264fb 100644 --- a/src/rpc/virnetsocket.h +++ b/src/rpc/virnetsocket.h @@ -34,6 +34,7 @@ typedef struct _virNetSocket virNetSocket; typedef virNetSocket *virNetSocketPtr; =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNetSocket, virObjectUnref); =20 typedef void (*virNetSocketIOFunc)(virNetSocketPtr sock, int events, --=20 2.26.2