Skip to content

Commit

Permalink
nbd: make server compliant with fixed newstyle spec
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
berrange authored and bonzini committed Feb 16, 2016
1 parent f72d705 commit 26afa86
Showing 1 changed file with 46 additions and 23 deletions.
69 changes: 46 additions & 23 deletions nbd/server.c
Expand Up @@ -310,6 +310,7 @@ static int nbd_negotiate_handle_export_name(NBDClient *client, uint32_t length)
static int nbd_negotiate_options(NBDClient *client)
{
uint32_t flags;
bool fixedNewstyle = false;

/* Client sends:
[ 0 .. 3] client flags
Expand All @@ -332,14 +333,19 @@ static int nbd_negotiate_options(NBDClient *client)
}
TRACE("Checking client flags");
be32_to_cpus(&flags);
if (flags != 0 && flags != NBD_FLAG_C_FIXED_NEWSTYLE) {
LOG("Bad client flags received");
if (flags & NBD_FLAG_C_FIXED_NEWSTYLE) {
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;
}

while (1) {
int ret;
uint32_t tmp, length;
uint32_t clientflags, length;
uint64_t magic;

if (nbd_negotiate_read(client->ioc, &magic, sizeof(magic)) !=
Expand All @@ -353,10 +359,12 @@ static int nbd_negotiate_options(NBDClient *client)
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");
return -EINVAL;
}
clientflags = be32_to_cpu(clientflags);

if (nbd_negotiate_read(client->ioc, &length, sizeof(length)) !=
sizeof(length)) {
Expand All @@ -365,26 +373,41 @@ static int nbd_negotiate_options(NBDClient *client)
}
length = be32_to_cpu(length);

TRACE("Checking option");
switch (be32_to_cpu(tmp)) {
case NBD_OPT_LIST:
ret = nbd_negotiate_handle_list(client, length);
if (ret < 0) {
return ret;
TRACE("Checking option 0x%x", clientflags);
if (fixedNewstyle) {
switch (clientflags) {
case NBD_OPT_LIST:
ret = nbd_negotiate_handle_list(client, length);
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;
}
} 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);

default:
TRACE("Unsupported option 0x%x", clientflags);
return -EINVAL;
}
break;

case NBD_OPT_ABORT:
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;
}
}
}
Expand Down

0 comments on commit 26afa86

Please sign in to comment.