Statistics
| Branch: | Revision:

root / nbd.c @ 016b2b28

History | View | Annotate | Download (13.9 kB)

1 75818250 ths
/*
2 7a5ca864 bellard
 *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
3 7a5ca864 bellard
 *
4 7a5ca864 bellard
 *  Network Block Device
5 7a5ca864 bellard
 *
6 7a5ca864 bellard
 *  This program is free software; you can redistribute it and/or modify
7 7a5ca864 bellard
 *  it under the terms of the GNU General Public License as published by
8 7a5ca864 bellard
 *  the Free Software Foundation; under version 2 of the License.
9 7a5ca864 bellard
 *
10 7a5ca864 bellard
 *  This program is distributed in the hope that it will be useful,
11 7a5ca864 bellard
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 7a5ca864 bellard
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 7a5ca864 bellard
 *  GNU General Public License for more details.
14 7a5ca864 bellard
 *
15 7a5ca864 bellard
 *  You should have received a copy of the GNU General Public License
16 8167ee88 Blue Swirl
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17 75818250 ths
 */
18 7a5ca864 bellard
19 7a5ca864 bellard
#include "nbd.h"
20 7a5ca864 bellard
21 7a5ca864 bellard
#include <errno.h>
22 7a5ca864 bellard
#include <string.h>
23 03ff3ca3 aliguori
#ifndef _WIN32
24 7a5ca864 bellard
#include <sys/ioctl.h>
25 03ff3ca3 aliguori
#endif
26 7e00eb9b aliguori
#ifdef __sun__
27 7e00eb9b aliguori
#include <sys/ioccom.h>
28 7e00eb9b aliguori
#endif
29 7a5ca864 bellard
#include <ctype.h>
30 7a5ca864 bellard
#include <inttypes.h>
31 75818250 ths
32 03ff3ca3 aliguori
#include "qemu_socket.h"
33 03ff3ca3 aliguori
34 03ff3ca3 aliguori
//#define DEBUG_NBD
35 03ff3ca3 aliguori
36 03ff3ca3 aliguori
#ifdef DEBUG_NBD
37 75818250 ths
#define TRACE(msg, ...) do { \
38 03ff3ca3 aliguori
    LOG(msg, ## __VA_ARGS__); \
39 75818250 ths
} while(0)
40 03ff3ca3 aliguori
#else
41 03ff3ca3 aliguori
#define TRACE(msg, ...) \
42 03ff3ca3 aliguori
    do { } while (0)
43 03ff3ca3 aliguori
#endif
44 7a5ca864 bellard
45 7a5ca864 bellard
#define LOG(msg, ...) do { \
46 7a5ca864 bellard
    fprintf(stderr, "%s:%s():L%d: " msg "\n", \
47 7a5ca864 bellard
            __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
48 7a5ca864 bellard
} while(0)
49 7a5ca864 bellard
50 7a5ca864 bellard
/* This is all part of the "official" NBD API */
51 7a5ca864 bellard
52 7a5ca864 bellard
#define NBD_REQUEST_MAGIC       0x25609513
53 7a5ca864 bellard
#define NBD_REPLY_MAGIC         0x67446698
54 7a5ca864 bellard
55 7a5ca864 bellard
#define NBD_SET_SOCK            _IO(0xab, 0)
56 7a5ca864 bellard
#define NBD_SET_BLKSIZE         _IO(0xab, 1)
57 7a5ca864 bellard
#define NBD_SET_SIZE            _IO(0xab, 2)
58 7a5ca864 bellard
#define NBD_DO_IT               _IO(0xab, 3)
59 7a5ca864 bellard
#define NBD_CLEAR_SOCK          _IO(0xab, 4)
60 7a5ca864 bellard
#define NBD_CLEAR_QUE           _IO(0xab, 5)
61 7a5ca864 bellard
#define NBD_PRINT_DEBUG                _IO(0xab, 6)
62 7a5ca864 bellard
#define NBD_SET_SIZE_BLOCKS        _IO(0xab, 7)
63 7a5ca864 bellard
#define NBD_DISCONNECT          _IO(0xab, 8)
64 7a5ca864 bellard
65 7a5ca864 bellard
/* That's all folks */
66 7a5ca864 bellard
67 75818250 ths
#define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
68 75818250 ths
#define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false)
69 7a5ca864 bellard
70 75818250 ths
size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
71 7a5ca864 bellard
{
72 7a5ca864 bellard
    size_t offset = 0;
73 7a5ca864 bellard
74 7a5ca864 bellard
    while (offset < size) {
75 7a5ca864 bellard
        ssize_t len;
76 7a5ca864 bellard
77 7a5ca864 bellard
        if (do_read) {
78 03ff3ca3 aliguori
            len = recv(fd, buffer + offset, size - offset, 0);
79 7a5ca864 bellard
        } else {
80 03ff3ca3 aliguori
            len = send(fd, buffer + offset, size - offset, 0);
81 7a5ca864 bellard
        }
82 7a5ca864 bellard
83 03ff3ca3 aliguori
        if (len == -1)
84 03ff3ca3 aliguori
            errno = socket_error();
85 03ff3ca3 aliguori
86 7a5ca864 bellard
        /* recoverable error */
87 75818250 ths
        if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
88 7a5ca864 bellard
            continue;
89 7a5ca864 bellard
        }
90 7a5ca864 bellard
91 7a5ca864 bellard
        /* eof */
92 7a5ca864 bellard
        if (len == 0) {
93 7a5ca864 bellard
            break;
94 7a5ca864 bellard
        }
95 7a5ca864 bellard
96 7a5ca864 bellard
        /* unrecoverable error */
97 7a5ca864 bellard
        if (len == -1) {
98 7a5ca864 bellard
            return 0;
99 7a5ca864 bellard
        }
100 7a5ca864 bellard
101 7a5ca864 bellard
        offset += len;
102 7a5ca864 bellard
    }
