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#define NBD_FLAG_CAN_MULTI_CONN (1 << 8)
139#define NBD_FLAG_SEND_RESIZE (1 << 9)
140#define NBD_FLAG_SEND_CACHE (1 << 10)
141
142
143
144#define NBD_FLAG_FIXED_NEWSTYLE (1 << 0)
145#define NBD_FLAG_NO_ZEROES (1 << 1)
146
147
148
149#define NBD_FLAG_C_FIXED_NEWSTYLE (1 << 0)
150#define NBD_FLAG_C_NO_ZEROES (1 << 1)
151
152
153#define NBD_OPT_EXPORT_NAME (1)
154#define NBD_OPT_ABORT (2)
155#define NBD_OPT_LIST (3)
156
157#define NBD_OPT_STARTTLS (5)
158#define NBD_OPT_INFO (6)
159#define NBD_OPT_GO (7)
160#define NBD_OPT_STRUCTURED_REPLY (8)
161#define NBD_OPT_LIST_META_CONTEXT (9)
162#define NBD_OPT_SET_META_CONTEXT (10)
163
164
165#define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
166
167#define NBD_REP_ACK (1)
168#define NBD_REP_SERVER (2)
169#define NBD_REP_INFO (3)
170#define NBD_REP_META_CONTEXT (4)
171
172#define NBD_REP_ERR_UNSUP NBD_REP_ERR(1)
173#define NBD_REP_ERR_POLICY NBD_REP_ERR(2)
174#define NBD_REP_ERR_INVALID NBD_REP_ERR(3)
175#define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4)
176#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5)
177#define NBD_REP_ERR_UNKNOWN NBD_REP_ERR(6)
178#define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7)
179#define NBD_REP_ERR_BLOCK_SIZE_REQD NBD_REP_ERR(8)
180
181
182#define NBD_INFO_EXPORT 0
183#define NBD_INFO_NAME 1
184#define NBD_INFO_DESCRIPTION 2
185#define NBD_INFO_BLOCK_SIZE 3
186
187
188#define NBD_CMD_FLAG_FUA (1 << 0)
189#define NBD_CMD_FLAG_NO_HOLE (1 << 1)
190#define NBD_CMD_FLAG_DF (1 << 2)
191#define NBD_CMD_FLAG_REQ_ONE (1 << 3)
192
193
194
195enum {
196 NBD_CMD_READ = 0,
197 NBD_CMD_WRITE = 1,
198 NBD_CMD_DISC = 2,
199 NBD_CMD_FLUSH = 3,
200 NBD_CMD_TRIM = 4,
201 NBD_CMD_CACHE = 5,
202 NBD_CMD_WRITE_ZEROES = 6,
203 NBD_CMD_BLOCK_STATUS = 7,
204};
205
206#define NBD_DEFAULT_PORT 10809
207
208
209#define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024)
210
211
212
213
214
215
216#define NBD_MAX_NAME_SIZE 256
217
218
219#define NBD_SIMPLE_REPLY_MAGIC 0x67446698
220#define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef
221
222
223#define NBD_REPLY_FLAG_DONE (1 << 0)
224
225
226#define NBD_REPLY_ERR(value) ((1 << 15) | (value))
227
228#define NBD_REPLY_TYPE_NONE 0
229#define NBD_REPLY_TYPE_OFFSET_DATA 1
230#define NBD_REPLY_TYPE_OFFSET_HOLE 2
231#define NBD_REPLY_TYPE_BLOCK_STATUS 5
232#define NBD_REPLY_TYPE_ERROR NBD_REPLY_ERR(1)
233#define NBD_REPLY_TYPE_ERROR_OFFSET NBD_REPLY_ERR(2)
234
235
236#define NBD_STATE_HOLE (1 << 0)
237#define NBD_STATE_ZERO (1 << 1)
238
239
240#define NBD_STATE_DIRTY (1 << 0)
241
242static inline bool nbd_reply_type_is_error(int type)
243{
244 return type & (1 << 15);
245}
246
247
248
249
250
251#define NBD_SUCCESS 0
252#define NBD_EPERM 1
253#define NBD_EIO 5
254#define NBD_ENOMEM 12
255#define NBD_EINVAL 22
256#define NBD_ENOSPC 28
257#define NBD_EOVERFLOW 75
258#define NBD_ESHUTDOWN 108
259
260
261struct NBDExportInfo {
262
263 bool request_sizes;
264 char *x_dirty_bitmap;
265
266
267
268 bool structured_reply;
269 bool base_allocation;
270
271
272 uint64_t size;
273 uint16_t flags;
274 uint32_t min_block;
275 uint32_t opt_block;
276 uint32_t max_block;
277
278 uint32_t meta_base_allocation_id;
279};
280typedef struct NBDExportInfo NBDExportInfo;
281
282int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
283 QCryptoTLSCreds *tlscreds, const char *hostname,
284 QIOChannel **outioc, NBDExportInfo *info,
285 Error **errp);
286int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
287 Error **errp);
288int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
289int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
290int nbd_client(int fd);
291int nbd_disconnect(int fd);
292int nbd_errno_to_system_errno(int err);
293
294typedef struct NBDExport NBDExport;
295typedef struct NBDClient NBDClient;
296
297NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
298 uint16_t nbdflags, void (*close)(NBDExport *),
299 bool writethrough, BlockBackend *on_eject_blk,
300 Error **errp);
301void nbd_export_close(NBDExport *exp);
302void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp);
303void nbd_export_get(NBDExport *exp);
304void nbd_export_put(NBDExport *exp);
305
306BlockBackend *nbd_export_get_blockdev(NBDExport *exp);
307
308NBDExport *nbd_export_find(const char *name);
309void nbd_export_set_name(NBDExport *exp, const char *name);
310void nbd_export_set_description(NBDExport *exp, const char *description);
311void nbd_export_close_all(void);
312
313void nbd_client_new(QIOChannelSocket *sioc,
314 QCryptoTLSCreds *tlscreds,
315 const char *tlsaclname,
316 void (*close_fn)(NBDClient *, bool));
317void nbd_client_get(NBDClient *client);
318void nbd_client_put(NBDClient *client);
319
320void nbd_server_start(SocketAddress *addr, const char *tls_creds,
321 Error **errp);
322
323void nbd_export_bitmap(NBDExport *exp, const char *bitmap,
324 const char *bitmap_export_name, Error **errp);
325
326
327
328
329static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
330 Error **errp)
331{
332 return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
333}
334
335static inline bool nbd_reply_is_simple(NBDReply *reply)
336{
337 return reply->magic == NBD_SIMPLE_REPLY_MAGIC;
338}
339
340static inline bool nbd_reply_is_structured(NBDReply *reply)
341{
342 return reply->magic == NBD_STRUCTURED_REPLY_MAGIC;
343}
344
345const char *nbd_reply_type_lookup(uint16_t type);
346
347#endif
348