protocol: Wire up backend support for NBD_INFO_INIT_STATE
[nbdkit/ericb.git] / server / protocol-handshake-newstyle.c
blob5ba358cdc7b11913f21e8a7a20961b0c445ba3a9
1 /* nbdkit
2 * Copyright (C) 2013-2020 Red Hat Inc.
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"
47 /* Maximum number of client options we allow before giving up. */
48 #define MAX_NR_OPTIONS 32
50 /* Receive newstyle options. */
51 static int
52 send_newstyle_option_reply (struct connection *conn,
53 uint32_t option, uint32_t reply)
55 struct nbd_fixed_new_option_reply fixed_new_option_reply;
57 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
58 fixed_new_option_reply.option = htobe32 (option);
59 fixed_new_option_reply.reply = htobe32 (reply);
60 fixed_new_option_reply.replylen = htobe32 (0);
62 if (conn->send (conn,
63 &fixed_new_option_reply,
64 sizeof fixed_new_option_reply, 0) == -1) {
65 /* The protocol document says that the client is allowed to simply
66 * drop the connection after sending NBD_OPT_ABORT, or may read
67 * the reply.
69 if (option == NBD_OPT_ABORT)
70 debug ("write: %s: %m", name_of_nbd_opt (option));
71 else
72 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
73 return -1;
76 return 0;
79 static int
80 send_newstyle_option_reply_exportname (struct connection *conn,
81 uint32_t option, uint32_t reply)
83 struct nbd_fixed_new_option_reply fixed_new_option_reply;
84 size_t name_len = strlen (exportname);
85 uint32_t len;
87 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
88 fixed_new_option_reply.option = htobe32 (option);
89 fixed_new_option_reply.reply = htobe32 (reply);
90 fixed_new_option_reply.replylen = htobe32 (name_len + sizeof (len));
92 if (conn->send (conn,
93 &fixed_new_option_reply,
94 sizeof fixed_new_option_reply, SEND_MORE) == -1) {
95 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
96 return -1;
99 len = htobe32 (name_len);
100 if (conn->send (conn, &len, sizeof len, SEND_MORE) == -1) {
101 nbdkit_error ("write: %s: %s: %m",
102 name_of_nbd_opt (option), "sending length");
103 return -1;
105 if (conn->send (conn, exportname, name_len, 0) == -1) {
106 nbdkit_error ("write: %s: %s: %m",
107 name_of_nbd_opt (option), "sending export name");
108 return -1;
111 return 0;
114 static int
115 send_newstyle_option_reply_info_export (struct connection *conn,
116 uint32_t option, uint32_t reply,
117 uint16_t info, uint64_t exportsize)
119 struct nbd_fixed_new_option_reply fixed_new_option_reply;
120 struct nbd_fixed_new_option_reply_info_export export;
122 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
123 fixed_new_option_reply.option = htobe32 (option);
124 fixed_new_option_reply.reply = htobe32 (reply);
125 fixed_new_option_reply.replylen = htobe32 (sizeof export);
126 export.info = htobe16 (info);
127 export.exportsize = htobe64 (exportsize);
128 export.eflags = htobe16 (conn->eflags);
130 if (conn->send (conn,
131 &fixed_new_option_reply,
132 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
133 conn->send (conn, &export, sizeof export, 0) == -1) {
134 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
135 return -1;
138 return 0;
141 static int
142 send_newstyle_option_reply_info_init_state (struct connection *conn,
143 uint32_t option, uint32_t reply)
145 struct nbd_fixed_new_option_reply fixed_new_option_reply;
146 struct nbd_fixed_new_option_reply_info_init init;
147 uint16_t flags = 0;
148 int r;
150 r = backend_init_sparse (backend, conn);
151 if (r == -1)
152 return r;
153 if (r)
154 flags |= NBD_INIT_SPARSE;
156 r = backend_init_zero (backend, conn);
157 if (r == -1)
158 return r;
159 if (r)
160 flags |= NBD_INIT_ZERO;
162 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
163 fixed_new_option_reply.option = htobe32 (option);
164 fixed_new_option_reply.reply = htobe32 (reply);
165 fixed_new_option_reply.replylen = htobe32 (sizeof init);
166 init.info = htobe16 (NBD_INFO_INIT_STATE);
167 init.flags = htobe16 (flags);
169 if (conn->send (conn,
170 &fixed_new_option_reply,
171 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
172 conn->send (conn, &init, sizeof init, 0) == -1) {
173 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
174 return -1;
177 return 0;
180 static int
181 send_newstyle_option_reply_meta_context (struct connection *conn,
182 uint32_t option, uint32_t reply,
183 uint32_t context_id,
184 const char *name)
186 struct nbd_fixed_new_option_reply fixed_new_option_reply;
187 struct nbd_fixed_new_option_reply_meta_context context;
188 const size_t namelen = strlen (name);
190 debug ("newstyle negotiation: %s: replying with %s id %d",
191 name_of_nbd_opt (option), name, context_id);
192 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
193 fixed_new_option_reply.option = htobe32 (option);
194 fixed_new_option_reply.reply = htobe32 (reply);
195 fixed_new_option_reply.replylen = htobe32 (sizeof context + namelen);
196 context.context_id = htobe32 (context_id);
198 if (conn->send (conn,
199 &fixed_new_option_reply,
200 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
201 conn->send (conn, &context, sizeof context, SEND_MORE) == -1 ||
202 conn->send (conn, name, namelen, 0) == -1) {
203 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
204 return -1;
207 return 0;
210 /* Sub-function during negotiate_handshake_newstyle, to uniformly handle
211 * a client hanging up on a message boundary.
213 static int __attribute__ ((format (printf, 4, 5)))
214 conn_recv_full (struct connection *conn, void *buf, size_t len,
215 const char *fmt, ...)
217 int r = conn->recv (conn, buf, len);
218 va_list args;
220 if (r == -1) {
221 va_start (args, fmt);
222 nbdkit_verror (fmt, args);
223 va_end (args);
224 return -1;
226 if (r == 0) {
227 /* During negotiation, client EOF on message boundary is less
228 * severe than failure in the middle of the buffer. */
229 debug ("client closed input socket, closing connection");
230 return -1;
232 return r;
235 /* Sub-function of negotiate_handshake_newstyle_options below. It
236 * must be called on all non-error paths out of the options for-loop
237 * in that function, and must not cause any wire traffic.
239 static int
240 finish_newstyle_options (struct connection *conn, uint64_t *exportsize)
242 if (protocol_common_open (conn, exportsize, &conn->eflags) == -1)
243 return -1;
245 debug ("newstyle negotiation: flags: export 0x%x", conn->eflags);
246 return 0;
249 /* Check that the string sent as part of @option, beginning at @buf,
250 * and with a client-reported length of @len, fits within @maxlen
251 * bytes and is well-formed. If not, report an error mentioning
252 * @name.
254 static int
255 check_string (uint32_t option, char *buf, uint32_t len, uint32_t maxlen,
256 const char *name)
258 if (len > NBD_MAX_STRING || len > maxlen) {
259 nbdkit_error ("%s: %s too long", name_of_nbd_opt (option), name);
260 return -1;
262 if (strnlen (buf, len) != len) {
263 nbdkit_error ("%s: %s may not include NUL bytes",
264 name_of_nbd_opt (option), name);
265 return -1;
267 /* TODO: Check for valid UTF-8? */
268 return 0;
271 /* Sub-function of negotiate_handshake_newstyle_options, to grab and
272 * validate an export name.
274 static int
275 check_export_name (struct connection *conn, uint32_t option, char *buf,
276 uint32_t exportnamelen, uint32_t maxlen, bool save)
278 if (check_string (option, buf, exportnamelen, maxlen, "export name") == -1)
279 return -1;
281 assert (exportnamelen < sizeof conn->exportname);
282 if (save) {
283 if (exportnamelen != conn->exportnamelen ||
284 memcmp (conn->exportname, buf, exportnamelen) != 0)
285 conn->meta_context_base_allocation = false;
286 memcpy (conn->exportname, buf, exportnamelen);
287 conn->exportname[exportnamelen] = '\0';
288 conn->exportnamelen = exportnamelen;
290 debug ("newstyle negotiation: %s: client requested export '%.*s'",
291 name_of_nbd_opt (option), (int) exportnamelen, buf);
292 return 0;
295 static int
296 negotiate_handshake_newstyle_options (struct connection *conn)
298 struct nbd_new_option new_option;
299 size_t nr_options;
300 uint64_t version;
301 uint32_t option;
302 uint32_t optlen;
303 struct nbd_export_name_option_reply handshake_finish;
304 const char *optname;
305 uint64_t exportsize;
307 for (nr_options = 0; nr_options < MAX_NR_OPTIONS; ++nr_options) {
308 CLEANUP_FREE char *data = NULL;
310 if (conn_recv_full (conn, &new_option, sizeof new_option,
311 "reading option: conn->recv: %m") == -1)
312 return -1;
314 version = be64toh (new_option.version);
315 if (version != NBD_NEW_VERSION) {
316 nbdkit_error ("unknown option version %" PRIx64
317 ", expecting %" PRIx64,
318 version, NBD_NEW_VERSION);
319 return -1;
322 /* There is a maximum option length we will accept, regardless
323 * of the option type.
325 optlen = be32toh (new_option.optlen);
326 if (optlen > MAX_REQUEST_SIZE) {
327 nbdkit_error ("client option data too long (%" PRIu32 ")", optlen);
328 return -1;
330 data = malloc (optlen + 1); /* Allowing a trailing NUL helps some uses */
331 if (data == NULL) {
332 nbdkit_error ("malloc: %m");
333 return -1;
336 option = be32toh (new_option.option);
337 optname = name_of_nbd_opt (option);
339 /* If the client lacks fixed newstyle support, it should only send
340 * NBD_OPT_EXPORT_NAME.
342 if (!(conn->cflags & NBD_FLAG_FIXED_NEWSTYLE) &&
343 option != NBD_OPT_EXPORT_NAME) {
344 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID))
345 return -1;
346 continue;
349 /* In --tls=require / FORCEDTLS mode the only options allowed
350 * before TLS negotiation are NBD_OPT_ABORT and NBD_OPT_STARTTLS.
352 if (tls == 2 && !conn->using_tls &&
353 !(option == NBD_OPT_ABORT || option == NBD_OPT_STARTTLS)) {
354 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_TLS_REQD))
355 return -1;
356 continue;
359 switch (option) {
360 case NBD_OPT_EXPORT_NAME:
361 if (conn_recv_full (conn, data, optlen,
362 "read: %s: %m", name_of_nbd_opt (option)) == -1)
363 return -1;
364 if (check_export_name (conn, option, data, optlen, optlen, true) == -1)
365 return -1;
367 /* We have to finish the handshake by sending handshake_finish.
368 * On failure, we have to disconnect.
370 if (finish_newstyle_options (conn, &exportsize) == -1)
371 return -1;
373 memset (&handshake_finish, 0, sizeof handshake_finish);
374 handshake_finish.exportsize = htobe64 (exportsize);
375 handshake_finish.eflags = htobe16 (conn->eflags);
377 if (conn->send (conn,
378 &handshake_finish,
379 (conn->cflags & NBD_FLAG_NO_ZEROES)
380 ? offsetof (struct nbd_export_name_option_reply, zeroes)
381 : sizeof handshake_finish, 0) == -1) {
382 nbdkit_error ("write: %s: %m", optname);
383 return -1;
385 break;
387 case NBD_OPT_ABORT:
388 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
389 return -1;
390 debug ("client sent %s to abort the connection",
391 name_of_nbd_opt (option));
392 return -1;
394 case NBD_OPT_LIST:
395 if (optlen != 0) {
396 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
397 == -1)
398 return -1;
399 if (conn_recv_full (conn, data, optlen,
400 "read: %s: %m", name_of_nbd_opt (option)) == -1)
401 return -1;
402 continue;
405 /* Send back the exportname. */
406 debug ("newstyle negotiation: %s: advertising export '%s'",
407 name_of_nbd_opt (option), exportname);
408 if (send_newstyle_option_reply_exportname (conn, option,
409 NBD_REP_SERVER) == -1)
410 return -1;
412 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
413 return -1;
414 break;
416 case NBD_OPT_STARTTLS:
417 if (optlen != 0) {
418 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
419 == -1)
420 return -1;
421 if (conn_recv_full (conn, data, optlen,
422 "read: %s: %m", name_of_nbd_opt (option)) == -1)
423 return -1;
424 continue;
427 if (tls == 0) { /* --tls=off (NOTLS mode). */
428 #ifdef HAVE_GNUTLS
429 #define NO_TLS_REPLY NBD_REP_ERR_POLICY
430 #else
431 #define NO_TLS_REPLY NBD_REP_ERR_UNSUP
432 #endif
433 if (send_newstyle_option_reply (conn, option, NO_TLS_REPLY) == -1)
434 return -1;
436 else /* --tls=on or --tls=require */ {
437 /* We can't upgrade to TLS twice on the same connection. */
438 if (conn->using_tls) {
439 if (send_newstyle_option_reply (conn, option,
440 NBD_REP_ERR_INVALID) == -1)
441 return -1;
442 continue;
445 /* We have to send the (unencrypted) reply before starting
446 * the handshake.
448 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
449 return -1;
451 /* Upgrade the connection to TLS. Also performs access control. */
452 if (crypto_negotiate_tls (conn, conn->sockin, conn->sockout) == -1)
453 return -1;
454 conn->using_tls = true;
455 debug ("using TLS on this connection");
457 break;
459 case NBD_OPT_INFO:
460 case NBD_OPT_GO:
461 if (conn_recv_full (conn, data, optlen,
462 "read: %s: %m", optname) == -1)
463 return -1;
465 if (optlen < 6) { /* 32 bit export length + 16 bit nr info */
466 debug ("newstyle negotiation: %s option length < 6", optname);
468 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
469 == -1)
470 return -1;
471 continue;
475 uint32_t exportnamelen;
476 uint16_t nrinfos;
477 uint16_t info;
478 size_t i;
480 /* Validate the name length and number of INFO requests. */
481 memcpy (&exportnamelen, &data[0], 4);
482 exportnamelen = be32toh (exportnamelen);
483 if (exportnamelen > optlen-6 /* NB optlen >= 6, see above */) {
484 debug ("newstyle negotiation: %s: export name too long", optname);
485 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
486 == -1)
487 return -1;
488 continue;
490 memcpy (&nrinfos, &data[exportnamelen+4], 2);
491 nrinfos = be16toh (nrinfos);
492 if (optlen != 4 + exportnamelen + 2 + 2*nrinfos) {
493 debug ("newstyle negotiation: %s: "
494 "number of information requests incorrect", optname);
495 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
496 == -1)
497 return -1;
498 continue;
501 /* As with NBD_OPT_EXPORT_NAME we print the export name and
502 * save it in the connection. If an earlier
503 * NBD_OPT_SET_META_CONTEXT used an export name, it must match
504 * or else we drop the support for that context.
506 if (check_export_name (conn, option, &data[4], exportnamelen,
507 optlen - 6, true) == -1) {
508 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
509 == -1)
510 return -1;
511 continue;
514 /* The spec is confusing, but it is required that we send back
515 * NBD_INFO_EXPORT, even if the client did not request it!
516 * qemu client in particular does not request this, but will
517 * fail if we don't send it. Note that if .open fails, but we
518 * succeed at .close, then we merely return an error to the
519 * client and let them try another NBD_OPT, rather than
520 * disconnecting.
522 if (finish_newstyle_options (conn, &exportsize) == -1) {
523 if (backend_finalize (backend, conn) == -1)
524 return -1;
525 backend_close (backend, conn);
526 if (send_newstyle_option_reply (conn, option,
527 NBD_REP_ERR_UNKNOWN) == -1)
528 return -1;
529 continue;
532 if (send_newstyle_option_reply_info_export (conn, option,
533 NBD_REP_INFO,
534 NBD_INFO_EXPORT,
535 exportsize) == -1)
536 return -1;
538 /* The spec states that we may offer gratuitous replies,
539 * whether or not the client has requested them. Offering
540 * NBD_INFO_INIT_STATE unconditionally is easy to do.
542 if (send_newstyle_option_reply_info_init_state (conn, option,
543 NBD_REP_INFO) == -1)
544 return -1;
546 /* For now we ignore all other info requests (but we must
547 * ignore NBD_INFO_EXPORT or NBD_INFO_INIT_STATE if either was
548 * requested, because we replied already above). Therefore this
549 * loop doesn't do much at the moment.
551 for (i = 0; i < nrinfos; ++i) {
552 memcpy (&info, &data[4 + exportnamelen + 2 + i*2], 2);
553 info = be16toh (info);
554 switch (info) {
555 case NBD_INFO_EXPORT: /* ignore - reply sent above */ break;
556 case NBD_INFO_INIT_STATE: /* ignore - reply sent above */ break;
557 default:
558 debug ("newstyle negotiation: %s: "
559 "ignoring NBD_INFO_* request %u (%s)",
560 optname, (unsigned) info, name_of_nbd_info (info));
561 break;
566 /* Unlike NBD_OPT_EXPORT_NAME, NBD_OPT_GO sends back an ACK
567 * or ERROR packet. If this was NBD_OPT_LIST, call .close.
569 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
570 return -1;
572 if (option == NBD_OPT_INFO) {
573 if (backend_finalize (backend, conn) == -1)
574 return -1;
575 backend_close (backend, conn);
578 break;
580 case NBD_OPT_STRUCTURED_REPLY:
581 if (optlen != 0) {
582 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
583 == -1)
584 return -1;
585 if (conn_recv_full (conn, data, optlen,
586 "read: %s: %m", name_of_nbd_opt (option)) == -1)
587 return -1;
588 continue;
591 debug ("newstyle negotiation: %s: client requested structured replies",
592 name_of_nbd_opt (option));
594 if (no_sr) {
595 /* Must fail with ERR_UNSUP for qemu 4.2 to remain happy;
596 * but failing with ERR_POLICY would have been nicer.
598 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_UNSUP) == -1)
599 return -1;
600 debug ("newstyle negotiation: %s: structured replies are disabled",
601 name_of_nbd_opt (option));
602 break;
605 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
606 return -1;
608 conn->structured_replies = true;
609 break;
611 case NBD_OPT_LIST_META_CONTEXT:
612 case NBD_OPT_SET_META_CONTEXT:
614 uint32_t opt_index;
615 uint32_t exportnamelen;
616 uint32_t nr_queries;
617 uint32_t querylen;
618 const char *what;
620 if (conn_recv_full (conn, data, optlen, "read: %s: %m", optname) == -1)
621 return -1;
623 /* Note that we support base:allocation whether or not the plugin
624 * supports can_extents.
626 if (!conn->structured_replies) {
627 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
628 == -1)
629 return -1;
630 continue;
633 /* Minimum length of the option payload is:
634 * 32 bit export name length followed by empty export name
635 * + 32 bit number of queries followed by no queries
636 * = 8 bytes.
638 what = "optlen < 8";
639 if (optlen < 8) {
640 opt_meta_invalid_option_len:
641 debug ("newstyle negotiation: %s: invalid option length: %s",
642 optname, what);
644 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
645 == -1)
646 return -1;
647 continue;
650 /* Remember the export name: the NBD spec says that if the client
651 * later uses NBD_OPT_GO on a different export, then the context
652 * returned here is not usable.
654 memcpy (&exportnamelen, &data[0], 4);
655 exportnamelen = be32toh (exportnamelen);
656 what = "validating export name";
657 if (check_export_name (conn, option, &data[4], exportnamelen,
658 optlen - 8,
659 option == NBD_OPT_SET_META_CONTEXT) == -1)
660 goto opt_meta_invalid_option_len;
661 opt_index = 4 + exportnamelen;
663 /* Read the number of queries. */
664 what = "reading number of queries";
665 if (opt_index+4 > optlen)
666 goto opt_meta_invalid_option_len;
667 memcpy (&nr_queries, &data[opt_index], 4);
668 nr_queries = be32toh (nr_queries);
669 opt_index += 4;
671 /* for LIST: nr_queries == 0 means return all meta contexts
672 * for SET: nr_queries == 0 means reset all contexts
674 debug ("newstyle negotiation: %s: %s count: %d", optname,
675 option == NBD_OPT_LIST_META_CONTEXT ? "query" : "set",
676 nr_queries);
677 if (option == NBD_OPT_SET_META_CONTEXT)
678 conn->meta_context_base_allocation = false;
679 if (nr_queries == 0) {
680 if (option == NBD_OPT_LIST_META_CONTEXT) {
681 if (send_newstyle_option_reply_meta_context
682 (conn, option, NBD_REP_META_CONTEXT,
683 0, "base:allocation") == -1)
684 return -1;
687 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
688 return -1;
690 else {
691 /* Read and answer each query. */
692 while (nr_queries > 0) {
693 what = "reading query string length";
694 if (opt_index+4 > optlen)
695 goto opt_meta_invalid_option_len;
696 memcpy (&querylen, &data[opt_index], 4);
697 querylen = be32toh (querylen);
698 opt_index += 4;
699 what = "reading query string";
700 if (check_string (option, &data[opt_index], querylen,
701 optlen - opt_index, "meta context query") == -1)
702 goto opt_meta_invalid_option_len;
704 debug ("newstyle negotiation: %s: %s %.*s",
705 optname,
706 option == NBD_OPT_LIST_META_CONTEXT ? "query" : "set",
707 (int) querylen, &data[opt_index]);
709 /* For LIST, "base:" returns all supported contexts in the
710 * base namespace. We only support "base:allocation".
712 if (option == NBD_OPT_LIST_META_CONTEXT &&
713 querylen == 5 &&
714 strncmp (&data[opt_index], "base:", 5) == 0) {
715 if (send_newstyle_option_reply_meta_context
716 (conn, option, NBD_REP_META_CONTEXT,
717 0, "base:allocation") == -1)
718 return -1;
720 /* "base:allocation" requested by name. */
721 else if (querylen == 15 &&
722 strncmp (&data[opt_index], "base:allocation", 15) == 0) {
723 if (send_newstyle_option_reply_meta_context
724 (conn, option, NBD_REP_META_CONTEXT,
725 option == NBD_OPT_SET_META_CONTEXT
726 ? base_allocation_id : 0,
727 "base:allocation") == -1)
728 return -1;
729 if (option == NBD_OPT_SET_META_CONTEXT)
730 conn->meta_context_base_allocation = true;
732 /* Every other query must be ignored. */
734 opt_index += querylen;
735 nr_queries--;
737 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
738 return -1;
740 debug ("newstyle negotiation: %s: reply complete", optname);
742 break;
744 default:
745 /* Unknown option. */
746 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_UNSUP) == -1)
747 return -1;
748 if (conn_recv_full (conn, data, optlen,
749 "reading unknown option data: conn->recv: %m") == -1)
750 return -1;
753 /* Note, since it's not very clear from the protocol doc, that the
754 * client must send NBD_OPT_EXPORT_NAME or NBD_OPT_GO last, and
755 * that ends option negotiation.
757 if (option == NBD_OPT_EXPORT_NAME || option == NBD_OPT_GO)
758 break;
761 if (nr_options >= MAX_NR_OPTIONS) {
762 nbdkit_error ("client exceeded maximum number of options (%d)",
763 MAX_NR_OPTIONS);
764 return -1;
767 /* In --tls=require / FORCEDTLS mode, we must have upgraded to TLS
768 * by the time we finish option negotiation. If not, give up.
770 if (tls == 2 && !conn->using_tls) {
771 nbdkit_error ("non-TLS client tried to connect in --tls=require mode");
772 return -1;
775 return 0;
779 protocol_handshake_newstyle (struct connection *conn)
781 struct nbd_new_handshake handshake;
782 uint16_t gflags;
784 gflags = (NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES) & mask_handshake;
786 debug ("newstyle negotiation: flags: global 0x%x", gflags);
788 handshake.nbdmagic = htobe64 (NBD_MAGIC);
789 handshake.version = htobe64 (NBD_NEW_VERSION);
790 handshake.gflags = htobe16 (gflags);
792 if (conn->send (conn, &handshake, sizeof handshake, 0) == -1) {
793 nbdkit_error ("write: %s: %m", "sending newstyle handshake");
794 return -1;
797 /* Client now sends us its 32 bit flags word ... */
798 if (conn_recv_full (conn, &conn->cflags, sizeof conn->cflags,
799 "reading initial client flags: conn->recv: %m") == -1)
800 return -1;
801 conn->cflags = be32toh (conn->cflags);
802 /* ... which we check for accuracy. */
803 debug ("newstyle negotiation: client flags: 0x%x", conn->cflags);
804 if (conn->cflags & ~gflags) {
805 nbdkit_error ("client requested unexpected flags 0x%x", conn->cflags);
806 return -1;
809 /* Receive newstyle options. */
810 if (negotiate_handshake_newstyle_options (conn) == -1)
811 return -1;
813 return 0;