103 7a5ca864 bellard
104 7a5ca864 bellard
    return offset;
105 7a5ca864 bellard
}
106 7a5ca864 bellard
107 75818250 ths
int tcp_socket_outgoing(const char *address, uint16_t port)
108 7a5ca864 bellard
{
109 7a5ca864 bellard
    int s;
110 7a5ca864 bellard
    struct in_addr in;
111 7a5ca864 bellard
    struct sockaddr_in addr;
112 7a5ca864 bellard
113 7a5ca864 bellard
    s = socket(PF_INET, SOCK_STREAM, 0);
114 7a5ca864 bellard
    if (s == -1) {
115 7a5ca864 bellard
        return -1;
116 7a5ca864 bellard
    }
117 7a5ca864 bellard
118 7a5ca864 bellard
    if (inet_aton(address, &in) == 0) {
119 7a5ca864 bellard
        struct hostent *ent;
120 7a5ca864 bellard
121 7a5ca864 bellard
        ent = gethostbyname(address);
122 7a5ca864 bellard
        if (ent == NULL) {
123 7a5ca864 bellard
            goto error;
124 7a5ca864 bellard
        }
125 7a5ca864 bellard
126 7a5ca864 bellard
        memcpy(&in, ent->h_addr, sizeof(in));
127 7a5ca864 bellard
    }
128 7a5ca864 bellard
129 7a5ca864 bellard
    addr.sin_family = AF_INET;
130 7a5ca864 bellard
    addr.sin_port = htons(port);
131 7a5ca864 bellard
    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
132 7a5ca864 bellard
133 7a5ca864 bellard
    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
134 7a5ca864 bellard
        goto error;
135 7a5ca864 bellard
    }
136 7a5ca864 bellard
137 7a5ca864 bellard
    return s;
138 7a5ca864 bellard
error:
139 03ff3ca3 aliguori
    closesocket(s);
140 7a5ca864 bellard
    return -1;
141 7a5ca864 bellard
}
142 7a5ca864 bellard
143 7a5ca864 bellard
int tcp_socket_incoming(const char *address, uint16_t port)
144 7a5ca864 bellard
{
145 7a5ca864 bellard
    int s;
146 7a5ca864 bellard
    struct in_addr in;
147 7a5ca864 bellard
    struct sockaddr_in addr;
148 7a5ca864 bellard
    int opt;
149 7a5ca864 bellard
150 7a5ca864 bellard
    s = socket(PF_INET, SOCK_STREAM, 0);
151 7a5ca864 bellard
    if (s == -1) {
152 7a5ca864 bellard
        return -1;
153 7a5ca864 bellard
    }
154 7a5ca864 bellard
155 7a5ca864 bellard
    if (inet_aton(address, &in) == 0) {
156 7a5ca864 bellard
        struct hostent *ent;
157 7a5ca864 bellard
158 7a5ca864 bellard
        ent = gethostbyname(address);
159 7a5ca864 bellard
        if (ent == NULL) {
160 7a5ca864 bellard
            goto error;
161 7a5ca864 bellard
        }
162 7a5ca864 bellard
163 7a5ca864 bellard
        memcpy(&in, ent->h_addr, sizeof(in));
164 7a5ca864 bellard
    }
165 7a5ca864 bellard
166 7a5ca864 bellard
    addr.sin_family = AF_INET;
167 7a5ca864 bellard
    addr.sin_port = htons(port);
168 7a5ca864 bellard
    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
169 7a5ca864 bellard
170 7a5ca864 bellard
    opt = 1;
171 0a656f5f malc
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
172 0a656f5f malc
                   (const void *) &opt, sizeof(opt)) == -1) {
173 7a5ca864 bellard
        goto error;
174 7a5ca864 bellard
    }
