=head1 NAME

nbdkit-info-plugin - serve client and server information

=head1 SYNOPSIS

 nbdkit info [mode=]exportname|base64exportname|address|
                    time|uptime|conntime

=head1 DESCRIPTION

C<nbdkit-info-plugin> is a test plugin which serves information about
the client and server in a disk image back to the client.

In its default mode (C<mode=exportname>) it converts the export name
passed from the client into a disk image.  C<mode=base64exportname> is
similar except the client must base64-encode the data in the export
name, allowing arbitrary binary data to be sent (see L</EXAMPLES>
below to make this clearer).  Export names are limited to 4096 bytes
by the NBD protocol, and nbdkit limits them to a few bytes smaller
than this.

C<mode=address> creates a disk which contains the client's IP address
and port number as a string.

C<mode=time>, C<mode=uptime> and C<mode=conntime> report server
wallclock time, nbdkit uptime, or time since the connection was opened
respectively and may be used to measure latency.

The plugin only supports read-only access.  To make the disk writable,
add L<nbdkit-cow-filter(1)> on top.

=head1 EXAMPLES

Create a “reflection disk”.  By setting the export name to C<"hello">
when we open it, a virtual disk of only 5 bytes containing these
characters is created.  We then display the contents:

 $ nbdkit --exit-with-parent info mode=exportname &
 $ nbdsh -u 'nbd://localhost/hello' -c - <<'EOF'
 size = h.get_size()
 print("size = %d" % size)
 buf = h.pread(size, 0)
 print("buf = %r" % buf)
 EOF

 size = 5
 buf = b"hello"

By running the info plugin, you can pass whole bootable VMs on the
qemu command line:

 $ nbdkit info mode=base64exportname
 $ qemu-system-x86_64 \
   -drive 'snapshot=on,file.driver=nbd,file.host=localhost,file.port=10809,file.export=
 tACwA80QtBOzCrABuRwAtgCyAL0ZfM0Q9CoqKiBIZWxsbyBmcm9tIG5iZGtp
 dCEgKioqDQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAVao=
 '

Another use for the info plugin is to send back the client's IP
address:

 $ nbdkit info mode=address
 $ nbdsh -u 'nbd://localhost' -c 'print(h.pread(h.get_size(), 0))'

which will print something like:

 b'[::1]:58912'

This plugin can also return the wallclock time:

 $ nbdkit info time --run 'nbdsh --connect $uri -c "sys.stdout.buffer.write(h.pread(12,0))" | hexdump -C'
 00000000  00 00 00 00 5d 8f 24 c7  00 04 24 01
                      └─────┬─────┘
                          ┌─┘
                          │
 $ date --date="@$(( 0x5d8f24c7 ))"
 Sat 28 Sep 10:15:51 BST 2019

or the nbdkit server uptime:

 $ nbdkit info uptime --run 'nbdsh --connect $uri -c "sys.stdout.buffer.write(h.pread(12,0))" | hexdump -C'
 00000000  00 00 00 00 00 00 00 00  00 00 60 4b
                                         └──┬──┘
                                   0x604b is about 25ms

or the time since the client opened the connection:

 $ nbdkit info conntime --run 'nbdsh --connect $uri -c "sys.stdout.buffer.write(h.pread(12,0))" | hexdump -C'
 00000000  00 00 00 00 00 00 00 00  00 00 00 e0
                                            └─┬─┘
                                     0xe0 is about 200μs

=head1 PARAMETERS

=over 4

=item [B<mode=>]B<address>

Send the client's IP address and client port number as a string in the
usual format.  For Unix sockets this sets the disk to the string
C<"unix"> to avoid leaking host paths.

=item [B<mode=>]B<base64exportname>

Send the export name passed by the client, assuming the client string
is base64 encoded.

This mode is only supported if nbdkit was compiled with GnuTLS E<ge>
3.6.0.  You can find out by checking if:

 $ nbdkit info --dump-plugin

contains:

 info_base64=yes

=item [B<mode=>]B<exportname>

Send the raw export name passed by the client.  Note the export name
cannot contain ASCII NUL characters.

This is the default mode.

=item [B<mode=>]B<time>

Reflect server wallclock time as seconds and microseconds since the
Epoch (see L<gettimeofday(2)>):

 ┌────────┬────────┬────────────┬──────────────────────┐
 │ offset │ length │ format     │ field                │
 ╞════════╪════════╪════════════╪══════════════════════╡
 │   0    │    8   │ 64 bit int │ seconds              │
 │        │        │ big endian │                      │
 ├────────┼────────┼────────────┼──────────────────────┤
 │   8    │    4   │ 32 bit int │ microseconds         │
 │        │        │ big endian │                      │
 └────────┴────────┴────────────┴──────────────────────┘

To be able to read this atomically you must read the whole 12 bytes in
a single request.

Note that exposing server time may be insecure.  It is safer to use
C<mode=uptime> or C<mode=conntime> instead.

=item [B<mode=>]B<uptime>

Reflect nbdkit uptime in seconds and microseconds (ie. both fields are
C<0> immediately after nbdkit starts, although a client would never be
able to observe this).  The format is exactly the same as for
C<mode=time> above.

In the current implementation this can jump forwards or backwards
discontinuously if the server time is adjusted.  In future we may fix
this bug.

=item [B<mode=>]B<conntime>

Reflect time since the NBD client connection was opened in seconds and
microseconds.  The format is exactly the same as for C<mode=time>
above.

In the current implementation this can jump forwards or backwards
discontinuously if the server time is adjusted.  In future we may fix
this bug.

C<mode=> is a magic config key and may be omitted in most cases.
See L<nbdkit(1)/Magic parameters>.

=back

=head1 FILES

=over 4

=item F<$plugindir/nbdkit-info-plugin.so>

The plugin.

Use C<nbdkit --dump-config> to find the location of C<$plugindir>.

=back

=head1 VERSION

C<nbdkit-info-plugin> first appeared in nbdkit 1.16.

=head1 SEE ALSO

L<nbdkit(1)>,
L<nbdkit-plugin(3)>,
L<nbdkit-cow-filter(1)>,
L<nbdkit-data-plugin(1)>.

=head1 AUTHORS

Richard W.M. Jones

=head1 COPYRIGHT

Copyright (C) 2019 Red Hat Inc.
