tests: Retry tests use bashisms, so set #!
[nbdkit/ericb.git] / server / protocol-handshake-newstyle.c
blobd0fb4dd73cf576cc0b75a74f9a6cd867b965ac42
1 /* nbdkit
2 * Copyright (C) 2013-2019 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 /* Maximum length of any option data (bytes). */
51 #define MAX_OPTION_LENGTH 4096
53 /* Receive newstyle options. */
54 static int
55 send_newstyle_option_reply (struct connection *conn,
56 uint32_t option, uint32_t reply)
58 struct nbd_fixed_new_option_reply fixed_new_option_reply;
60 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
61 fixed_new_option_reply.option = htobe32 (option);
62 fixed_new_option_reply.reply = htobe32 (reply);
63 fixed_new_option_reply.replylen = htobe32 (0);
65 if (conn->send (conn,
66 &fixed_new_option_reply,
67 sizeof fixed_new_option_reply, 0) == -1) {
68 /* The protocol document says that the client is allowed to simply
69 * drop the connection after sending NBD_OPT_ABORT, or may read
70 * the reply.
72 if (option == NBD_OPT_ABORT)
73 debug ("write: %s: %m", name_of_nbd_opt (option));
74 else
75 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
76 return -1;
79 return 0;
82 static int
83 send_newstyle_option_reply_exportname (struct connection *conn,
84 uint32_t option, uint32_t reply)
86 struct nbd_fixed_new_option_reply fixed_new_option_reply;
87 size_t name_len = strlen (exportname);
88 uint32_t len;
90 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
91 fixed_new_option_reply.option = htobe32 (option);
92 fixed_new_option_reply.reply = htobe32 (reply);
93 fixed_new_option_reply.replylen = htobe32 (name_len + sizeof (len));
95 if (conn->send (conn,
96 &fixed_new_option_reply,
97 sizeof fixed_new_option_reply, SEND_MORE) == -1) {
98 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
99 return -1;
102 len = htobe32 (name_len);
103 if (conn->send (conn, &len, sizeof len, SEND_MORE) == -1) {
104 nbdkit_error ("write: %s: %s: %m",
105 name_of_nbd_opt (option), "sending length");
106 return -1;
108 if (conn->send (conn, exportname, name_len, 0) == -1) {
109 nbdkit_error ("write: %s: %s: %m",
110 name_of_nbd_opt (option), "sending export name");
111 return -1;
114 return 0;
117 static int
118 send_newstyle_option_reply_info_export (struct connection *conn,
119 uint32_t option, uint32_t reply,
120 uint16_t info, uint64_t exportsize)
122 struct nbd_fixed_new_option_reply fixed_new_option_reply;
123 struct nbd_fixed_new_option_reply_info_export export;
125 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
126 fixed_new_option_reply.option = htobe32 (option);
127 fixed_new_option_reply.reply = htobe32 (reply);
128 fixed_new_option_reply.replylen = htobe32 (sizeof export);
129 export.info = htobe16 (info);
130 export.exportsize = htobe64 (exportsize);
131 export.eflags = htobe16 (conn->eflags);
133 if (conn->send (conn,
134 &fixed_new_option_reply,
135 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
136 conn->send (conn, &export, sizeof export, 0) == -1) {
137 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
138 return -1;
141 return 0;
144 static int
145 send_newstyle_option_reply_meta_context (struct connection *conn,
146 uint32_t option, uint32_t reply,
147 uint32_t context_id,
148 const char *name)
150 struct nbd_fixed_new_option_reply fixed_new_option_reply;
151 struct nbd_fixed_new_option_reply_meta_context context;
152 const size_t namelen = strlen (name);
154 debug ("newstyle negotiation: %s: replying with %s id %d",
155 name_of_nbd_opt (option), name, context_id);
156 fixed_new_option_reply.magic = htobe64 (NBD_REP_MAGIC);
157 fixed_new_option_reply.option = htobe32 (option);
158 fixed_new_option_reply.reply = htobe32 (reply);
159 fixed_new_option_reply.replylen = htobe32 (sizeof context + namelen);
160 context.context_id = htobe32 (context_id);
162 if (conn->send (conn,
163 &fixed_new_option_reply,
164 sizeof fixed_new_option_reply, SEND_MORE) == -1 ||
165 conn->send (conn, &context, sizeof context, SEND_MORE) == -1 ||
166 conn->send (conn, name, namelen, 0) == -1) {
167 nbdkit_error ("write: %s: %m", name_of_nbd_opt (option));
168 return -1;
171 return 0;
174 /* Sub-function during negotiate_handshake_newstyle, to uniformly handle
175 * a client hanging up on a message boundary.
177 static int __attribute__ ((format (printf, 4, 5)))
178 conn_recv_full (struct connection *conn, void *buf, size_t len,
179 const char *fmt, ...)
181 int r = conn->recv (conn, buf, len);
182 va_list args;
184 if (r == -1) {
185 va_start (args, fmt);
186 nbdkit_verror (fmt, args);
187 va_end (args);
188 return -1;
190 if (r == 0) {
191 /* During negotiation, client EOF on message boundary is less
192 * severe than failure in the middle of the buffer. */
193 debug ("client closed input socket, closing connection");
194 return -1;
196 return r;
199 /* Sub-function of negotiate_handshake_newstyle_options below. It
200 * must be called on all non-error paths out of the options for-loop
201 * in that function.
203 static int
204 finish_newstyle_options (struct connection *conn, uint64_t *exportsize)
206 if (protocol_common_open (conn, exportsize, &conn->eflags) == -1)
207 return -1;
209 debug ("newstyle negotiation: flags: export 0x%x", conn->eflags);
210 return 0;
213 static int
214 negotiate_handshake_newstyle_options (struct connection *conn)
216 struct nbd_new_option new_option;
217 size_t nr_options;
218 uint64_t version;
219 uint32_t option;
220 uint32_t optlen;
221 char data[MAX_OPTION_LENGTH+1];
222 struct nbd_export_name_option_reply handshake_finish;
223 const char *optname;
224 uint64_t exportsize;
226 for (nr_options = 0; nr_options < MAX_NR_OPTIONS; ++nr_options) {
227 if (conn_recv_full (conn, &new_option, sizeof new_option,
228 "reading option: conn->recv: %m") == -1)
229 return -1;
231 version = be64toh (new_option.version);
232 if (version != NBD_NEW_VERSION) {
233 nbdkit_error ("unknown option version %" PRIx64
234 ", expecting %" PRIx64,
235 version, NBD_NEW_VERSION);
236 return -1;
239 /* There is a maximum option length we will accept, regardless
240 * of the option type.
242 optlen = be32toh (new_option.optlen);
243 if (optlen > MAX_OPTION_LENGTH) {
244 nbdkit_error ("client option data too long (%" PRIu32 ")", optlen);
245 return -1;
248 option = be32toh (new_option.option);
249 optname = name_of_nbd_opt (option);
251 /* If the client lacks fixed newstyle support, it should only send
252 * NBD_OPT_EXPORT_NAME.
254 if (!(conn->cflags & NBD_FLAG_FIXED_NEWSTYLE) &&
255 option != NBD_OPT_EXPORT_NAME) {
256 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID))
257 return -1;
258 continue;
261 /* In --tls=require / FORCEDTLS mode the only options allowed
262 * before TLS negotiation are NBD_OPT_ABORT and NBD_OPT_STARTTLS.
264 if (tls == 2 && !conn->using_tls &&
265 !(option == NBD_OPT_ABORT || option == NBD_OPT_STARTTLS)) {
266 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_TLS_REQD))
267 return -1;
268 continue;
271 switch (option) {
272 case NBD_OPT_EXPORT_NAME:
273 if (conn_recv_full (conn, data, optlen,
274 "read: %s: %m", name_of_nbd_opt (option)) == -1)
275 return -1;
276 /* Print the export name and save it in the connection. */
277 data[optlen] = '\0';
278 debug ("newstyle negotiation: %s: client requested export '%s'",
279 name_of_nbd_opt (option), data);
280 free (conn->exportname);
281 conn->exportname = malloc (optlen+1);
282 if (conn->exportname == NULL) {
283 nbdkit_error ("malloc: %m");
284 return -1;
286 strcpy (conn->exportname, data);
288 /* We have to finish the handshake by sending handshake_finish. */
289 if (finish_newstyle_options (conn, &exportsize) == -1)
290 return -1;
292 memset (&handshake_finish, 0, sizeof handshake_finish);
293 handshake_finish.exportsize = htobe64 (exportsize);
294 handshake_finish.eflags = htobe16 (conn->eflags);
296 if (conn->send (conn,
297 &handshake_finish,
298 (conn->cflags & NBD_FLAG_NO_ZEROES)
299 ? offsetof (struct nbd_export_name_option_reply, zeroes)
300 : sizeof handshake_finish, 0) == -1) {
301 nbdkit_error ("write: %s: %m", optname);
302 return -1;
304 break;
306 case NBD_OPT_ABORT:
307 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
308 return -1;
309 debug ("client sent %s to abort the connection",
310 name_of_nbd_opt (option));
311 return -1;
313 case NBD_OPT_LIST:
314 if (optlen != 0) {
315 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
316 == -1)
317 return -1;
318 if (conn_recv_full (conn, data, optlen,
319 "read: %s: %m", name_of_nbd_opt (option)) == -1)
320 return -1;
321 continue;
324 /* Send back the exportname. */
325 debug ("newstyle negotiation: %s: advertising export '%s'",
326 name_of_nbd_opt (option), exportname);
327 if (send_newstyle_option_reply_exportname (conn, option,
328 NBD_REP_SERVER) == -1)
329 return -1;
331 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
332 return -1;
333 break;
335 case NBD_OPT_STARTTLS:
336 if (optlen != 0) {
337 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
338 == -1)
339 return -1;
340 if (conn_recv_full (conn, data, optlen,
341 "read: %s: %m", name_of_nbd_opt (option)) == -1)
342 return -1;
343 continue;
346 if (tls == 0) { /* --tls=off (NOTLS mode). */
347 #ifdef HAVE_GNUTLS
348 #define NO_TLS_REPLY NBD_REP_ERR_POLICY
349 #else
350 #define NO_TLS_REPLY NBD_REP_ERR_UNSUP
351 #endif
352 if (send_newstyle_option_reply (conn, option, NO_TLS_REPLY) == -1)
353 return -1;
355 else /* --tls=on or --tls=require */ {
356 /* We can't upgrade to TLS twice on the same connection. */
357 if (conn->using_tls) {
358 if (send_newstyle_option_reply (conn, option,
359 NBD_REP_ERR_INVALID) == -1)
360 return -1;
361 continue;
364 /* We have to send the (unencrypted) reply before starting
365 * the handshake.
367 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
368 return -1;
370 /* Upgrade the connection to TLS. Also performs access control. */
371 if (crypto_negotiate_tls (conn, conn->sockin, conn->sockout) == -1)
372 return -1;
373 conn->using_tls = true;
374 debug ("using TLS on this connection");
376 break;
378 case NBD_OPT_INFO:
379 case NBD_OPT_GO:
380 if (conn_recv_full (conn, data, optlen,
381 "read: %s: %m", optname) == -1)
382 return -1;
384 if (optlen < 6) { /* 32 bit export length + 16 bit nr info */
385 debug ("newstyle negotiation: %s option length < 6", optname);
387 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
388 == -1)
389 return -1;
390 continue;
394 uint32_t exportnamelen;
395 uint16_t nrinfos;
396 uint16_t info;
397 size_t i;
399 /* Validate the name length and number of INFO requests. */
400 memcpy (&exportnamelen, &data[0], 4);
401 exportnamelen = be32toh (exportnamelen);
402 if (exportnamelen > optlen-6 /* NB optlen >= 6, see above */) {
403 debug ("newstyle negotiation: %s: export name too long", optname);
404 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
405 == -1)
406 return -1;
407 continue;
409 memcpy (&nrinfos, &data[exportnamelen+4], 2);
410 nrinfos = be16toh (nrinfos);
411 if (optlen != 4 + exportnamelen + 2 + 2*nrinfos) {
412 debug ("newstyle negotiation: %s: "
413 "number of information requests incorrect", optname);
414 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
415 == -1)
416 return -1;
417 continue;
420 /* As with NBD_OPT_EXPORT_NAME we print the export name and
421 * save it in the connection.
423 free (conn->exportname);
424 conn->exportname = malloc (exportnamelen+1);
425 if (conn->exportname == NULL) {
426 nbdkit_error ("malloc: %m");
427 return -1;
429 memcpy (conn->exportname, &data[4], exportnamelen);
430 conn->exportname[exportnamelen] = '\0';
431 debug ("newstyle negotiation: %s: client requested export '%s'",
432 optname, conn->exportname);
434 /* The spec is confusing, but it is required that we send back
435 * NBD_INFO_EXPORT, even if the client did not request it!
436 * qemu client in particular does not request this, but will
437 * fail if we don't send it.
439 if (finish_newstyle_options (conn, &exportsize) == -1)
440 return -1;
442 if (send_newstyle_option_reply_info_export (conn, option,
443 NBD_REP_INFO,
444 NBD_INFO_EXPORT,
445 exportsize) == -1)
446 return -1;
448 /* For now we ignore all other info requests (but we must
449 * ignore NBD_INFO_EXPORT if it was requested, because we
450 * replied already above). Therefore this loop doesn't do
451 * much at the moment.
453 for (i = 0; i < nrinfos; ++i) {
454 memcpy (&info, &data[4 + exportnamelen + 2 + i*2], 2);
455 info = be16toh (info);
456 switch (info) {
457 case NBD_INFO_EXPORT: /* ignore - reply sent above */ break;
458 default:
459 debug ("newstyle negotiation: %s: "
460 "ignoring NBD_INFO_* request %u (%s)",
461 optname, (unsigned) info, name_of_nbd_info (info));
462 break;
467 /* Unlike NBD_OPT_EXPORT_NAME, NBD_OPT_GO sends back an ACK
468 * or ERROR packet.
470 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
471 return -1;
473 if (option == NBD_OPT_INFO) {
474 if (backend->finalize (backend, conn) == -1)
475 return -1;
476 backend_close (backend, conn);
479 break;
481 case NBD_OPT_STRUCTURED_REPLY:
482 if (optlen != 0) {
483 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
484 == -1)
485 return -1;
486 if (conn_recv_full (conn, data, optlen,
487 "read: %s: %m", name_of_nbd_opt (option)) == -1)
488 return -1;
489 continue;
492 debug ("newstyle negotiation: %s: client requested structured replies",
493 name_of_nbd_opt (option));
495 if (no_sr) {
496 /* Must fail with ERR_UNSUP for qemu 4.2 to remain happy;
497 * but failing with ERR_POLICY would have been nicer.
499 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_UNSUP) == -1)
500 return -1;
501 debug ("newstyle negotiation: %s: structured replies are disabled",
502 name_of_nbd_opt (option));
503 break;
506 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
507 return -1;
509 conn->structured_replies = true;
510 break;
512 case NBD_OPT_LIST_META_CONTEXT:
513 case NBD_OPT_SET_META_CONTEXT:
515 uint32_t opt_index;
516 uint32_t exportnamelen;
517 uint32_t nr_queries;
518 uint32_t querylen;
519 const char *what;
521 if (conn_recv_full (conn, data, optlen, "read: %s: %m", optname) == -1)
522 return -1;
524 /* Note that we support base:allocation whether or not the plugin
525 * supports can_extents.
527 if (!conn->structured_replies) {
528 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
529 == -1)
530 return -1;
531 continue;
534 /* Minimum length of the option payload is:
535 * 32 bit export name length followed by empty export name
536 * + 32 bit number of queries followed by no queries
537 * = 8 bytes.
539 what = "optlen < 8";
540 if (optlen < 8) {
541 opt_meta_invalid_option_len:
542 debug ("newstyle negotiation: %s: invalid option length: %s",
543 optname, what);
545 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_INVALID)
546 == -1)
547 return -1;
548 continue;
551 /* Discard the export name. */
552 memcpy (&exportnamelen, &data[0], 4);
553 exportnamelen = be32toh (exportnamelen);
554 opt_index = 4 + exportnamelen;
556 /* Read the number of queries. */
557 what = "reading number of queries";
558 if (opt_index+4 > optlen)
559 goto opt_meta_invalid_option_len;
560 memcpy (&nr_queries, &data[opt_index], 4);
561 nr_queries = be32toh (nr_queries);
562 opt_index += 4;
564 /* for LIST: nr_queries == 0 means return all meta contexts
565 * for SET: nr_queries == 0 means reset all contexts
567 debug ("newstyle negotiation: %s: %s count: %d", optname,
568 option == NBD_OPT_LIST_META_CONTEXT ? "query" : "set",
569 nr_queries);
570 if (option == NBD_OPT_SET_META_CONTEXT)
571 conn->meta_context_base_allocation = false;
572 if (nr_queries == 0) {
573 if (option == NBD_OPT_LIST_META_CONTEXT) {
574 if (send_newstyle_option_reply_meta_context
575 (conn, option, NBD_REP_META_CONTEXT,
576 0, "base:allocation") == -1)
577 return -1;
580 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
581 return -1;
583 else {
584 /* Read and answer each query. */
585 while (nr_queries > 0) {
586 what = "reading query string length";
587 if (opt_index+4 > optlen)
588 goto opt_meta_invalid_option_len;
589 memcpy (&querylen, &data[opt_index], 4);
590 querylen = be32toh (querylen);
591 opt_index += 4;
592 what = "reading query string";
593 if (opt_index + querylen > optlen)
594 goto opt_meta_invalid_option_len;
596 debug ("newstyle negotiation: %s: %s %.*s",
597 optname,
598 option == NBD_OPT_LIST_META_CONTEXT ? "query" : "set",
599 (int) querylen, &data[opt_index]);
601 /* For LIST, "base:" returns all supported contexts in the
602 * base namespace. We only support "base:allocation".
604 if (option == NBD_OPT_LIST_META_CONTEXT &&
605 querylen == 5 &&
606 strncmp (&data[opt_index], "base:", 5) == 0) {
607 if (send_newstyle_option_reply_meta_context
608 (conn, option, NBD_REP_META_CONTEXT,
609 0, "base:allocation") == -1)
610 return -1;
612 /* "base:allocation" requested by name. */
613 else if (querylen == 15 &&
614 strncmp (&data[opt_index], "base:allocation", 15) == 0) {
615 if (send_newstyle_option_reply_meta_context
616 (conn, option, NBD_REP_META_CONTEXT,
617 option == NBD_OPT_SET_META_CONTEXT
618 ? base_allocation_id : 0,
619 "base:allocation") == -1)
620 return -1;
621 if (option == NBD_OPT_SET_META_CONTEXT)
622 conn->meta_context_base_allocation = true;
624 /* Every other query must be ignored. */
626 opt_index += querylen;
627 nr_queries--;
629 if (send_newstyle_option_reply (conn, option, NBD_REP_ACK) == -1)
630 return -1;
632 debug ("newstyle negotiation: %s: reply complete", optname);
634 break;
636 default:
637 /* Unknown option. */
638 if (send_newstyle_option_reply (conn, option, NBD_REP_ERR_UNSUP) == -1)
639 return -1;
640 if (conn_recv_full (conn, data, optlen,
641 "reading unknown option data: conn->recv: %m") == -1)
642 return -1;
645 /* Note, since it's not very clear from the protocol doc, that the
646 * client must send NBD_OPT_EXPORT_NAME or NBD_OPT_GO last, and
647 * that ends option negotiation.
649 if (option == NBD_OPT_EXPORT_NAME || option == NBD_OPT_GO)
650 break;
653 if (nr_options >= MAX_NR_OPTIONS) {
654 nbdkit_error ("client exceeded maximum number of options (%d)",
655 MAX_NR_OPTIONS);
656 return -1;
659 /* In --tls=require / FORCEDTLS mode, we must have upgraded to TLS
660 * by the time we finish option negotiation. If not, give up.
662 if (tls == 2 && !conn->using_tls) {
663 nbdkit_error ("non-TLS client tried to connect in --tls=require mode");
664 return -1;
667 return 0;
671 protocol_handshake_newstyle (struct connection *conn)
673 struct nbd_new_handshake handshake;
674 uint16_t gflags;
676 gflags = (NBD_FLAG_FIXED_NEWSTYLE | NBD_FLAG_NO_ZEROES) & mask_handshake;
678 debug ("newstyle negotiation: flags: global 0x%x", gflags);
680 handshake.nbdmagic = htobe64 (NBD_MAGIC);
681 handshake.version = htobe64 (NBD_NEW_VERSION);
682 handshake.gflags = htobe16 (gflags);
684 if (conn->send (conn, &handshake, sizeof handshake, 0) == -1) {
685 nbdkit_error ("write: %s: %m", "sending newstyle handshake");
686 return -1;
689 /* Client now sends us its 32 bit flags word ... */
690 if (conn_recv_full (conn, &conn->cflags, sizeof conn->cflags,
691 "reading initial client flags: conn->recv: %m") == -1)
692 return -1;
693 conn->cflags = be32toh (conn->cflags);
694 /* ... which we check for accuracy. */
695 debug ("newstyle negotiation: client flags: 0x%x", conn->cflags);
696 if (conn->cflags & ~gflags) {
697 nbdkit_error ("client requested unexpected flags 0x%x", conn->cflags);
698 return -1;
701 /* Receive newstyle options. */
702 if (negotiate_handshake_newstyle_options (conn) == -1)
703 return -1;
705 return 0;