175 7a5ca864 bellard
176 7a5ca864 bellard
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
177 7a5ca864 bellard
        goto error;
178 7a5ca864 bellard
    }
179 7a5ca864 bellard
180 7a5ca864 bellard
    if (listen(s, 128) == -1) {
181 7a5ca864 bellard
        goto error;
182 7a5ca864 bellard
    }
183 7a5ca864 bellard
184 7a5ca864 bellard
    return s;
185 7a5ca864 bellard
error:
186 03ff3ca3 aliguori
    closesocket(s);
187 7a5ca864 bellard
    return -1;
188 7a5ca864 bellard
}
189 7a5ca864 bellard
190 03ff3ca3 aliguori
#ifndef _WIN32
191 cd831bd7 ths
int unix_socket_incoming(const char *path)
192 cd831bd7 ths
{
193 cd831bd7 ths
    int s;
194 cd831bd7 ths
    struct sockaddr_un addr;
195 cd831bd7 ths
196 cd831bd7 ths
    s = socket(PF_UNIX, SOCK_STREAM, 0);
197 cd831bd7 ths
    if (s == -1) {
198 cd831bd7 ths
        return -1;
199 cd831bd7 ths
    }
200 cd831bd7 ths
201 cd831bd7 ths
    memset(&addr, 0, sizeof(addr));
202 cd831bd7 ths
    addr.sun_family = AF_UNIX;
203 cd831bd7 ths
    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
204 cd831bd7 ths
205 cd831bd7 ths
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
206 cd831bd7 ths
        goto error;
207 cd831bd7 ths
    }
208 cd831bd7 ths
209 cd831bd7 ths
    if (listen(s, 128) == -1) {
210 cd831bd7 ths
        goto error;
211 cd831bd7 ths
    }
212 cd831bd7 ths
213 cd831bd7 ths
    return s;
214 cd831bd7 ths
error:
215 03ff3ca3 aliguori
    closesocket(s);
216 cd831bd7 ths
    return -1;
217 cd831bd7 ths
}
218 cd831bd7 ths
219 cd831bd7 ths
int unix_socket_outgoing(const char *path)
220 cd831bd7 ths
{
221 cd831bd7 ths
    int s;
222 cd831bd7 ths
    struct sockaddr_un addr;
223 cd831bd7 ths
224 cd831bd7 ths
    s = socket(PF_UNIX, SOCK_STREAM, 0);
225 cd831bd7 ths
    if (s == -1) {
226 cd831bd7 ths
        return -1;
227 cd831bd7 ths
    }
228 cd831bd7 ths
229 cd831bd7 ths
    memset(&addr, 0, sizeof(addr));
230 cd831bd7 ths
    addr.sun_family = AF_UNIX;
231 cd831bd7 ths
    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
232 cd831bd7 ths
233 cd831bd7 ths
    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
234 cd831bd7 ths
        goto error;
235 cd831bd7 ths
    }
236 cd831bd7 ths
237 cd831bd7 ths
    return s;
238 cd831bd7 ths
error:
239 03ff3ca3 aliguori
    closesocket(s);
240 03ff3ca3 aliguori
    return -1;
