plugins: Wire up rust plugin support for NBD_INFO_INIT_STATE
[nbdkit/ericb.git] / server / protocol-handshake.c
blob2c2f35ee4f1d0eb16e6b3951ae3a66def2aa0be2
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"
46 int
47 protocol_handshake (struct connection *conn)
49 int r;
51 lock_request (conn);
52 if (!newstyle)
53 r = protocol_handshake_oldstyle (conn);
54 else
55 r = protocol_handshake_newstyle (conn);
56 unlock_request (conn);
58 return r;
61 /* Common code used by oldstyle and newstyle protocols to:
63 * - call the backend .open method
65 * - get the export size
67 * - compute the eflags (same between oldstyle and newstyle
68 * protocols)
70 * The protocols must defer this as late as possible so that
71 * unauthorized clients can't cause unnecessary work in .open by
72 * simply opening a TCP connection.
74 int
75 protocol_common_open (struct connection *conn,
76 uint64_t *exportsize, uint16_t *flags)
78 int64_t size;
79 uint16_t eflags = NBD_FLAG_HAS_FLAGS;
80 int fl;
82 if (backend_open (backend, conn, read_only) == -1)
83 return -1;
85 /* Prepare (for filters), called just after open. */
86 if (backend_prepare (backend, conn) == -1)
87 return -1;
89 size = backend_get_size (backend, conn);
90 if (size == -1)
91 return -1;
92 if (size < 0) {
93 nbdkit_error (".get_size function returned invalid value "
94 "(%" PRIi64 ")", size);
95 return -1;
98 /* Check all flags even if they won't be advertised, to prime the
99 * cache and make later request validation easier.
101 fl = backend_can_write (backend, conn);
102 if (fl == -1)
103 return -1;
104 if (!fl)
105 eflags |= NBD_FLAG_READ_ONLY;
107 fl = backend_can_zero (backend, conn);
108 if (fl == -1)
109 return -1;
110 if (fl)
111 eflags |= NBD_FLAG_SEND_WRITE_ZEROES;
113 fl = backend_can_fast_zero (backend, conn);
114 if (fl == -1)
115 return -1;
116 if (fl)
117 eflags |= NBD_FLAG_SEND_FAST_ZERO;
119 fl = backend_can_trim (backend, conn);
120 if (fl == -1)
121 return -1;
122 if (fl)
123 eflags |= NBD_FLAG_SEND_TRIM;
125 fl = backend_can_fua (backend, conn);
126 if (fl == -1)
127 return -1;
128 if (fl)
129 eflags |= NBD_FLAG_SEND_FUA;
131 fl = backend_can_flush (backend, conn);
132 if (fl == -1)
133 return -1;
134 if (fl)
135 eflags |= NBD_FLAG_SEND_FLUSH;
137 fl = backend_is_rotational (backend, conn);
138 if (fl == -1)
139 return -1;
140 if (fl)
141 eflags |= NBD_FLAG_ROTATIONAL;
143 /* multi-conn is useless if parallel connections are not allowed. */
144 fl = backend_can_multi_conn (backend, conn);
145 if (fl == -1)
146 return -1;
147 if (fl && (backend->thread_model (backend) >
148 NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS))
149 eflags |= NBD_FLAG_CAN_MULTI_CONN;
151 fl = backend_can_cache (backend, conn);
152 if (fl == -1)
153 return -1;
154 if (fl)
155 eflags |= NBD_FLAG_SEND_CACHE;
157 /* The result of this is not directly advertised as part of the
158 * handshake, but priming the cache here makes BLOCK_STATUS handling
159 * not have to worry about errors, and makes test-layers easier to
160 * write.
162 fl = backend_can_extents (backend, conn);
163 if (fl == -1)
164 return -1;
166 if (conn->structured_replies)
167 eflags |= NBD_FLAG_SEND_DF;
169 *exportsize = size;
170 *flags = eflags;
171 return 0;