1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#ifndef NBD_H
21#define NBD_H
22
23#include "qapi/qapi-types-block.h"
24#include "io/channel-socket.h"
25#include "crypto/tlscreds.h"
26
27
28
29struct NBDOption {
30 uint64_t magic;
31 uint32_t option;
32 uint32_t length;
33} QEMU_PACKED;
34typedef struct NBDOption NBDOption;
35
36struct NBDOptionReply {
37 uint64_t magic;
38 uint32_t option;
39 uint32_t type;
40 uint32_t length;
41} QEMU_PACKED;
42typedef struct NBDOptionReply NBDOptionReply;
43
44typedef struct NBDOptionReplyMetaContext {
45 NBDOptionReply h;
46 uint32_t context_id;
47
48} QEMU_PACKED NBDOptionReplyMetaContext;
49
50
51
52
53
54
55struct NBDRequest {
56 uint64_t handle;
57 uint64_t from;
58 uint32_t len;
59 uint16_t flags;
60 uint16_t type;
61};
62typedef struct NBDRequest NBDRequest;
63
64typedef struct NBDSimpleReply {
65 uint32_t magic;
66 uint32_t error;
67 uint64_t handle;
68} QEMU_PACKED NBDSimpleReply;
69
70
71typedef struct NBDStructuredReplyChunk {
72 uint32_t magic;
73 uint16_t flags;
74 uint16_t type;
75 uint64_t handle;
76 uint32_t length;
77} QEMU_PACKED NBDStructuredReplyChunk;
78
79typedef union NBDReply {
80 NBDSimpleReply simple;
81 NBDStructuredReplyChunk structured;
82 struct {
83
84
85
86
87 uint32_t magic;
88 uint32_t _skip;
89 uint64_t handle;
90 } QEMU_PACKED;
91} NBDReply;
92
93
94typedef struct NBDStructuredReadData {
95 NBDStructuredReplyChunk h;
96 uint64_t offset;
97
98} QEMU_PACKED NBDStructuredReadData;
99
100
101typedef struct NBDStructuredReadHole {
102 NBDStructuredReplyChunk h;
103 uint64_t offset;
104 uint32_t length;
105} QEMU_PACKED NBDStructuredReadHole;
106
107
108typedef struct NBDStructuredError {
109 NBDStructuredReplyChunk h;
110 uint32_t error;
111 uint16_t message_length;
112} QEMU_PACKED NBDStructuredError;
113
114
115typedef struct NBDStructuredMeta {
116 NBDStructuredReplyChunk h;
117 uint32_t context_id;
118
119} QEMU_PACKED NBDStructuredMeta;
120
121
122typedef struct NBDExtent {
123 uint32_t length;
124 uint32_t flags;
125} QEMU_PACKED NBDExtent;
126
127
128
129#define NBD_FLAG_HAS_FLAGS (1 << 0)
130#define NBD_FLAG_READ_ONLY (1 << 1)
131#define NBD_FLAG_SEND_FLUSH (1 << 2)
132#define NBD_FLAG_SEND_FUA (1 << 3)
133#define NBD_FLAG_ROTATIONAL (1 << 4)
134
135#define NBD_FLAG_SEND_TRIM (1 << 5)
136#define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6)
137#define NBD_FLAG_SEND_DF (1 << 7)
138
139
140
141#define NBD_FLAG_FIXED_NEWSTYLE (1 << 0)
142#define NBD_FLAG_NO_ZEROES (1 << 1)
143
144
145
146#define NBD_FLAG_C_FIXED_NEWSTYLE (1 << 0)
147#define NBD_FLAG_C_NO_ZEROES (1 << 1)
148
149
150#define NBD_OPT_EXPORT_NAME (1)
151#define NBD_OPT_ABORT (2)
152#define NBD_OPT_LIST (3)
153
154#define NBD_OPT_STARTTLS (5)
155#define NBD_OPT_INFO (6)
156#define NBD_OPT_GO (7)
157#define NBD_OPT_STRUCTURED_REPLY (8)
158#define NBD_OPT_LIST_META_CONTEXT (9)
159#define NBD_OPT_SET_META_CONTEXT (10)
160
161
162#define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
163
164#define NBD_REP_ACK (1)
165#define NBD_REP_SERVER (2)
166#define NBD_REP_INFO (3)
167#define NBD_REP_META_CONTEXT (4)
168
169#define NBD_REP_ERR_UNSUP NBD_REP_ERR(1)
170#define NBD_REP_ERR_POLICY NBD_REP_ERR(2)
171#define NBD_REP_ERR_INVALID NBD_REP_ERR(3)
172#define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4)
173#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5)
174#define NBD_REP_ERR_UNKNOWN NBD_REP_ERR(6)
175#define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7)
176#define NBD_REP_ERR_BLOCK_SIZE_REQD NBD_REP_ERR(8)
177
178
179#define NBD_INFO_EXPORT 0
180#define NBD_INFO_NAME 1
181#define NBD_INFO_DESCRIPTION 2
182#define NBD_INFO_BLOCK_SIZE 3
183
184
185#define NBD_CMD_FLAG_FUA (1 << 0)
186#define NBD_CMD_FLAG_NO_HOLE (1 << 1)
187#define NBD_CMD_FLAG_DF (1 << 2)
188#define NBD_CMD_FLAG_REQ_ONE (1 << 3)
189
190
191
192enum {
193 NBD_CMD_READ = 0,
194 NBD_CMD_WRITE = 1,
195 NBD_CMD_DISC = 2,
196 NBD_CMD_FLUSH = 3,
197 NBD_CMD_TRIM = 4,
198
199 NBD_CMD_WRITE_ZEROES = 6,
200 NBD_CMD_BLOCK_STATUS = 7,
201};
202
203#define NBD_DEFAULT_PORT 10809
204
205
206#define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024)
207
208
209
210
211
212
213#define NBD_MAX_NAME_SIZE 256
214
215
216#define NBD_SIMPLE_REPLY_MAGIC 0x67446698
217#define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef
218
219
220#define NBD_REPLY_FLAG_DONE (1 << 0)
221
222
223#define NBD_REPLY_ERR(value) ((1 << 15) | (value))
224
225#define NBD_REPLY_TYPE_NONE 0
226#define NBD_REPLY_TYPE_OFFSET_DATA 1
227#define NBD_REPLY_TYPE_OFFSET_HOLE 2
228#define NBD_REPLY_TYPE_BLOCK_STATUS 5
229#define NBD_REPLY_TYPE_ERROR NBD_REPLY_ERR(1)
230#define NBD_REPLY_TYPE_ERROR_OFFSET NBD_REPLY_ERR(2)
231
232
233
234#define NBD_STATE_HOLE (1 << 0)
235#define NBD_STATE_ZERO (1 << 1)
236
237static inline bool nbd_reply_type_is_error(int type)
238{
239 return type & (1 << 15);
240}
241
242
243
244
245
246#define NBD_SUCCESS 0
247#define NBD_EPERM 1
248#define NBD_EIO 5
249#define NBD_ENOMEM 12
250#define NBD_EINVAL 22
251#define NBD_ENOSPC 28
252#define NBD_EOVERFLOW 75
253#define NBD_ESHUTDOWN 108
254
255
256struct NBDExportInfo {
257
258 bool request_sizes;
259
260
261
262 bool structured_reply;
263 bool base_allocation;
264
265
266 uint64_t size;
267 uint16_t flags;
268 uint32_t min_block;
269 uint32_t opt_block;
270 uint32_t max_block;
271
272 uint32_t meta_base_allocation_id;
273};
274typedef struct NBDExportInfo NBDExportInfo;
275
276int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
277 QCryptoTLSCreds *tlscreds, const char *hostname,
278 QIOChannel **outioc, NBDExportInfo *info,
279 Error **errp);
280int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
281 Error **errp);
282int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
283int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
284int nbd_client(int fd);
285int nbd_disconnect(int fd);
286int nbd_errno_to_system_errno(int err);
287
288typedef struct NBDExport NBDExport;
289typedef struct NBDClient NBDClient;
290
291NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
292 uint16_t nbdflags, void (*close)(NBDExport *),
293 bool writethrough, BlockBackend *on_eject_blk,
294 Error **errp);
295void nbd_export_close(NBDExport *exp);
296void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp);
297void nbd_export_get(NBDExport *exp);
298void nbd_export_put(NBDExport *exp);
299
300BlockBackend *nbd_export_get_blockdev(NBDExport *exp);
301
302NBDExport *nbd_export_find(const char *name);
303void nbd_export_set_name(NBDExport *exp, const char *name);
304void nbd_export_set_description(NBDExport *exp, const char *description);
305void nbd_export_close_all(void);
306
307void nbd_client_new(NBDExport *exp,
308 QIOChannelSocket *sioc,
309 QCryptoTLSCreds *tlscreds,
310 const char *tlsaclname,
311 void (*close_fn)(NBDClient *, bool));
312void nbd_client_get(NBDClient *client);
313void nbd_client_put(NBDClient *client);
314
315void nbd_server_start(SocketAddress *addr, const char *tls_creds,
316 Error **errp);
317
318
319
320
321
322static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
323 Error **errp)
324{
325 return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
326}
327
328static inline bool nbd_reply_is_simple(NBDReply *reply)
329{
330 return reply->magic == NBD_SIMPLE_REPLY_MAGIC;
331}
332
333static inline bool nbd_reply_is_structured(NBDReply *reply)
334{
335 return reply->magic == NBD_STRUCTURED_REPLY_MAGIC;
336}
337
338const char *nbd_reply_type_lookup(uint16_t type);
339
340#endif
341