241 03ff3ca3 aliguori
}
242 03ff3ca3 aliguori
#else
243 03ff3ca3 aliguori
int unix_socket_incoming(const char *path)
244 03ff3ca3 aliguori
{
245 03ff3ca3 aliguori
    errno = ENOTSUP;
246 cd831bd7 ths
    return -1;
247 cd831bd7 ths
}
248 cd831bd7 ths
249 03ff3ca3 aliguori
int unix_socket_outgoing(const char *path)
250 03ff3ca3 aliguori
{
251 03ff3ca3 aliguori
    errno = ENOTSUP;
252 03ff3ca3 aliguori
    return -1;
253 03ff3ca3 aliguori
}
254 03ff3ca3 aliguori
#endif
255 03ff3ca3 aliguori
256 cd831bd7 ths
257 7a5ca864 bellard
/* Basic flow
258 7a5ca864 bellard

259 7a5ca864 bellard
   Server         Client
260 7a5ca864 bellard

261 7a5ca864 bellard
   Negotiate
262 7a5ca864 bellard
                  Request
263 7a5ca864 bellard
   Response
264 7a5ca864 bellard
                  Request
265 7a5ca864 bellard
   Response
266 7a5ca864 bellard
                  ...
267 7a5ca864 bellard
   ...
268 7a5ca864 bellard
                  Request (type == 2)
269 7a5ca864 bellard
*/
270 7a5ca864 bellard
271 27982661 aliguori
int nbd_negotiate(int csock, off_t size)
272 7a5ca864 bellard
{
273 7a5ca864 bellard
        char buf[8 + 8 + 8 + 128];
274 7a5ca864 bellard
275 7a5ca864 bellard
        /* Negotiate
276 7a5ca864 bellard
           [ 0 ..   7]   passwd   ("NBDMAGIC")
277 7a5ca864 bellard
           [ 8 ..  15]   magic    (0x00420281861253)
278 7a5ca864 bellard
           [16 ..  23]   size
279 7a5ca864 bellard
           [24 .. 151]   reserved (0)
280 7a5ca864 bellard
         */
281 7a5ca864 bellard
282 7a5ca864 bellard
        TRACE("Beginning negotiation.");
283 7a5ca864 bellard
        memcpy(buf, "NBDMAGIC", 8);
284 7a5ca864 bellard
        cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
285 7a5ca864 bellard
        cpu_to_be64w((uint64_t*)(buf + 16), size);
286 7a5ca864 bellard
        memset(buf + 24, 0, 128);
287 7a5ca864 bellard
288 7a5ca864 bellard
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
289 7a5ca864 bellard
                LOG("write failed");
290 7a5ca864 bellard
                errno = EINVAL;
291 7a5ca864 bellard
                return -1;
292 7a5ca864 bellard
        }
293 7a5ca864 bellard
294 7a5ca864 bellard
        TRACE("Negotation succeeded.");
295 7a5ca864 bellard
296 7a5ca864 bellard
        return 0;
297 7a5ca864 bellard
}
298 7a5ca864 bellard
299 cd831bd7 ths
int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize)
300 7a5ca864 bellard
{
301 7a5ca864 bellard
        char buf[8 + 8 + 8 + 128];
302 7a5ca864 bellard
        uint64_t magic;
303 7a5ca864 bellard
304 7a5ca864 bellard
        TRACE("Receiving negotation.");
305 7a5ca864 bellard
306 7a5ca864 bellard
        if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
307 7a5ca864 bellard
                LOG("read failed");
308 7a5ca864 bellard
                errno = EINVAL;
309 7a5ca864 bellard
                return -1;
310 7a5ca864 bellard
        }
311 7a5ca864 bellard
312 7a5ca864 bellard
        magic = be64_to_cpup((uint64_t*)(buf + 8));
313 cd831bd7 ths
        *size = be64_to_cpup((uint64_t*)(buf + 16));
314 cd831bd7 ths
        *blocksize = 1024;
315 7a5ca864 bellard
316 7a5ca864 bellard
        TRACE("Magic is %c%c%c%c%c%c%c%c",
317 47398b9c blueswir1
              qemu_isprint(buf[0]) ? buf[0] : '.',
318 47398b9c blueswir1
              qemu_isprint(buf[1]) ? buf[1] : '.',
319 47398b9c blueswir1
              qemu_isprint(buf[2]) ? buf[2] : '.',
320 47398b9c blueswir1
              qemu_isprint(buf[3]) ? buf[3] : '.',
321 47398b9c blueswir1
              qemu_isprint(buf[4]) ? buf[4] : '.',
322 47398b9c blueswir1
              qemu_isprint(buf[5]) ? buf[5] : '.',
323 47398b9c blueswir1
              qemu_isprint(buf[6]) ? buf[6] : '.',
324 47398b9c blueswir1
              qemu_isprint(buf[7]) ? buf[7] : '.');
