Update Red Hat Copyright Notices
[nbdkit.git] / server / protocol-handshake-newstyle.c
blobb70732b6dc8a9f165c89ed8ba19e97bc2a2fe449
1 /* nbdkit
2 * Copyright Red Hat
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <string.h>
40 #include <unistd.h>
42 #include "internal.h"
43 #include "byte-swapping.h"
44 #include "nbd-protocol.h"
45 #include "protostrings.h"
46 #include "strndup.h"
48 /* Initial bound of client options we allow before giving up.
49 * However, a client that issues NBD_OPT_LIST is permitted to follow
50 * up with another round of options per export listed.
52 #define MAX_NR_OPTIONS 32
54 /* Receive newstyle options. */
55 static int
56 send_newstyle_option_reply (uint32_t option, uint32_t reply)
58 GET_CONN;
59 struct nbd_fixed_new_option_reply fixed_new_option_reply;
61 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
62 fixed_new_option_reply.option = htobe32 (option);
63 fixed_new_option_reply.reply = htobe32 (reply);
64 fixed_new_option_reply.replylen = htobe32 (0);
66 debug ("replying to %s with %s", name_of_nbd_opt (option),
67 name_of_nbd_rep (reply));
68 if (conn->send (&fixed_new_option_reply,
69 sizeof fixed_new_option_reply, 0) == -1) {
70 /* The protocol document says that the client is allowed to simply
71 * drop the connection after sending NBD_OPT_ABORT, or may read
72 * the reply.
74 if (option == NBD_OPT_ABORT)
75 debug ("write: %s: %m", name_of_nbd_opt (option));
76 else
77 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
78 return -1;
81 return 0;
84 /* Reply to NBD_OPT_LIST with the plugin's list of export names.
86 static int
87 send_newstyle_option_reply_exportnames (uint32_t option, size_t *nr_options)
89 GET_CONN;
90 struct nbd_fixed_new_option_reply fixed_new_option_reply;
91 size_t i, list_len;
92 CLEANUP_EXPORTS_FREE struct nbdkit_exports *exps = NULL;
94 exps = nbdkit_exports_new ();
95 if (exps == NULL)
96 return send_newstyle_option_reply (option, NBD_REP_ERR_TOO_BIG);
97 if (backend_list_exports (top, read_only, exps) == -1)
98 return send_newstyle_option_reply (option, NBD_REP_ERR_PLATFORM);
100 /* Allow additional per-export NBD_OPT_INFO and friends. */
101 list_len = nbdkit_exports_count (exps);
102 *nr_options += MAX_NR_OPTIONS * list_len;
104 for (i = 0; i < list_len; i++) {
105 const struct nbdkit_export export = nbdkit_get_export (exps, i);
106 size_t name_len = strlen (export.name);
107 size_t desc_len = export.description ? strlen (export.description) : 0;
108 uint32_t len;
110 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
111 fixed_new_option_reply.option = htobe32 (option);
112 fixed_new_option_reply.reply = htobe32 (NBD_REP_SERVER);
113 fixed_new_option_reply.replylen = htobe32 (name_len + sizeof (len) +
114 desc_len);
116 if (conn->send (&fixed_new_option_reply,
117 sizeof fixed_new_option_reply, SEND_MORE) == -1) {
118 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
119 return -1;
122 len = htobe32 (name_len);
123 if (conn->send (&len, sizeof len, SEND_MORE) == -1) {
124 nbdkit_error ("write: %s: %s: %m",
125 name_of_nbd_opt (option), "sending length");
126 return -1;
128 if (conn->send (export.name, name_len, SEND_MORE) == -1) {
129 nbdkit_error ("write: %s: %s: %m",
130 name_of_nbd_opt (option), "sending export name");
131 return -1;
133 if (conn->send (export.description, desc_len, 0) == -1) {
134 nbdkit_error ("write: %s: %s: %m",
135 name_of_nbd_opt (option), "sending export description");
136 return -1;
140 return send_newstyle_option_reply (option, NBD_REP_ACK);
143 static int
144 send_newstyle_option_reply_info_export (uint32_t option, uint32_t reply,
145 uint16_t info, uint64_t exportsize)
147 GET_CONN;
148 struct nbd_fixed_new_option_reply fixed_new_option_reply;
149 struct nbd_fixed_new_option_reply_info_export export;
151 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
152 fixed_new_option_reply.option = htobe32 (option);
153 fixed_new_option_reply.reply = htobe32 (reply);
154 fixed_new_option_reply.replylen = htobe32 (sizeof export);
155 export.info = htobe16 (info);
156 export.exportsize = htobe64 (exportsize);
157 export.eflags = htobe16 (conn->eflags);
159 if (conn->send (&fixed_new_option_reply,
160 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
161 conn->send (&export, sizeof export, 0) == -1) {
162 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
163 return -1;
166 return 0;
169 /* Can be used for NBD_INFO_NAME and NBD_INFO_DESCRIPTION. */
170 static int
171 send_newstyle_option_reply_info_str (uint32_t option, uint32_t reply,
172 uint16_t info, const char *str,
173 size_t len)
175 GET_CONN;
176 struct nbd_fixed_new_option_reply fixed_new_option_reply;
177 struct nbd_fixed_new_option_reply_info_name_or_desc name;
179 if (len == -1)
180 len = strlen (str);
181 assert (len <= NBD_MAX_STRING);
183 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
184 fixed_new_option_reply.option = htobe32 (option);
185 fixed_new_option_reply.reply = htobe32 (reply);
186 fixed_new_option_reply.replylen = htobe32 (sizeof info + len);
187 name.info = htobe16 (info);
189 if (conn->send (&fixed_new_option_reply,
190 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
191 conn->send (&name, sizeof name, SEND_MORE) == -1 ||
192 conn->send (str, len, 0) == -1) {
193 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
194 return -1;
197 return 0;
200 /* Send reply containing NBD_INFO_BLOCK_SIZE. */
201 static int
202 send_newstyle_option_reply_info_block_size (uint32_t option, uint32_t reply,
203 uint16_t info,
204 uint32_t minimum,
205 uint32_t preferred,
206 uint32_t maximum)
208 GET_CONN;
209 struct nbd_fixed_new_option_reply fixed_new_option_reply;
210 struct nbd_fixed_new_option_reply_info_block_size block_size;
212 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
213 fixed_new_option_reply.option = htobe32 (option);
214 fixed_new_option_reply.reply = htobe32 (reply);
215 fixed_new_option_reply.replylen = htobe32 (14);
216 block_size.info = htobe16 (info);
217 block_size.minimum = htobe32 (minimum);
218 block_size.preferred = htobe32 (preferred);
219 block_size.maximum = htobe32 (maximum);
221 if (conn->send (&fixed_new_option_reply,
222 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
223 conn->send (&block_size,
224 sizeof block_size, 0) == -1) {
225 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
226 return -1;
229 return 0;
232 static int
233 send_newstyle_option_reply_meta_context (uint32_t option, uint32_t reply,
234 uint32_t context_id,
235 const char *name)
237 GET_CONN;
238 struct nbd_fixed_new_option_reply fixed_new_option_reply;
239 struct nbd_fixed_new_option_reply_meta_context context;
240 const size_t namelen = strlen (name);
242 debug ("newstyle negotiation: %s: replying with %s id %d",
243 name_of_nbd_opt (option), name, context_id);
244 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
245 fixed_new_option_reply.option = htobe32 (option);
246 fixed_new_option_reply.reply = htobe32 (reply);
247 fixed_new_option_reply.replylen = htobe32 (sizeof context + namelen);
248 context.context_id = htobe32 (context_id);
250 if (conn->send (&fixed_new_option_reply,
251 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
252 conn->send (&context, sizeof context, SEND_MORE) == -1 ||
253 conn->send (name, namelen, 0) == -1) {
254 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
255 return -1;
258 return 0;
261 /* Sub-function during negotiate_handshake_newstyle, to uniformly handle
262 * a client hanging up on a message boundary.
264 static int ATTRIBUTE_FORMAT_PRINTF (3, 4)
265 conn_recv_full (void *buf, size_t len, const char *fmt, ...)
267 GET_CONN;
268 int r = conn->recv (buf, len);
269 va_list args;
271 if (r == -1) {
272 va_start (args, fmt);
273 nbdkit_verror (fmt, args);
274 va_end (args);
275 return -1;
277 if (r == 0) {
278 /* During negotiation, client EOF on message boundary is less
279 * severe than failure in the middle of the buffer. */
280 debug ("client closed input socket, closing connection");
281 return -1;
283 return r;
286 /* Sub-function of negotiate_handshake_newstyle_options below. It
287 * must be called on all non-error paths out of the options for-loop
288 * in that function, and must not cause any wire traffic.
290 static int
291 finish_newstyle_options (uint64_t *exportsize,
292 const char *exportname_in, uint32_t exportnamelen)
294 GET_CONN;
296 /* Since the exportname string passed here comes directly out of the
297 * NBD protocol make a temporary copy of the exportname into a
298 * \0-terminated buffer.
300 CLEANUP_FREE char *exportname = strndup (exportname_in, exportnamelen);
301 if (exportname == NULL) {
302 nbdkit_error ("strndup: %m");
303 return -1;
306 /* The NBD spec says that if the client later uses NBD_OPT_GO on a
307 * different export, then the context from the earlier
308 * NBD_OPT_SET_META_CONTEXT is not usable so discard it.
310 if (conn->exportname_from_set_meta_context &&
311 strcmp (conn->exportname_from_set_meta_context, exportname) != 0) {
312 debug ("newstyle negotiation: NBD_OPT_SET_META_CONTEXT export name \"%s\" "
313 "≠ final client exportname \"%s\", "
314 "so discarding the previous context",
315 conn->exportname_from_set_meta_context, exportname);
316 conn->meta_context_base_allocation = false;
319 if (protocol_common_open (exportsize, &conn->eflags, exportname) == -1)
320 return -1;
322 debug ("newstyle negotiation: flags: export 0x%x", conn->eflags);
323 return 0;
326 /* Check that the string sent as part of @option, beginning at @buf,
327 * and with a client-reported length of @len, fits within @maxlen
328 * bytes and is well-formed. If not, report an error mentioning
329 * @name.
331 static int
332 check_string (uint32_t option, char *buf, uint32_t len, uint32_t maxlen,
333 const char *name)
335 if (len > NBD_MAX_STRING || len > maxlen) {
336 nbdkit_error ("%s: %s too long", name_of_nbd_opt (option), name);
337 return -1;
339 if (strnlen (buf, len) != len) {
340 nbdkit_error ("%s: %s may not include NUL bytes",
341 name_of_nbd_opt (option), name);
342 return -1;
344 /* TODO: Check for valid UTF-8? */
345 return 0;
348 /* Sub-function of negotiate_handshake_newstyle_options, to grab and
349 * validate an export name.
351 static int
352 check_export_name (uint32_t option, char *buf,
353 uint32_t exportnamelen, uint32_t maxlen)
355 GET_CONN;
357 if (check_string (option, buf, exportnamelen, maxlen, "export name") == -1)
358 return -1;
360 debug ("newstyle negotiation: %s: client requested export '%.*s'",
361 name_of_nbd_opt (option), (int) exportnamelen, buf);
362 return 0;
365 static int
366 negotiate_handshake_newstyle_options (void)
368 GET_CONN;
369 struct nbd_new_option new_option;
370 size_t nr_options;
371 bool list_seen = false;
372 uint64_t version;
373 uint32_t option;
374 uint32_t optlen;
375 struct nbd_export_name_option_reply handshake_finish;
376 const char *optname;
377 uint64_t exportsize;
378 struct backend *b;
380 for (nr_options = MAX_NR_OPTIONS; nr_options > 0; --nr_options) {
381 CLEANUP_FREE char *data = NULL;
383 if (conn_recv_full (&new_option, sizeof new_option,
384 "reading option: conn->recv: %m") == -1)
385 return -1;
387 version = be64toh (new_option.version);
388 if (version != NBD_NEW_VERSION) {
389 nbdkit_error ("unknown option version %" PRIx64
390 ", expecting %" PRIx64,
391 version, NBD_NEW_VERSION);
392 return -1;
395 /* There is a maximum option length we will accept, regardless
396 * of the option type.
398 optlen = be32toh (new_option.optlen);
399 if (optlen > MAX_REQUEST_SIZE) {
400 nbdkit_error ("client option data too long (%" PRIu32 ")", optlen);
401 return -1;
403 data = malloc (optlen + 1); /* Allowing a trailing NUL helps some uses */
404 if (data == NULL) {
405 nbdkit_error ("malloc: %m");
406 return -1;
409 option = be32toh (new_option.option);
410 optname = name_of_nbd_opt (option);
412 /* If the client lacks fixed newstyle support, it should only send
413 * NBD_OPT_EXPORT_NAME.
415 if (!(conn->cflags & NBD_FLAG_FIXED_NEWSTYLE) &&
416 option != NBD_OPT_EXPORT_NAME) {
417 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID))
418 return -1;
419 continue;
422 /* In --tls=require / FORCEDTLS mode the only options allowed
423 * before TLS negotiation are NBD_OPT_ABORT and NBD_OPT_STARTTLS.
425 if (tls == 2 && !conn->using_tls &&
426 !(option == NBD_OPT_ABORT || option == NBD_OPT_STARTTLS)) {
427 if (option == NBD_OPT_EXPORT_NAME) {
428 debug ("newstyle negotiation: can't reply NBD_REP_ERR_TLS_REQD to %s",
429 name_of_nbd_opt (option));
430 return -1;
432 if (send_newstyle_option_reply (option, NBD_REP_ERR_TLS_REQD))
433 return -1;
434 if (conn_recv_full (data, optlen,
435 "waiting for starttls: %m") == -1)
436 return -1;
437 continue;
440 switch (option) {
441 case NBD_OPT_EXPORT_NAME:
442 if (conn_recv_full (data, optlen,
443 "read: %s: %m", name_of_nbd_opt (option)) == -1)
444 return -1;
445 if (check_export_name (option, data, optlen, optlen) == -1)
446 return -1;
448 /* We have to finish the handshake by sending handshake_finish.
449 * On failure, we have to disconnect.
451 if (finish_newstyle_options (&exportsize, data, optlen) == -1)
452 return -1;
454 memset (&handshake_finish, 0, sizeof handshake_finish);
455 handshake_finish.exportsize = htobe64 (exportsize);
456 handshake_finish.eflags = htobe16 (conn->eflags);
458 if (conn->send (&handshake_finish,
459 (conn->cflags & NBD_FLAG_NO_ZEROES)
460 ? offsetof (struct nbd_export_name_option_reply, zeroes)
461 : sizeof handshake_finish, 0) == -1) {
462 nbdkit_error ("write: %s: %m", optname);
463 return -1;
465 break;
467 case NBD_OPT_ABORT:
468 if (send_newstyle_option_reply (option, NBD_REP_ACK) == -1)
469 return -1;
470 debug ("client sent %s to abort the connection",
471 name_of_nbd_opt (option));
472 return -1;
474 case NBD_OPT_LIST:
475 if (optlen != 0) {
476 debug ("ignoring request, client sent unexpected payload: %s",
477 name_of_nbd_opt (option));
478 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
479 == -1)
480 return -1;
481 if (conn_recv_full (data, optlen,
482 "read: %s: %m", name_of_nbd_opt (option)) == -1)
483 return -1;
484 continue;
487 if (list_seen) {
488 debug ("newstyle negotiation: %s: export list already advertised",
489 name_of_nbd_opt (option));
490 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID) == -1)
491 return -1;
492 continue;
494 else {
495 /* Send back the exportname list. */
496 debug ("newstyle negotiation: %s: advertising exports",
497 name_of_nbd_opt (option));
498 if (send_newstyle_option_reply_exportnames (option, &nr_options) == -1)
499 return -1;
500 list_seen = true;
502 break;
504 case NBD_OPT_STARTTLS:
505 if (optlen != 0) {
506 debug ("ignoring request, client sent unexpected payload: %s",
507 name_of_nbd_opt (option));
508 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
509 == -1)
510 return -1;
511 if (conn_recv_full (data, optlen,
512 "read: %s: %m", name_of_nbd_opt (option)) == -1)
513 return -1;
514 continue;
517 if (tls == 0) { /* --tls=off (NOTLS mode). */
518 #ifdef HAVE_GNUTLS
519 #define NO_TLS_REPLY NBD_REP_ERR_POLICY
520 #else
521 #define NO_TLS_REPLY NBD_REP_ERR_UNSUP
522 #endif
523 if (send_newstyle_option_reply (option, NO_TLS_REPLY) == -1)
524 return -1;
526 else /* --tls=on or --tls=require */ {
527 /* We can't upgrade to TLS twice on the same connection. */
528 if (conn->using_tls) {
529 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID) == -1)
530 return -1;
531 continue;
534 /* We have to send the (unencrypted) reply before starting
535 * the handshake.
537 if (send_newstyle_option_reply (option, NBD_REP_ACK) == -1)
538 return -1;
540 /* Upgrade the connection to TLS. Also performs access control. */
541 if (crypto_negotiate_tls (conn->sockin, conn->sockout) == -1)
542 return -1;
543 conn->using_tls = true;
544 debug ("using TLS on this connection");
545 /* Wipe out any cached state. */
546 conn->structured_replies = false;
547 free (conn->exportname_from_set_meta_context);
548 conn->exportname_from_set_meta_context = NULL;
549 conn->meta_context_base_allocation = false;
550 for_each_backend (b) {
551 free (conn->default_exportname[b->i]);
552 conn->default_exportname[b->i] = NULL;
555 break;
557 case NBD_OPT_INFO:
558 case NBD_OPT_GO:
559 if (conn_recv_full (data, optlen, "read: %s: %m", optname) == -1)
560 return -1;
562 if (optlen < 6) { /* 32 bit export length + 16 bit nr info */
563 debug ("newstyle negotiation: %s option length < 6", optname);
565 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
566 == -1)
567 return -1;
568 continue;
572 uint32_t exportnamelen;
573 uint16_t nrinfos;
574 uint16_t info;
575 size_t i;
577 /* Validate the name length and number of INFO requests. */
578 memcpy (&exportnamelen, &data[0], 4);
579 exportnamelen = be32toh (exportnamelen);
580 if (exportnamelen > optlen-6 /* NB optlen >= 6, see above */) {
581 debug ("newstyle negotiation: %s: export name too long", optname);
582 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
583 == -1)
584 return -1;
585 continue;
587 memcpy (&nrinfos, &data[exportnamelen+4], 2);
588 nrinfos = be16toh (nrinfos);
589 if (optlen != 4 + exportnamelen + 2 + 2*nrinfos) {
590 debug ("newstyle negotiation: %s: "
591 "number of information requests incorrect", optname);
592 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
593 == -1)
594 return -1;
595 continue;
598 /* As with NBD_OPT_EXPORT_NAME we print the export name and
599 * save it in the connection. If an earlier
600 * NBD_OPT_SET_META_CONTEXT used an export name, it must match
601 * or else we drop the support for that context.
603 if (check_export_name (option, &data[4], exportnamelen,
604 optlen - 6) == -1) {
605 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
606 == -1)
607 return -1;
608 continue;
611 /* The spec is confusing, but it is required that we send back
612 * NBD_INFO_EXPORT, even if the client did not request it!
613 * qemu client in particular does not request this, but will
614 * fail if we don't send it. Note that if .open fails, but we
615 * succeed at .close, then we merely return an error to the
616 * client and let them try another NBD_OPT, rather than
617 * disconnecting.
619 if (finish_newstyle_options (&exportsize,
620 &data[4], exportnamelen) == -1) {
621 if (conn->top_context) {
622 if (backend_finalize (conn->top_context) == -1)
623 return -1;
624 backend_close (conn->top_context);
625 conn->top_context = NULL;
627 if (send_newstyle_option_reply (option, NBD_REP_ERR_UNKNOWN) == -1)
628 return -1;
629 continue;
632 assert (conn->top_context);
633 if (send_newstyle_option_reply_info_export (option,
634 NBD_REP_INFO,
635 NBD_INFO_EXPORT,
636 exportsize) == -1)
637 return -1;
639 /* For now we send NBD_INFO_NAME, NBD_INFO_DESCRIPTION and
640 * NBD_INFO_BLOCK_SIZE if requested, and ignore all other info
641 * requests (including NBD_INFO_EXPORT if it was requested,
642 * because we replied already above).
644 for (i = 0; i < nrinfos; ++i) {
645 memcpy (&info, &data[4 + exportnamelen + 2 + i*2], 2);
646 info = be16toh (info);
647 switch (info) {
648 case NBD_INFO_EXPORT: /* ignore - reply sent above */ break;
649 case NBD_INFO_NAME:
651 const char *name = &data[4];
652 size_t namelen = exportnamelen;
654 if (exportnamelen == 0) {
655 name = backend_default_export (top, read_only);
656 if (!name) {
657 debug ("newstyle negotiation: %s: "
658 "NBD_INFO_NAME: no name to send", optname);
659 break;
661 namelen = -1;
663 if (send_newstyle_option_reply_info_str (option,
664 NBD_REP_INFO,
665 NBD_INFO_NAME,
666 name, namelen) == -1)
667 return -1;
669 break;
670 case NBD_INFO_DESCRIPTION:
672 const char *desc = backend_export_description (conn->top_context);
674 if (!desc) {
675 debug ("newstyle negotiation: %s: "
676 "NBD_INFO_DESCRIPTION: no description to send",
677 optname);
678 break;
680 if (send_newstyle_option_reply_info_str (option,
681 NBD_REP_INFO,
682 NBD_INFO_DESCRIPTION,
683 desc, -1) == -1)
684 return -1;
686 break;
687 case NBD_INFO_BLOCK_SIZE:
689 uint32_t minimum, preferred, maximum;
691 if (backend_block_size (conn->top_context,
692 &minimum, &preferred, &maximum) == -1)
693 return -1;
694 if (minimum == 0) {
695 debug ("newstyle negotiation: %s: "
696 "NBD_INFO_BLOCK_SIZE: client requested but "
697 "no plugin or filter provided block size information, "
698 "ignoring client request",
699 optname);
700 break;
702 if (send_newstyle_option_reply_info_block_size
703 (option,
704 NBD_REP_INFO,
705 NBD_INFO_BLOCK_SIZE,
706 minimum, preferred, maximum) == -1)
707 return -1;
709 break;
710 default:
711 debug ("newstyle negotiation: %s: "
712 "ignoring NBD_INFO_* request %u (%s)",
713 optname, (unsigned) info, name_of_nbd_info (info));
714 break;
719 /* Unlike NBD_OPT_EXPORT_NAME, NBD_OPT_GO sends back an ACK
720 * or ERROR packet. If this was NBD_OPT_LIST, call .close.
722 if (send_newstyle_option_reply (option, NBD_REP_ACK) == -1)
723 return -1;
725 if (option == NBD_OPT_INFO) {
726 if (backend_finalize (conn->top_context) == -1)
727 return -1;
728 backend_close (conn->top_context);
729 conn->top_context = NULL;
732 break;
734 case NBD_OPT_STRUCTURED_REPLY:
735 if (optlen != 0) {
736 debug ("ignoring request, client sent unexpected payload: %s",
737 name_of_nbd_opt (option));
738 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
739 == -1)
740 return -1;
741 if (conn_recv_full (data, optlen,
742 "read: %s: %m", name_of_nbd_opt (option)) == -1)
743 return -1;
744 continue;
747 debug ("newstyle negotiation: %s: client requested structured replies",
748 name_of_nbd_opt (option));
750 if (no_sr) {
751 /* Must fail with ERR_UNSUP for qemu 4.2 to remain happy;
752 * but failing with ERR_POLICY would have been nicer.
754 if (send_newstyle_option_reply (option, NBD_REP_ERR_UNSUP) == -1)
755 return -1;
756 debug ("newstyle negotiation: %s: structured replies are disabled",
757 name_of_nbd_opt (option));
758 break;
761 if (conn->structured_replies) {
762 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID) == -1)
763 return -1;
764 debug ("newstyle negotiation: %s: structured replies already in use",
765 name_of_nbd_opt (option));
766 break;
769 if (send_newstyle_option_reply (option, NBD_REP_ACK) == -1)
770 return -1;
772 conn->structured_replies = true;
773 break;
775 case NBD_OPT_LIST_META_CONTEXT:
776 case NBD_OPT_SET_META_CONTEXT:
778 uint32_t opt_index;
779 uint32_t exportnamelen;
780 uint32_t nr_queries;
781 uint32_t querylen;
782 const char *what;
784 if (conn_recv_full (data, optlen, "read: %s: %m", optname) == -1)
785 return -1;
787 /* Note that we support base:allocation whether or not the plugin
788 * supports can_extents.
790 if (option == NBD_OPT_SET_META_CONTEXT && !conn->structured_replies) {
791 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
792 == -1)
793 return -1;
794 continue;
797 /* Minimum length of the option payload is:
798 * 32 bit export name length followed by empty export name
799 * + 32 bit number of queries followed by no queries
800 * = 8 bytes.
802 what = "optlen < 8";
803 if (optlen < 8) {
804 opt_meta_invalid_option_len:
805 debug ("newstyle negotiation: %s: invalid option length: %s",
806 optname, what);
808 if (send_newstyle_option_reply (option, NBD_REP_ERR_INVALID)
809 == -1)
810 return -1;
811 continue;
814 memcpy (&exportnamelen, &data[0], 4);
815 exportnamelen = be32toh (exportnamelen);
816 what = "validating export name";
817 if (check_export_name (option, &data[4], exportnamelen,
818 optlen - 8) == -1)
819 goto opt_meta_invalid_option_len;
821 /* Remember the export name: the NBD spec says that if the client
822 * later uses NBD_OPT_GO on a different export, then the context
823 * returned here is not usable.
825 if (option == NBD_OPT_SET_META_CONTEXT) {
826 conn->exportname_from_set_meta_context =
827 strndup (&data[4], exportnamelen);
828 if (conn->exportname_from_set_meta_context == NULL) {
829 nbdkit_error ("malloc: %m");
830 return -1;
834 opt_index = 4 + exportnamelen;
836 /* Read the number of queries. */
837 what = "reading number of queries";
838 if (opt_index+4 > optlen)
839 goto opt_meta_invalid_option_len;
840 memcpy (&nr_queries, &data[opt_index], 4);
841 nr_queries = be32toh (nr_queries);
842 opt_index += 4;
844 /* for LIST: nr_queries == 0 means return all meta contexts
845 * for SET: nr_queries == 0 means reset all contexts
847 debug ("newstyle negotiation: %s: %s count: %d", optname,
848 option == NBD_OPT_LIST_META_CONTEXT ? "query" : "set",
849 nr_queries);
850 if (option == NBD_OPT_SET_META_CONTEXT)
851 conn->meta_context_base_allocation = false;
852 if (nr_queries == 0) {
853 if (option == NBD_OPT_LIST_META_CONTEXT) {
854 if (send_newstyle_option_reply_meta_context (option,
855 NBD_REP_META_CONTEXT,
856 0, "base:allocation")
857 == -1)
858 return -1;
861 if (send_newstyle_option_reply (option, NBD_REP_ACK) == -1)
862 return -1;
864 else {
865 /* Read and answer each query. */
866 while (nr_queries > 0) {
867 what = "reading query string length";
868 if (opt_index+4 > optlen)
869 goto opt_meta_invalid_option_len;
870 memcpy (&querylen, &data[opt_index], 4);
871 querylen = be32toh (querylen);
872 opt_index += 4;
873 what = "reading query string";
874 if (check_string (option, &data[opt_index], querylen,
875 optlen - opt_index, "meta context query") == -1)
876 goto opt_meta_invalid_option_len;
878 debug ("newstyle negotiation: %s: %s %.*s",
879 optname,
880 option == NBD_OPT_LIST_META_CONTEXT ? "query" : "set",
881 (int) querylen, &data[opt_index]);
883 /* For LIST, "base:" returns all supported contexts in the
884 * base namespace. We only support "base:allocation".
886 if (option == NBD_OPT_LIST_META_CONTEXT &&
887 querylen == 5 &&
888 strncmp (&data[opt_index], "base:", 5) == 0) {
889 if (send_newstyle_option_reply_meta_context
890 (option, NBD_REP_META_CONTEXT,
891 0, "base:allocation") == -1)
892 return -1;
894 /* "base:allocation" requested by name. */
895 else if (querylen == 15 &&
896 strncmp (&data[opt_index], "base:allocation", 15) == 0) {
897 if (send_newstyle_option_reply_meta_context
898 (option, NBD_REP_META_CONTEXT,
899 option == NBD_OPT_SET_META_CONTEXT
900 ? base_allocation_id : 0,
901 "base:allocation") == -1)
902 return -1;
903 if (option == NBD_OPT_SET_META_CONTEXT)
904 conn->meta_context_base_allocation = true;
906 /* Every other query must be ignored. */
908 opt_index += querylen;
909 nr_queries--;
911 if (send_newstyle_option_reply (option, NBD_REP_ACK) == -1)
912 return -1;
914 debug ("newstyle negotiation: %s: reply complete", optname);
916 break;
918 default:
919 /* Unknown option. */
920 if (send_newstyle_option_reply (option, NBD_REP_ERR_UNSUP) == -1)
921 return -1;
922 if (conn_recv_full (data, optlen,
923 "reading unknown option data: conn->recv: %m") == -1)
924 return -1;
927 /* Note, since it's not very clear from the protocol doc, that the
928 * client must send NBD_OPT_EXPORT_NAME or NBD_OPT_GO last, and
929 * that ends option negotiation.
931 if (option == NBD_OPT_EXPORT_NAME || option == NBD_OPT_GO)
932 break;
935 if (nr_options == 0) {
936 nbdkit_error ("client spent too much time negotiating without selecting "
937 "an export");
938 return -1;
941 /* In --tls=require / FORCEDTLS mode, we must have upgraded to TLS
942 * by the time we finish option negotiation. If not, give up.
944 if (tls == 2 && !conn->using_tls) {
945 nbdkit_error ("non-TLS client tried to connect in --tls=require mode");
946 return -1;
949 return 0;
953 protocol_handshake_newstyle (void)
955 GET_CONN;
956 struct nbd_new_handshake handshake;
957 uint16_t gflags;
959 gflags = (NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES) & mask_handshake;
961 debug ("newstyle negotiation: flags: global 0x%x", gflags);
963 handshake.nbdmagic = htobe64 (NBD_MAGIC);
964 handshake.version = htobe64 (NBD_NEW_VERSION);
965 handshake.gflags = htobe16 (gflags);
967 if (conn->send (&handshake, sizeof handshake, 0) == -1) {
968 nbdkit_error ("write: %s: %m", "sending newstyle handshake");
969 return -1;
972 /* Client now sends us its 32 bit flags word ... */
973 if (conn_recv_full (&conn->cflags, sizeof conn->cflags,
974 "reading initial client flags: conn->recv: %m") == -1)
975 return -1;
976 conn->cflags = be32toh (conn->cflags);
977 /* ... which we check for accuracy. */
978 debug ("newstyle negotiation: client flags: 0x%x", conn->cflags);
979 if (conn->cflags & ~gflags) {
980 nbdkit_error ("client requested unexpected flags 0x%x", conn->cflags);
981 return -1;
984 /* Receive newstyle options. */
985 if (negotiate_handshake_newstyle_options () == -1)
986 return -1;
988 return 0;