From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41390) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1c1bwx-0001hS-2X for qemu-devel@nongnu.org; Tue, 01 Nov 2016 12:30:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1c1bww-0006dy-1f for qemu-devel@nongnu.org; Tue, 01 Nov 2016 12:30:11 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50088) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1c1bwv-0006dF-RB for qemu-devel@nongnu.org; Tue, 01 Nov 2016 12:30:09 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2BC0DC057FA4 for ; Tue, 1 Nov 2016 16:30:09 +0000 (UTC) From: Paolo Bonzini Date: Tue, 1 Nov 2016 17:29:27 +0100 Message-Id: <1478017783-7703-15-git-send-email-pbonzini@redhat.com> In-Reply-To: <1478017783-7703-1-git-send-email-pbonzini@redhat.com> References: <1478017783-7703-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PULL 14/30] nbd: Send message along with server NBD_REP_ERR errors List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org From: Eric Blake The NBD Protocol allows us to send human-readable messages along with any NBD_REP_ERR error during option negotiation; make use of this fact for clients that know what to do with our message. Signed-off-by: Eric Blake Message-Id: <1476469998-28592-8-git-send-email-eblake@redhat.com> Signed-off-by: Paolo Bonzini --- nbd/server.c | 78 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/nbd/server.c b/nbd/server.c index 0f0c68c..fa01e49 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -236,6 +236,38 @@ static int nbd_negotiate_send_rep(QIOChannel *ioc, uint32_t type, uint32_t opt) return nbd_negotiate_send_rep_len(ioc, type, opt, 0); } +/* Send an error reply. + * Return -errno on error, 0 on success. */ +static int GCC_FMT_ATTR(4, 5) +nbd_negotiate_send_rep_err(QIOChannel *ioc, uint32_t type, + uint32_t opt, const char *fmt, ...) +{ + va_list va; + char *msg; + int ret; + size_t len; + + va_start(va, fmt); + msg = g_strdup_vprintf(fmt, va); + va_end(va); + len = strlen(msg); + assert(len < 4096); + TRACE("sending error message \"%s\"", msg); + ret = nbd_negotiate_send_rep_len(ioc, type, opt, len); + if (ret < 0) { + goto out; + } + if (nbd_negotiate_write(ioc, msg, len) != len) { + LOG("write failed (error message)"); + ret = -EIO; + } else { + ret = 0; + } +out: + g_free(msg); + return ret; +} + /* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload. * Return -errno on error, 0 on success. */ static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp) @@ -281,8 +313,9 @@ static int nbd_negotiate_handle_list(NBDClient *client, uint32_t length) if (nbd_negotiate_drop_sync(client->ioc, length) != length) { return -EIO; } - return nbd_negotiate_send_rep(client->ioc, - NBD_REP_ERR_INVALID, NBD_OPT_LIST); + return nbd_negotiate_send_rep_err(client->ioc, + NBD_REP_ERR_INVALID, NBD_OPT_LIST, + "OPT_LIST should not have length"); } /* For each export, send a NBD_REP_SERVER reply. */ @@ -329,7 +362,8 @@ fail: return rc; } - +/* Handle NBD_OPT_STARTTLS. Return NULL to drop connection, or else the + * new channel for all further (now-encrypted) communication. */ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client, uint32_t length) { @@ -343,7 +377,8 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client, if (nbd_negotiate_drop_sync(ioc, length) != length) { return NULL; } - nbd_negotiate_send_rep(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS); + nbd_negotiate_send_rep_err(ioc, NBD_REP_ERR_INVALID, NBD_OPT_STARTTLS, + "OPT_STARTTLS should not have length"); return NULL; } @@ -474,13 +509,15 @@ static int nbd_negotiate_options(NBDClient *client) return -EINVAL; default: - TRACE("Option 0x%" PRIx32 " not permitted before TLS", - clientflags); if (nbd_negotiate_drop_sync(client->ioc, length) != length) { return -EIO; } - ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_TLS_REQD, - clientflags); + ret = nbd_negotiate_send_rep_err(client->ioc, + NBD_REP_ERR_TLS_REQD, + clientflags, + "Option 0x%" PRIx32 + "not permitted before TLS", + clientflags); if (ret < 0) { return ret; } @@ -506,27 +543,30 @@ static int nbd_negotiate_options(NBDClient *client) return -EIO; } if (client->tlscreds) { - TRACE("TLS already enabled"); - ret = nbd_negotiate_send_rep(client->ioc, - NBD_REP_ERR_INVALID, - clientflags); + ret = nbd_negotiate_send_rep_err(client->ioc, + NBD_REP_ERR_INVALID, + clientflags, + "TLS already enabled"); } else { - TRACE("TLS not configured"); - ret = nbd_negotiate_send_rep(client->ioc, - NBD_REP_ERR_POLICY, - clientflags); + ret = nbd_negotiate_send_rep_err(client->ioc, + NBD_REP_ERR_POLICY, + clientflags, + "TLS not configured"); } if (ret < 0) { return ret; } break; default: - TRACE("Unsupported option 0x%" PRIx32, clientflags); if (nbd_negotiate_drop_sync(client->ioc, length) != length) { return -EIO; } - ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP, - clientflags); + ret = nbd_negotiate_send_rep_err(client->ioc, + NBD_REP_ERR_UNSUP, + clientflags, + "Unsupported option 0x%" + PRIx32, + clientflags); if (ret < 0) { return ret; } -- 2.7.4