325 7a5ca864 bellard
        TRACE("Magic is 0x%" PRIx64, magic);
326 cd831bd7 ths
        TRACE("Size is %" PRIu64, *size);
327 7a5ca864 bellard
328 7a5ca864 bellard
        if (memcmp(buf, "NBDMAGIC", 8) != 0) {
329 7a5ca864 bellard
                LOG("Invalid magic received");
330 7a5ca864 bellard
                errno = EINVAL;
331 7a5ca864 bellard
                return -1;
332 7a5ca864 bellard
        }
333 7a5ca864 bellard
334 7a5ca864 bellard
        TRACE("Checking magic");
335 7a5ca864 bellard
336 7a5ca864 bellard
        if (magic != 0x00420281861253LL) {
337 7a5ca864 bellard
                LOG("Bad magic received");
338 7a5ca864 bellard
                errno = EINVAL;
339 7a5ca864 bellard
                return -1;
340 7a5ca864 bellard
        }
341 cd831bd7 ths
        return 0;
342 cd831bd7 ths
}
343 7a5ca864 bellard
344 03ff3ca3 aliguori
#ifndef _WIN32
345 cd831bd7 ths
int nbd_init(int fd, int csock, off_t size, size_t blocksize)
346 cd831bd7 ths
{
347 7a5ca864 bellard
        TRACE("Setting block size to %lu", (unsigned long)blocksize);
348 7a5ca864 bellard
349 7a5ca864 bellard
        if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
350 7a5ca864 bellard
                int serrno = errno;
351 7a5ca864 bellard
                LOG("Failed setting NBD block size");
352 7a5ca864 bellard
                errno = serrno;
353 7a5ca864 bellard
                return -1;
354 7a5ca864 bellard
        }
355 7a5ca864 bellard
356 7a5ca864 bellard
        TRACE("Setting size to %llu block(s)",
357 7a5ca864 bellard
              (unsigned long long)(size / blocksize));
358 7a5ca864 bellard
359 7a5ca864 bellard
        if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
360 7a5ca864 bellard
                int serrno = errno;
361 7a5ca864 bellard
                LOG("Failed setting size (in blocks)");
362 7a5ca864 bellard
                errno = serrno;
363 7a5ca864 bellard
                return -1;
364 7a5ca864 bellard
        }
365 7a5ca864 bellard
366 7a5ca864 bellard
        TRACE("Clearing NBD socket");
367 7a5ca864 bellard
368 7a5ca864 bellard
        if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
369 7a5ca864 bellard
                int serrno = errno;
370 7a5ca864 bellard
                LOG("Failed clearing NBD socket");
371 7a5ca864 bellard
                errno = serrno;
372 7a5ca864 bellard
                return -1;
373 7a5ca864 bellard
        }
374 7a5ca864 bellard
375 7a5ca864 bellard
        TRACE("Setting NBD socket");
376 7a5ca864 bellard
377 7a5ca864 bellard
        if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
378 7a5ca864 bellard
                int serrno = errno;
379 7a5ca864 bellard
                LOG("Failed to set NBD socket");
380 7a5ca864 bellard
                errno = serrno;
381 7a5ca864 bellard
                return -1;
382 7a5ca864 bellard
        }
383 7a5ca864 bellard
384 7a5ca864 bellard
        TRACE("Negotiation ended");
385 7a5ca864 bellard
386 7a5ca864 bellard
        return 0;
