mirror of https://github.com/xemu-project/xemu.git
nbd: Send message along with server NBD_REP_ERR errors
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 <eblake@redhat.com> Message-Id: <1476469998-28592-8-git-send-email-eblake@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
526e5c6559
commit
3668328303
78
nbd/server.c
78
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);
|
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.
|
/* Send a single NBD_REP_SERVER reply to NBD_OPT_LIST, including payload.
|
||||||
* Return -errno on error, 0 on success. */
|
* Return -errno on error, 0 on success. */
|
||||||
static int nbd_negotiate_send_rep_list(QIOChannel *ioc, NBDExport *exp)
|
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) {
|
if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
return nbd_negotiate_send_rep(client->ioc,
|
return nbd_negotiate_send_rep_err(client->ioc,
|
||||||
NBD_REP_ERR_INVALID, NBD_OPT_LIST);
|
NBD_REP_ERR_INVALID, NBD_OPT_LIST,
|
||||||
|
"OPT_LIST should not have length");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For each export, send a NBD_REP_SERVER reply. */
|
/* For each export, send a NBD_REP_SERVER reply. */
|
||||||
|
@ -329,7 +362,8 @@ fail:
|
||||||
return rc;
|
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,
|
static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
|
||||||
uint32_t length)
|
uint32_t length)
|
||||||
{
|
{
|
||||||
|
@ -343,7 +377,8 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
|
||||||
if (nbd_negotiate_drop_sync(ioc, length) != length) {
|
if (nbd_negotiate_drop_sync(ioc, length) != length) {
|
||||||
return NULL;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,13 +509,15 @@ static int nbd_negotiate_options(NBDClient *client)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TRACE("Option 0x%" PRIx32 " not permitted before TLS",
|
|
||||||
clientflags);
|
|
||||||
if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
|
if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_TLS_REQD,
|
ret = nbd_negotiate_send_rep_err(client->ioc,
|
||||||
clientflags);
|
NBD_REP_ERR_TLS_REQD,
|
||||||
|
clientflags,
|
||||||
|
"Option 0x%" PRIx32
|
||||||
|
"not permitted before TLS",
|
||||||
|
clientflags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -506,27 +543,30 @@ static int nbd_negotiate_options(NBDClient *client)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if (client->tlscreds) {
|
if (client->tlscreds) {
|
||||||
TRACE("TLS already enabled");
|
ret = nbd_negotiate_send_rep_err(client->ioc,
|
||||||
ret = nbd_negotiate_send_rep(client->ioc,
|
NBD_REP_ERR_INVALID,
|
||||||
NBD_REP_ERR_INVALID,
|
clientflags,
|
||||||
clientflags);
|
"TLS already enabled");
|
||||||
} else {
|
} else {
|
||||||
TRACE("TLS not configured");
|
ret = nbd_negotiate_send_rep_err(client->ioc,
|
||||||
ret = nbd_negotiate_send_rep(client->ioc,
|
NBD_REP_ERR_POLICY,
|
||||||
NBD_REP_ERR_POLICY,
|
clientflags,
|
||||||
clientflags);
|
"TLS not configured");
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TRACE("Unsupported option 0x%" PRIx32, clientflags);
|
|
||||||
if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
|
if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
ret = nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP,
|
ret = nbd_negotiate_send_rep_err(client->ioc,
|
||||||
clientflags);
|
NBD_REP_ERR_UNSUP,
|
||||||
|
clientflags,
|
||||||
|
"Unsupported option 0x%"
|
||||||
|
PRIx32,
|
||||||
|
clientflags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue