nbd: make server compliant with fixed newstyle spec
If the client does not request the fixed new style protocol, then we should only accept NBD_OPT_EXPORT_NAME. All other options are only valid when fixed new style has been activated. The qemu-nbd client doesn't currently request fixed new style protocol, but this change won't break qemu-nbd, because it fortunately only ever uses NBD_OPT_EXPORT_NAME, so was never triggering the non-compliant server behaviour. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Message-Id: <1455129674-17255-9-git-send-email-berrange@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
f72d705f0d
commit
26afa868db
67
nbd/server.c
67
nbd/server.c
@ -310,6 +310,7 @@ fail:
|
|||||||
static int nbd_negotiate_options(NBDClient *client)
|
static int nbd_negotiate_options(NBDClient *client)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
bool fixedNewstyle = false;
|
||||||
|
|
||||||
/* Client sends:
|
/* Client sends:
|
||||||
[ 0 .. 3] client flags
|
[ 0 .. 3] client flags
|
||||||
@ -332,14 +333,19 @@ static int nbd_negotiate_options(NBDClient *client)
|
|||||||
}
|
}
|
||||||
TRACE("Checking client flags");
|
TRACE("Checking client flags");
|
||||||
be32_to_cpus(&flags);
|
be32_to_cpus(&flags);
|
||||||
if (flags != 0 && flags != NBD_FLAG_C_FIXED_NEWSTYLE) {
|
if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
|
||||||
LOG("Bad client flags received");
|
TRACE("Support supports fixed newstyle handshake");
|
||||||
|
fixedNewstyle = true;
|
||||||
|
flags &= ~NBD_FLAG_C_FIXED_NEWSTYLE;
|
||||||
|
}
|
||||||
|
if (flags != 0) {
|
||||||
|
TRACE("Unknown client flags 0x%x received", flags);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t tmp, length;
|
uint32_t clientflags, length;
|
||||||
uint64_t magic;
|
uint64_t magic;
|
||||||
|
|
||||||
if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=
|
if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=
|
||||||
@ -353,10 +359,12 @@ static int nbd_negotiate_options(NBDClient *client)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbd_negotiate_read(client->ioc, &tmp, sizeof(tmp)) != sizeof(tmp)) {
|
if (nbd_negotiate_read(client->ioc, &clientflags,
|
||||||
|
sizeof(clientflags)) != sizeof(clientflags)) {
|
||||||
LOG("read failed");
|
LOG("read failed");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
clientflags = be32_to_cpu(clientflags);
|
||||||
|
|
||||||
if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=
|
if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=
|
||||||
sizeof(length)) {
|
sizeof(length)) {
|
||||||
@ -365,26 +373,41 @@ static int nbd_negotiate_options(NBDClient *client)
|
|||||||
}
|
}
|
||||||
length = be32_to_cpu(length);
|
length = be32_to_cpu(length);
|
||||||
|
|
||||||
TRACE("Checking option");
|
TRACE("Checking option 0x%x", clientflags);
|
||||||
switch (be32_to_cpu(tmp)) {
|
if (fixedNewstyle) {
|
||||||
case NBD_OPT_LIST:
|
switch (clientflags) {
|
||||||
ret = nbd_negotiate_handle_list(client, length);
|
case NBD_OPT_LIST:
|
||||||
if (ret < 0) {
|
ret = nbd_negotiate_handle_list(client, length);
|
||||||
return ret;
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NBD_OPT_ABORT:
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
case NBD_OPT_EXPORT_NAME:
|
||||||
|
return nbd_negotiate_handle_export_name(client, length);
|
||||||
|
|
||||||
|
default:
|
||||||
|
TRACE("Unsupported option 0x%x", clientflags);
|
||||||
|
nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP,
|
||||||
|
clientflags);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
|
/*
|
||||||
|
* If broken new-style we should drop the connection
|
||||||
|
* for anything except NBD_OPT_EXPORT_NAME
|
||||||
|
*/
|
||||||
|
switch (clientflags) {
|
||||||
|
case NBD_OPT_EXPORT_NAME:
|
||||||
|
return nbd_negotiate_handle_export_name(client, length);
|
||||||
|
|
||||||
case NBD_OPT_ABORT:
|
default:
|
||||||
return -EINVAL;
|
TRACE("Unsupported option 0x%x", clientflags);
|
||||||
|
return -EINVAL;
|
||||||
case NBD_OPT_EXPORT_NAME:
|
}
|
||||||
return nbd_negotiate_handle_export_name(client, length);
|
|
||||||
|
|
||||||
default:
|
|
||||||
tmp = be32_to_cpu(tmp);
|
|
||||||
LOG("Unsupported option 0x%x", tmp);
|
|
||||||
nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP, tmp);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user