387 7a5ca864 bellard
}
388 7a5ca864 bellard
389 7a5ca864 bellard
int nbd_disconnect(int fd)
390 7a5ca864 bellard
{
391 7a5ca864 bellard
        ioctl(fd, NBD_CLEAR_QUE);
392 7a5ca864 bellard
        ioctl(fd, NBD_DISCONNECT);
393 7a5ca864 bellard
        ioctl(fd, NBD_CLEAR_SOCK);
394 7a5ca864 bellard
        return 0;
395 7a5ca864 bellard
}
396 7a5ca864 bellard
397 7a5ca864 bellard
int nbd_client(int fd, int csock)
398 7a5ca864 bellard
{
399 7a5ca864 bellard
        int ret;
400 7a5ca864 bellard
        int serrno;
401 7a5ca864 bellard
402 7a5ca864 bellard
        TRACE("Doing NBD loop");
403 7a5ca864 bellard
404 7a5ca864 bellard
        ret = ioctl(fd, NBD_DO_IT);
405 7a5ca864 bellard
        serrno = errno;
406 7a5ca864 bellard
407 7a5ca864 bellard
        TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
408 7a5ca864 bellard
409 7a5ca864 bellard
        TRACE("Clearing NBD queue");
410 7a5ca864 bellard
        ioctl(fd, NBD_CLEAR_QUE);
411 7a5ca864 bellard
412 7a5ca864 bellard
        TRACE("Clearing NBD socket");
413 7a5ca864 bellard
        ioctl(fd, NBD_CLEAR_SOCK);
414 7a5ca864 bellard
415 7a5ca864 bellard
        errno = serrno;
416 7a5ca864 bellard
        return ret;
417 7a5ca864 bellard
}
418 03ff3ca3 aliguori
#else
419 03ff3ca3 aliguori
int nbd_init(int fd, int csock, off_t size, size_t blocksize)
420 03ff3ca3 aliguori
{
421 03ff3ca3 aliguori
    errno = ENOTSUP;
422 03ff3ca3 aliguori
    return -1;
423 03ff3ca3 aliguori
}
424 03ff3ca3 aliguori
425 03ff3ca3 aliguori
int nbd_disconnect(int fd)
426 03ff3ca3 aliguori
{
427 03ff3ca3 aliguori
    errno = ENOTSUP;
428 03ff3ca3 aliguori
    return -1;
429 03ff3ca3 aliguori
}
430 03ff3ca3 aliguori
431 03ff3ca3 aliguori
int nbd_client(int fd, int csock)
432 03ff3ca3 aliguori
{
433 03ff3ca3 aliguori
    errno = ENOTSUP;
434 03ff3ca3 aliguori
    return -1;
435 03ff3ca3 aliguori
}
436 03ff3ca3 aliguori
#endif
437 7a5ca864 bellard
438 75818250 ths
int nbd_send_request(int csock, struct nbd_request *request)
439 7a5ca864 bellard
{
440 7a5ca864 bellard
        uint8_t buf[4 + 4 + 8 + 8 + 4];
441 7a5ca864 bellard
442 75818250 ths
        cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
443 75818250 ths
        cpu_to_be32w((uint32_t*)(buf + 4), request->type);
444 75818250 ths
        cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
445 75818250 ths
        cpu_to_be64w((uint64_t*)(buf + 16), request->from);
446 75818250 ths
        cpu_to_be32w((uint32_t*)(buf + 24), request->len);
447 75818250 ths
448 75818250 ths
        TRACE("Sending request to client");
449 75818250 ths
450 75818250 ths
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
451 75818250 ths
                LOG("writing to socket failed");
452 75818250 ths
                errno = EINVAL;
453 75818250 ths
                return -1;
454 75818250 ths
        }
455 75818250 ths
        return 0;
456 75818250 ths
}
457 75818250 ths
458 75818250 ths
459 75818250 ths
static int nbd_receive_request(int csock, struct nbd_request *request)
460 75818250 ths
{
461 75818250 ths
        uint8_t buf[4 + 4 + 8 + 8 + 4];
462 75818250 ths
        uint32_t magic;
463 7a5ca864 bellard
464 7a5ca864 bellard
        if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
465 7a5ca864 bellard
                LOG("read failed");
466 7a5ca864 bellard
                errno = EINVAL;
467 7a5ca864 bellard
                return -1;
468 7a5ca864 bellard
        }
469 7a5ca864 bellard
470 7a5ca864 bellard
        /* Request
471 75818250 ths
           [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
472 75818250 ths
           [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
473 75818250 ths
           [ 8 .. 15]   handle
474 75818250 ths
           [16 .. 23]   from
475 75818250 ths
           [24 .. 27]   len
476 7a5ca864 bellard
         */
477 7a5ca864 bellard
478 7a5ca864 bellard
        magic = be32_to_cpup((uint32_t*)buf);
479 75818250 ths
        request->type  = be32_to_cpup((uint32_t*)(buf + 4));
480 75818250 ths
        request->handle = be64_to_cpup((uint64_t*)(buf + 8));
481 75818250 ths
        request->from  = be64_to_cpup((uint64_t*)(buf + 16));
482 75818250 ths
        request->len   = be32_to_cpup((uint32_t*)(buf + 24));
483 7a5ca864 bellard
484 7a5ca864 bellard
        TRACE("Got request: "
485 7a5ca864 bellard
              "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
486 75818250 ths
              magic, request->type, request->from, request->len);
