Similar to --no-sr, it can be handy for testing a client
implementation to have a server that can easily be forced into older
behaviors, without having to recompile a one-off hack into a server or
dig up an older server binary that lacked a newer feature.
To see the patch in action, try things like:
$ ./nbdkit -U - -fv --mask-handshake=0 null \
--run 'qemu-nbd --list -k $unixsocket'
Signed-off-by: Eric Blake
---
docs/nbdkit-protocol.pod | 25 ++-
docs/synopsis.txt| 2 +-
server/internal.h| 1 +
server/options.h | 2 ++
server/main.c| 30 ++--
server/protocol-handshake-newstyle.c | 4 ++--
6 files changed, 45 insertions(+), 19 deletions(-)
diff --git a/docs/nbdkit-protocol.pod b/docs/nbdkit-protocol.pod
index 3ae89063..272f4e5b 100644
--- a/docs/nbdkit-protocol.pod
+++ b/docs/nbdkit-protocol.pod
@@ -4,8 +4,8 @@ nbdkit - which parts of the NBD protocol nbdkit supports
=head1 SYNOPSIS
- nbdkit [-n|--newstyle] [--no-sr] [-o|--oldstyle] [-e|--exportname EXPORTNAME]
-[...]
+ nbdkit [-n|--newstyle] [--mask-handshake MASK] [--no-sr] [-o|--oldstyle]
+[-e|--exportname EXPORTNAME] [...]
=head1 DESCRIPTION
@@ -24,15 +24,30 @@ newstyle protocol is better in every respect than the
oldstyle
protocol and you should prefer it if possible. The newstyle protocol
also includes an extension where a client may request structured
replies for even more capabilities, such as sparse reads or obtaining
-block status.
+block status. By default, nbdkit advertises as many features as it
+can support (in some cases, this can be limited by what callbacks the
+plugin handles), even if the client does not negotiate to use all
+advertised features.
Use the I<-e> or I<--exportname> flag to set the optional exportname
for the newstyle protocol.
-Use the I<--no-sr> flag to force the newstyle protocol to decline any
-client request for structured replies.
+Nbdkit also includes some options that are useful mainly when
+performing integration tests, for proving whether clients have sane
+fallback behavior when dealing various older servers permitted by the
+NBD protocol. Use the I<--no-sr> flag to force the newstyle protocol
+to decline any client request for structured replies. Use the
+I<--mask-handshake> parameter to mask off particular global features
+which are advertised during new-style handshake (defaulting to all
+supported bits set). Clearing bit 0 (the low order bit) limits a
+client to using just C (and is incompatible with
+TLS or structured replies); clearing bit 1 causes the handshake to
+send more padding bytes in response to C. Other
+bits in the mask will only have an effect if the NBD protocol is
+extended in the future to define other global bits.
Use the I<-o> or I<--oldstyle> flag to force the oldstyle protocol.
+In this mode, I<--no-sr> and I<--mask-handshake> have no effect.
=head2 Common clients and the protocol they require
diff --git a/docs/synopsis.txt b/docs/synopsis.txt
index 04cd136d..5fc57fd1 100644
--- a/docs/synopsis.txt
+++ b/docs/synopsis.txt
@@ -3,7 +3,7 @@ nbdkit [-D|--debug PLUGIN|FILTER.FLAG=N]
[--filter FILTER ...] [-f|--foreground]
[-g|--group GROUP] [-i|--ipaddr IPADDR]
[--log stderr|syslog]
- [-n|--newstyle] [--no-sr] [-o|--oldstyle]
+ [-n|--newstyle] [--mask-handshake MASK] [--no-sr] [-o|--oldstyle]
[-P|--pidfile PIDFILE]
[-p|--port PORT] [-r|--readonly]
[--run CMD] [-s|--single] [--selinux-label LABEL]
diff --git a/server/internal.h b/server/internal.h
index 9314e8ff..5da3e3c3 100644
--- a/server/internal.h
+++ b/server/internal.h
@@ -90,6 +90,7 @@ extern const char *exportname;
extern bool foreground;
extern const char *ipaddr;
extern enum log_to log_to;
+extern unsigned mask_handshake;
extern bool newstyle;
extern bool no_sr;
extern const char *port;
diff --git a/server/options.h b/server/options.h
index a69f413a..c74e0b8b 100644
--- a/server/options.h
+++ b/server/options.h
@@ -46,6 +46,7 @@ enum {
FILTER_OPTION,
LOG_OPTION,
LONG_OPTIONS_OPTION,
+ MASK_HANDSHAKE_OPTION,
NO_SR_OPTION,
RUN_OPTION,
SELINUX_LABEL_OPTION,
@@ -74,6 +75,7 @@ static const struct option long_options[] = {
{ "ipaddr", required_argument, NULL, 'i' },
{ "log", required_argument, NULL, LOG_OPTION },
{ "long-options", no_argument, NULL, LONG_OPTIONS_OPTION },
+ { "mask-handshake", required_argument, NULL, MASK_HANDSHAKE_OPTION },
{ "new-style",no_argument, NULL, 'n' },
{ "newstyle", no_argument, NULL, 'n' },
{ "no-sr",no_argument, NULL, NO_SR_OPTION },
diff --git a/server/main.c b/server/main.c
index 22cf8d33..d433c1fa 100644
--- a/server/main.c
+++ b/server/main.c
@@ -67,6 +67,7 @@ const char *exportname; /* -e */
bool foreground;/*