aboutsummaryrefslogtreecommitdiff
path: root/nbd/nbd-internal.h
blob: 11a130d0505826dd7fee6513c2c7d4d8c92ed9c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * NBD Internal Declarations
 *
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

#ifndef NBD_INTERNAL_H
#define NBD_INTERNAL_H
#include "block/nbd.h"
#include "sysemu/block-backend.h"
#include "io/channel-tls.h"

#include "qemu/coroutine.h"
#include "qemu/iov.h"

#ifndef _WIN32
#include <sys/ioctl.h>
#endif
#if defined(__sun__) || defined(__HAIKU__)
#include <sys/ioccom.h>
#endif

#ifdef __linux__
#include <linux/fs.h>
#endif

#include "qemu/bswap.h"
#include "qemu/queue.h"
#include "qemu/main-loop.h"

/* This is all part of the "official" NBD API.
 *
 * The most up-to-date documentation is available at:
 * https://github.com/yoe/nbd/blob/master/doc/proto.md
 */

/* Size of all NBD_OPT_*, without payload */
#define NBD_REQUEST_SIZE            (4 + 2 + 2 + 8 + 8 + 4)
/* Size of all NBD_REP_* sent in answer to most NBD_OPT_*, without payload */
#define NBD_REPLY_SIZE              (4 + 4 + 8)
/* Size of reply to NBD_OPT_EXPORT_NAME */
#define NBD_REPLY_EXPORT_NAME_SIZE  (8 + 2 + 124)
/* Size of oldstyle negotiation */
#define NBD_OLDSTYLE_NEGOTIATE_SIZE (8 + 8 + 8 + 4 + 124)

#define NBD_REQUEST_MAGIC           0x25609513
#define NBD_SIMPLE_REPLY_MAGIC      0x67446698
#define NBD_OPTS_MAGIC              0x49484156454F5054LL
#define NBD_CLIENT_MAGIC            0x0000420281861253LL
#define NBD_REP_MAGIC               0x0003e889045565a9LL

#define NBD_SET_SOCK                _IO(0xab, 0)
#define NBD_SET_BLKSIZE             _IO(0xab, 1)
#define NBD_SET_SIZE                _IO(0xab, 2)
#define NBD_DO_IT                   _IO(0xab, 3)
#define NBD_CLEAR_SOCK              _IO(0xab, 4)
#define NBD_CLEAR_QUE               _IO(0xab, 5)
#define NBD_PRINT_DEBUG             _IO(0xab, 6)
#define NBD_SET_SIZE_BLOCKS         _IO(0xab, 7)
#define NBD_DISCONNECT              _IO(0xab, 8)
#define NBD_SET_TIMEOUT             _IO(0xab, 9)
#define NBD_SET_FLAGS               _IO(0xab, 10)

/* NBD errors are based on errno numbers, so there is a 1:1 mapping,
 * but only a limited set of errno values is specified in the protocol.
 * Everything else is squashed to EINVAL.
 */
#define NBD_SUCCESS    0
#define NBD_EPERM      1
#define NBD_EIO        5
#define NBD_ENOMEM     12
#define NBD_EINVAL     22
#define NBD_ENOSPC     28
#define NBD_ESHUTDOWN  108

/* nbd_read_eof
 * Tries to read @size bytes from @ioc.
 * Returns 1 on success
 *         0 on eof, when no data was read (errp is not set)
 *         negative errno on failure (errp is set)
 */
static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
                               Error **errp)
{
    int ret;

    assert(size);
    ret = qio_channel_read_all_eof(ioc, buffer, size, errp);
    if (ret < 0) {
        ret = -EIO;
    }
    return ret;
}

/* nbd_read
 * Reads @size bytes from @ioc. Returns 0 on success.
 */
static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
                           Error **errp)
{
    return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
}

/* nbd_write
 * Writes @size bytes to @ioc. Returns 0 on success.
 */
static inline int nbd_write(QIOChannel *ioc, const void *buffer, size_t size,
                            Error **errp)
{
    return qio_channel_write_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
}

struct NBDTLSHandshakeData {
    GMainLoop *loop;
    bool complete;
    Error *error;
};


void nbd_tls_handshake(QIOTask *task,
                       void *opaque);
const char *nbd_opt_lookup(uint32_t opt);
const char *nbd_rep_lookup(uint32_t rep);
const char *nbd_info_lookup(uint16_t info);
const char *nbd_cmd_lookup(uint16_t info);

int nbd_drop(QIOChannel *ioc, size_t size, Error **errp);

#endif