487 7a5ca864 bellard
488 7a5ca864 bellard
        if (magic != NBD_REQUEST_MAGIC) {
489 7a5ca864 bellard
                LOG("invalid magic (got 0x%x)", magic);
490 7a5ca864 bellard
                errno = EINVAL;
491 7a5ca864 bellard
                return -1;
492 7a5ca864 bellard
        }
493 d94888e3 malc
        return 0;
494 75818250 ths
}
495 75818250 ths
496 75818250 ths
int nbd_receive_reply(int csock, struct nbd_reply *reply)
497 75818250 ths
{
498 75818250 ths
        uint8_t buf[4 + 4 + 8];
499 75818250 ths
        uint32_t magic;
500 75818250 ths
501 75818250 ths
        memset(buf, 0xAA, sizeof(buf));
502 75818250 ths
503 75818250 ths
        if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
504 75818250 ths
                LOG("read failed");
505 75818250 ths
                errno = EINVAL;
506 75818250 ths
                return -1;
507 75818250 ths
        }
508 75818250 ths
509 75818250 ths
        /* Reply
510 75818250 ths
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
511 75818250 ths
           [ 4 ..  7]    error   (0 == no error)
512 75818250 ths
           [ 7 .. 15]    handle
513 75818250 ths
         */
514 75818250 ths
515 75818250 ths
        magic = be32_to_cpup((uint32_t*)buf);
516 75818250 ths
        reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
517 75818250 ths
        reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
518 75818250 ths
519 75818250 ths
        TRACE("Got reply: "
520 75818250 ths
              "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
521 75818250 ths
              magic, reply->error, reply->handle);
522 75818250 ths
523 75818250 ths
        if (magic != NBD_REPLY_MAGIC) {
524 75818250 ths
                LOG("invalid magic (got 0x%x)", magic);
525 75818250 ths
                errno = EINVAL;
526 75818250 ths
                return -1;
527 75818250 ths
        }
528 75818250 ths
        return 0;
529 75818250 ths
}
530 75818250 ths
531 75818250 ths
static int nbd_send_reply(int csock, struct nbd_reply *reply)
532 75818250 ths
{
533 75818250 ths
        uint8_t buf[4 + 4 + 8];
534 75818250 ths
535 75818250 ths
        /* Reply
536 75818250 ths
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
537 75818250 ths
           [ 4 ..  7]    error   (0 == no error)
538 75818250 ths
           [ 7 .. 15]    handle
539 75818250 ths
         */
540 75818250 ths
        cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
541 75818250 ths
        cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
542 75818250 ths
        cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
543 75818250 ths
544 75818250 ths
        TRACE("Sending response to client");
545 75818250 ths
546 75818250 ths
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
547 75818250 ths
                LOG("writing to socket failed");
548 75818250 ths
                errno = EINVAL;
549 75818250 ths
                return -1;
550 75818250 ths
        }
551 75818250 ths
        return 0;
552 75818250 ths
}
553 7a5ca864 bellard
554 75818250 ths
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
555 75818250 ths
             off_t *offset, bool readonly, uint8_t *data, int data_size)
556 75818250 ths
{
557 75818250 ths
        struct nbd_request request;
558 75818250 ths
        struct nbd_reply reply;
559 75818250 ths
560 75818250 ths
        TRACE("Reading request.");
561 75818250 ths
562 75818250 ths
        if (nbd_receive_request(csock, &request) == -1)
563 75818250 ths
                return -1;
564 75818250 ths
565 75818250 ths
        if (request.len > data_size) {
566 2f726488 ths
                LOG("len (%u) is larger than max len (%u)",
567 75818250 ths
                    request.len, data_size);
568 7a5ca864 bellard
                errno = EINVAL;
569 7a5ca864 bellard
                return -1;
570 7a5ca864 bellard
        }
571 7a5ca864 bellard
572 75818250 ths
        if ((request.from + request.len) < request.from) {
573 7a5ca864 bellard
                LOG("integer overflow detected! "
574 7a5ca864 bellard
                    "you're probably being attacked");
575 7a5ca864 bellard
                errno = EINVAL;
576 7a5ca864 bellard
                return -1;
577 7a5ca864 bellard
        }
578 7a5ca864 bellard
579 75818250 ths
        if ((request.from + request.len) > size) {
580 7a5ca864 bellard
                LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
581 7a5ca864 bellard
                    ", Offset: %" PRIu64 "\n",
582 b9e82a59 blueswir1
                    request.from, request.len, (uint64_t)size, dev_offset);
583 7a5ca864 bellard
                LOG("requested operation past EOF--bad client?");
584 7a5ca864 bellard
                errno = EINVAL;
585 7a5ca864 bellard
                return -1;
586 7a5ca864 bellard
        }
587 7a5ca864 bellard
588 7a5ca864 bellard
        TRACE("Decoding type");
589 7a5ca864 bellard
590 75818250 ths
        reply.handle = request.handle;
591 75818250 ths
        reply.error = 0;
592 75818250 ths
593 75818250 ths
        switch (request.type) {
594 75818250 ths
        case NBD_CMD_READ:
595 7a5ca864 bellard
                TRACE("Request type is READ");
596 7a5ca864 bellard
597 75818250 ths
                if (bdrv_read(bs, (request.from + dev_offset) / 512, data,
598 75818250 ths
                              request.len / 512) == -1) {
599 7a5ca864 bellard
                        LOG("reading from file failed");
600 7a5ca864 bellard
                        errno = EINVAL;
601 7a5ca864 bellard
                        return -1;
602 7a5ca864 bellard
                }
603 75818250 ths
                *offset += request.len;
604 7a5ca864 bellard
605 75818250 ths
                TRACE("Read %u byte(s)", request.len);
606 7a5ca864 bellard
607 75818250 ths
                if (nbd_send_reply(csock, &reply) == -1)
608 7a5ca864 bellard
                        return -1;
609 7a5ca864 bellard
610 7a5ca864 bellard
                TRACE("Sending data to client");
611 7a5ca864 bellard
612 75818250 ths
                if (write_sync(csock, data, request.len) != request.len) {
613 7a5ca864 bellard
                        LOG("writing to socket failed");
614 7a5ca864 bellard
                        errno = EINVAL;
615 7a5ca864 bellard
                        return -1;
616 7a5ca864 bellard
                }
617 7a5ca864 bellard
                break;
618 75818250 ths
        case NBD_CMD_WRITE:
619 7a5ca864 bellard
                TRACE("Request type is WRITE");
620 7a5ca864 bellard
621 75818250 ths
                TRACE("Reading %u byte(s)", request.len);
622 7a5ca864 bellard
623 75818250 ths
                if (read_sync(csock, data, request.len) != request.len) {
624 7a5ca864 bellard
                        LOG("reading from socket failed");
625 7a5ca864 bellard
                        errno = EINVAL;
626 7a5ca864 bellard
                        return -1;
627 7a5ca864 bellard
                }
628 7a5ca864 bellard
629 7a5ca864 bellard
                if (readonly) {
630 7a5ca864 bellard
                        TRACE("Server is read-only, return error");
631 75818250 ths
                        reply.error = 1;
632 7a5ca864 bellard
                } else {
633 7a5ca864 bellard
                        TRACE("Writing to device");
634 7a5ca864 bellard
635 75818250 ths
                        if (bdrv_write(bs, (request.from + dev_offset) / 512,
636 75818250 ths
                                       data, request.len / 512) == -1) {
637 7a5ca864 bellard
                                LOG("writing to file failed");
638 7a5ca864 bellard
                                errno = EINVAL;
639 7a5ca864 bellard
                                return -1;
640 7a5ca864 bellard
                        }
641 7a5ca864 bellard
642 75818250 ths
                        *offset += request.len;
643 7a5ca864 bellard
                }
644 7a5ca864 bellard
645 75818250 ths
                if (nbd_send_reply(csock, &reply) == -1)
646 7a5ca864 bellard
                        return -1;
647 7a5ca864 bellard
                break;
648 75818250 ths
        case NBD_CMD_DISC:
649 7a5ca864 bellard
                TRACE("Request type is DISCONNECT");
650 7a5ca864 bellard
                errno = 0;
651 7a5ca864 bellard
                return 1;
652 7a5ca864 bellard
        default:
653 75818250 ths
                LOG("invalid request type (%u) received", request.type);
654 7a5ca864 bellard
                errno = EINVAL;
655 7a5ca864 bellard
                return -1;
656 7a5ca864 bellard
        }
657 7a5ca864 bellard
658 7a5ca864 bellard
        TRACE("Request/Reply complete");
659 7a5ca864 bellard
660 7a5ca864 bellard
        return 0;
661 7a5ca864 bellard
}