Statistics
| Branch: | Revision:

root / nbd.c @ 1743b515

History | View | Annotate | Download (22.3 kB)

1
/*
2
 *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
3
 *
4
 *  Network Block Device
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; under version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17
 */
18

    
19
#include "nbd.h"
20
#include "block.h"
21
#include "block_int.h"
22

    
23
#include <errno.h>
24
#include <string.h>
25
#ifndef _WIN32
26
#include <sys/ioctl.h>
27
#endif
28
#if defined(__sun__) || defined(__HAIKU__)
29
#include <sys/ioccom.h>
30
#endif
31
#include <ctype.h>
32
#include <inttypes.h>
33

    
34
#ifdef __linux__
35
#include <linux/fs.h>
36
#endif
37

    
38
#include "qemu_socket.h"
39
#include "qemu-queue.h"
40

    
41
//#define DEBUG_NBD
42

    
43
#ifdef DEBUG_NBD
44
#define TRACE(msg, ...) do { \
45
    LOG(msg, ## __VA_ARGS__); \
46
} while(0)
47
#else
48
#define TRACE(msg, ...) \
49
    do { } while (0)
50
#endif
51

    
52
#define LOG(msg, ...) do { \
53
    fprintf(stderr, "%s:%s():L%d: " msg "\n", \
54
            __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
55
} while(0)
56

    
57
/* This is all part of the "official" NBD API */
58

    
59
#define NBD_REPLY_SIZE          (4 + 4 + 8)
60
#define NBD_REQUEST_MAGIC       0x25609513
61
#define NBD_REPLY_MAGIC         0x67446698
62

    
63
#define NBD_SET_SOCK            _IO(0xab, 0)
64
#define NBD_SET_BLKSIZE         _IO(0xab, 1)
65
#define NBD_SET_SIZE            _IO(0xab, 2)
66
#define NBD_DO_IT               _IO(0xab, 3)
67
#define NBD_CLEAR_SOCK          _IO(0xab, 4)
68
#define NBD_CLEAR_QUE           _IO(0xab, 5)
69
#define NBD_PRINT_DEBUG         _IO(0xab, 6)
70
#define NBD_SET_SIZE_BLOCKS     _IO(0xab, 7)
71
#define NBD_DISCONNECT          _IO(0xab, 8)
72
#define NBD_SET_TIMEOUT         _IO(0xab, 9)
73
#define NBD_SET_FLAGS           _IO(0xab, 10)
74

    
75
#define NBD_OPT_EXPORT_NAME     (1 << 0)
76

    
77
/* That's all folks */
78

    
79
#define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
80
#define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false)
81

    
82
size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
83
{
84
    size_t offset = 0;
85

    
86
    if (qemu_in_coroutine()) {
87
        if (do_read) {
88
            return qemu_co_recv(fd, buffer, size);
89
        } else {
90
            return qemu_co_send(fd, buffer, size);
91
        }
92
    }
93

    
94
    while (offset < size) {
95
        ssize_t len;
96

    
97
        if (do_read) {
98
            len = qemu_recv(fd, buffer + offset, size - offset, 0);
99
        } else {
100
            len = send(fd, buffer + offset, size - offset, 0);
101
        }
102

    
103
        if (len == -1)
104
            errno = socket_error();
105

    
106
        /* recoverable error */
107
        if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
108
            continue;
109
        }
110

    
111
        /* eof */
112
        if (len == 0) {
113
            break;
114
        }
115

    
116
        /* unrecoverable error */
117
        if (len == -1) {
118
            return 0;
119
        }
120

    
121
        offset += len;
122
    }
123

    
124
    return offset;
125
}
126

    
127
static void combine_addr(char *buf, size_t len, const char* address,
128
                         uint16_t port)
129
{
130
    /* If the address-part contains a colon, it's an IPv6 IP so needs [] */
131
    if (strstr(address, ":")) {
132
        snprintf(buf, len, "[%s]:%u", address, port);
133
    } else {
134
        snprintf(buf, len, "%s:%u", address, port);
135
    }
136
}
137

    
138
int tcp_socket_outgoing(const char *address, uint16_t port)
139
{
140
    char address_and_port[128];
141
    combine_addr(address_and_port, 128, address, port);
142
    return tcp_socket_outgoing_spec(address_and_port);
143
}
144

    
145
int tcp_socket_outgoing_spec(const char *address_and_port)
146
{
147
    return inet_connect(address_and_port, SOCK_STREAM);
148
}
149

    
150
int tcp_socket_incoming(const char *address, uint16_t port)
151
{
152
    char address_and_port[128];
153
    combine_addr(address_and_port, 128, address, port);
154
    return tcp_socket_incoming_spec(address_and_port);
155
}
156

    
157
int tcp_socket_incoming_spec(const char *address_and_port)
158
{
159
    char *ostr  = NULL;
160
    int olen = 0;
161
    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0);
162
}
163

    
164
int unix_socket_incoming(const char *path)
165
{
166
    char *ostr = NULL;
167
    int olen = 0;
168

    
169
    return unix_listen(path, ostr, olen);
170
}
171

    
172
int unix_socket_outgoing(const char *path)
173
{
174
    return unix_connect(path);
175
}
176

    
177
/* Basic flow
178

179
   Server         Client
180

181
   Negotiate
182
                  Request
183
   Response
184
                  Request
185
   Response
186
                  ...
187
   ...
188
                  Request (type == 2)
189
*/
190

    
191
static int nbd_send_negotiate(int csock, off_t size, uint32_t flags)
192
{
193
    char buf[8 + 8 + 8 + 128];
194

    
195
    /* Negotiate
196
        [ 0 ..   7]   passwd   ("NBDMAGIC")
197
        [ 8 ..  15]   magic    (0x00420281861253)
198
        [16 ..  23]   size
199
        [24 ..  27]   flags
200
        [28 .. 151]   reserved (0)
201
     */
202

    
203
    TRACE("Beginning negotiation.");
204
    memcpy(buf, "NBDMAGIC", 8);
205
    cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
206
    cpu_to_be64w((uint64_t*)(buf + 16), size);
207
    cpu_to_be32w((uint32_t*)(buf + 24),
208
                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
209
                 NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
210
    memset(buf + 28, 0, 124);
211

    
212
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
213
        LOG("write failed");
214
        errno = EINVAL;
215
        return -1;
216
    }
217

    
218
    TRACE("Negotiation succeeded.");
219

    
220
    return 0;
221
}
222

    
223
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
224
                          off_t *size, size_t *blocksize)
225
{
226
    char buf[256];
227
    uint64_t magic, s;
228
    uint16_t tmp;
229

    
230
    TRACE("Receiving negotiation.");
231

    
232
    if (read_sync(csock, buf, 8) != 8) {
233
        LOG("read failed");
234
        errno = EINVAL;
235
        return -1;
236
    }
237

    
238
    buf[8] = '\0';
239
    if (strlen(buf) == 0) {
240
        LOG("server connection closed");
241
        errno = EINVAL;
242
        return -1;
243
    }
244

    
245
    TRACE("Magic is %c%c%c%c%c%c%c%c",
246
          qemu_isprint(buf[0]) ? buf[0] : '.',
247
          qemu_isprint(buf[1]) ? buf[1] : '.',
248
          qemu_isprint(buf[2]) ? buf[2] : '.',
249
          qemu_isprint(buf[3]) ? buf[3] : '.',
250
          qemu_isprint(buf[4]) ? buf[4] : '.',
251
          qemu_isprint(buf[5]) ? buf[5] : '.',
252
          qemu_isprint(buf[6]) ? buf[6] : '.',
253
          qemu_isprint(buf[7]) ? buf[7] : '.');
254

    
255
    if (memcmp(buf, "NBDMAGIC", 8) != 0) {
256
        LOG("Invalid magic received");
257
        errno = EINVAL;
258
        return -1;
259
    }
260

    
261
    if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
262
        LOG("read failed");
263
        errno = EINVAL;
264
        return -1;
265
    }
266
    magic = be64_to_cpu(magic);
267
    TRACE("Magic is 0x%" PRIx64, magic);
268

    
269
    if (name) {
270
        uint32_t reserved = 0;
271
        uint32_t opt;
272
        uint32_t namesize;
273

    
274
        TRACE("Checking magic (opts_magic)");
275
        if (magic != 0x49484156454F5054LL) {
276
            LOG("Bad magic received");
277
            errno = EINVAL;
278
            return -1;
279
        }
280
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
281
            LOG("flags read failed");
282
            errno = EINVAL;
283
            return -1;
284
        }
285
        *flags = be16_to_cpu(tmp) << 16;
286
        /* reserved for future use */
287
        if (write_sync(csock, &reserved, sizeof(reserved)) !=
288
            sizeof(reserved)) {
289
            LOG("write failed (reserved)");
290
            errno = EINVAL;
291
            return -1;
292
        }
293
        /* write the export name */
294
        magic = cpu_to_be64(magic);
295
        if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
296
            LOG("write failed (magic)");
297
            errno = EINVAL;
298
            return -1;
299
        }
300
        opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
301
        if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
302
            LOG("write failed (opt)");
303
            errno = EINVAL;
304
            return -1;
305
        }
306
        namesize = cpu_to_be32(strlen(name));
307
        if (write_sync(csock, &namesize, sizeof(namesize)) !=
308
            sizeof(namesize)) {
309
            LOG("write failed (namesize)");
310
            errno = EINVAL;
311
            return -1;
312
        }
313
        if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
314
            LOG("write failed (name)");
315
            errno = EINVAL;
316
            return -1;
317
        }
318
    } else {
319
        TRACE("Checking magic (cli_magic)");
320

    
321
        if (magic != 0x00420281861253LL) {
322
            LOG("Bad magic received");
323
            errno = EINVAL;
324
            return -1;
325
        }
326
    }
327

    
328
    if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
329
        LOG("read failed");
330
        errno = EINVAL;
331
        return -1;
332
    }
333
    *size = be64_to_cpu(s);
334
    *blocksize = 1024;
335
    TRACE("Size is %" PRIu64, *size);
336

    
337
    if (!name) {
338
        if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
339
            LOG("read failed (flags)");
340
            errno = EINVAL;
341
            return -1;
342
        }
343
        *flags = be32_to_cpup(flags);
344
    } else {
345
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
346
            LOG("read failed (tmp)");
347
            errno = EINVAL;
348
            return -1;
349
        }
350
        *flags |= be32_to_cpu(tmp);
351
    }
352
    if (read_sync(csock, &buf, 124) != 124) {
353
        LOG("read failed (buf)");
354
        errno = EINVAL;
355
        return -1;
356
    }
357
        return 0;
358
}
359

    
360
#ifdef __linux__
361
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
362
{
363
    TRACE("Setting NBD socket");
364

    
365
    if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
366
        int serrno = errno;
367
        LOG("Failed to set NBD socket");
368
        errno = serrno;
369
        return -1;
370
    }
371

    
372
    TRACE("Setting block size to %lu", (unsigned long)blocksize);
373

    
374
    if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
375
        int serrno = errno;
376
        LOG("Failed setting NBD block size");
377
        errno = serrno;
378
        return -1;
379
    }
380

    
381
        TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
382

    
383
    if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
384
        int serrno = errno;
385
        LOG("Failed setting size (in blocks)");
386
        errno = serrno;
387
        return -1;
388
    }
389

    
390
    if (flags & NBD_FLAG_READ_ONLY) {
391
        int read_only = 1;
392
        TRACE("Setting readonly attribute");
393

    
394
        if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
395
            int serrno = errno;
396
            LOG("Failed setting read-only attribute");
397
            errno = serrno;
398
            return -1;
399
        }
400
    }
401

    
402
    if (ioctl(fd, NBD_SET_FLAGS, flags) < 0
403
        && errno != ENOTTY) {
404
        int serrno = errno;
405
        LOG("Failed setting flags");
406
        errno = serrno;
407
        return -1;
408
    }
409

    
410
    TRACE("Negotiation ended");
411

    
412
    return 0;
413
}
414

    
415
int nbd_disconnect(int fd)
416
{
417
    ioctl(fd, NBD_CLEAR_QUE);
418
    ioctl(fd, NBD_DISCONNECT);
419
    ioctl(fd, NBD_CLEAR_SOCK);
420
    return 0;
421
}
422

    
423
int nbd_client(int fd)
424
{
425
    int ret;
426
    int serrno;
427

    
428
    TRACE("Doing NBD loop");
429

    
430
    ret = ioctl(fd, NBD_DO_IT);
431
    if (ret == -1 && errno == EPIPE) {
432
        /* NBD_DO_IT normally returns EPIPE when someone has disconnected
433
         * the socket via NBD_DISCONNECT.  We do not want to return 1 in
434
         * that case.
435
         */
436
        ret = 0;
437
    }
438
    serrno = errno;
439

    
440
    TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
441

    
442
    TRACE("Clearing NBD queue");
443
    ioctl(fd, NBD_CLEAR_QUE);
444

    
445
    TRACE("Clearing NBD socket");
446
    ioctl(fd, NBD_CLEAR_SOCK);
447

    
448
    errno = serrno;
449
    return ret;
450
}
451
#else
452
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
453
{
454
    errno = ENOTSUP;
455
    return -1;
456
}
457

    
458
int nbd_disconnect(int fd)
459
{
460
    errno = ENOTSUP;
461
    return -1;
462
}
463

    
464
int nbd_client(int fd)
465
{
466
    errno = ENOTSUP;
467
    return -1;
468
}
469
#endif
470

    
471
int nbd_send_request(int csock, struct nbd_request *request)
472
{
473
    uint8_t buf[4 + 4 + 8 + 8 + 4];
474

    
475
    cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
476
    cpu_to_be32w((uint32_t*)(buf + 4), request->type);
477
    cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
478
    cpu_to_be64w((uint64_t*)(buf + 16), request->from);
479
    cpu_to_be32w((uint32_t*)(buf + 24), request->len);
480

    
481
    TRACE("Sending request to client: "
482
          "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
483
          request->from, request->len, request->handle, request->type);
484

    
485
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
486
        LOG("writing to socket failed");
487
        errno = EINVAL;
488
        return -1;
489
    }
490
    return 0;
491
}
492

    
493
static int nbd_receive_request(int csock, struct nbd_request *request)
494
{
495
    uint8_t buf[4 + 4 + 8 + 8 + 4];
496
    uint32_t magic;
497

    
498
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
499
        LOG("read failed");
500
        errno = EINVAL;
501
        return -1;
502
    }
503

    
504
    /* Request
505
       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
506
       [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
507
       [ 8 .. 15]   handle
508
       [16 .. 23]   from
509
       [24 .. 27]   len
510
     */
511

    
512
    magic = be32_to_cpup((uint32_t*)buf);
513
    request->type  = be32_to_cpup((uint32_t*)(buf + 4));
514
    request->handle = be64_to_cpup((uint64_t*)(buf + 8));
515
    request->from  = be64_to_cpup((uint64_t*)(buf + 16));
516
    request->len   = be32_to_cpup((uint32_t*)(buf + 24));
517

    
518
    TRACE("Got request: "
519
          "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
520
          magic, request->type, request->from, request->len);
521

    
522
    if (magic != NBD_REQUEST_MAGIC) {
523
        LOG("invalid magic (got 0x%x)", magic);
524
        errno = EINVAL;
525
        return -1;
526
    }
527
    return 0;
528
}
529

    
530
int nbd_receive_reply(int csock, struct nbd_reply *reply)
531
{
532
    uint8_t buf[NBD_REPLY_SIZE];
533
    uint32_t magic;
534

    
535
    memset(buf, 0xAA, sizeof(buf));
536

    
537
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
538
        LOG("read failed");
539
        errno = EINVAL;
540
        return -1;
541
    }
542

    
543
    /* Reply
544
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
545
       [ 4 ..  7]    error   (0 == no error)
546
       [ 7 .. 15]    handle
547
     */
548

    
549
    magic = be32_to_cpup((uint32_t*)buf);
550
    reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
551
    reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
552

    
553
    TRACE("Got reply: "
554
          "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
555
          magic, reply->error, reply->handle);
556

    
557
    if (magic != NBD_REPLY_MAGIC) {
558
        LOG("invalid magic (got 0x%x)", magic);
559
        errno = EINVAL;
560
        return -1;
561
    }
562
    return 0;
563
}
564

    
565
static int nbd_send_reply(int csock, struct nbd_reply *reply)
566
{
567
    uint8_t buf[4 + 4 + 8];
568

    
569
    /* Reply
570
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
571
       [ 4 ..  7]    error   (0 == no error)
572
       [ 7 .. 15]    handle
573
     */
574
    cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
575
    cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
576
    cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
577

    
578
    TRACE("Sending response to client");
579

    
580
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
581
        LOG("writing to socket failed");
582
        errno = EINVAL;
583
        return -1;
584
    }
585
    return 0;
586
}
587

    
588
typedef struct NBDRequest NBDRequest;
589

    
590
struct NBDRequest {
591
    QSIMPLEQ_ENTRY(NBDRequest) entry;
592
    uint8_t *data;
593
};
594

    
595
struct NBDExport {
596
    BlockDriverState *bs;
597
    off_t dev_offset;
598
    off_t size;
599
    uint32_t nbdflags;
600
    QSIMPLEQ_HEAD(, NBDRequest) requests;
601
};
602

    
603
struct NBDClient {
604
    int refcount;
605
    void (*close)(NBDClient *client);
606

    
607
    NBDExport *exp;
608
    int sock;
609
};
610

    
611
static void nbd_client_get(NBDClient *client)
612
{
613
    client->refcount++;
614
}
615

    
616
static void nbd_client_put(NBDClient *client)
617
{
618
    if (--client->refcount == 0) {
619
        g_free(client);
620
    }
621
}
622

    
623
static void nbd_client_close(NBDClient *client)
624
{
625
    qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL);
626
    close(client->sock);
627
    client->sock = -1;
628
    if (client->close) {
629
        client->close(client);
630
    }
631
    nbd_client_put(client);
632
}
633

    
634
static NBDRequest *nbd_request_get(NBDExport *exp)
635
{
636
    NBDRequest *req;
637
    if (QSIMPLEQ_EMPTY(&exp->requests)) {
638
        req = g_malloc0(sizeof(NBDRequest));
639
        req->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE);
640
    } else {
641
        req = QSIMPLEQ_FIRST(&exp->requests);
642
        QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
643
    }
644
    return req;
645
}
646

    
647
static void nbd_request_put(NBDExport *exp, NBDRequest *req)
648
{
649
    QSIMPLEQ_INSERT_HEAD(&exp->requests, req, entry);
650
}
651

    
652
NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset,
653
                          off_t size, uint32_t nbdflags)
654
{
655
    NBDExport *exp = g_malloc0(sizeof(NBDExport));
656
    QSIMPLEQ_INIT(&exp->requests);
657
    exp->bs = bs;
658
    exp->dev_offset = dev_offset;
659
    exp->nbdflags = nbdflags;
660
    exp->size = size == -1 ? exp->bs->total_sectors * 512 : size;
661
    return exp;
662
}
663

    
664
void nbd_export_close(NBDExport *exp)
665
{
666
    while (!QSIMPLEQ_EMPTY(&exp->requests)) {
667
        NBDRequest *first = QSIMPLEQ_FIRST(&exp->requests);
668
        QSIMPLEQ_REMOVE_HEAD(&exp->requests, entry);
669
        qemu_vfree(first->data);
670
        g_free(first);
671
    }
672

    
673
    bdrv_close(exp->bs);
674
    g_free(exp);
675
}
676

    
677
static int nbd_do_send_reply(int csock, struct nbd_reply *reply,
678
                             uint8_t *data, int len)
679
{
680
    int rc, ret;
681

    
682
    if (!len) {
683
        rc = nbd_send_reply(csock, reply);
684
        if (rc == -1) {
685
            rc = -errno;
686
        }
687
    } else {
688
        socket_set_cork(csock, 1);
689
        rc = nbd_send_reply(csock, reply);
690
        if (rc != -1) {
691
            ret = write_sync(csock, data, len);
692
            if (ret != len) {
693
                errno = EIO;
694
                rc = -1;
695
            }
696
        }
697
        if (rc == -1) {
698
            rc = -errno;
699
        }
700
        socket_set_cork(csock, 0);
701
    }
702
    return rc;
703
}
704

    
705
static int nbd_do_receive_request(int csock, struct nbd_request *request,
706
                                  uint8_t *data)
707
{
708
    int rc;
709

    
710
    if (nbd_receive_request(csock, request) == -1) {
711
        rc = -EIO;
712
        goto out;
713
    }
714

    
715
    if (request->len > NBD_BUFFER_SIZE) {
716
        LOG("len (%u) is larger than max len (%u)",
717
            request->len, NBD_BUFFER_SIZE);
718
        rc = -EINVAL;
719
        goto out;
720
    }
721

    
722
    if ((request->from + request->len) < request->from) {
723
        LOG("integer overflow detected! "
724
            "you're probably being attacked");
725
        rc = -EINVAL;
726
        goto out;
727
    }
728

    
729
    TRACE("Decoding type");
730

    
731
    if ((request->type & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) {
732
        TRACE("Reading %u byte(s)", request->len);
733

    
734
        if (read_sync(csock, data, request->len) != request->len) {
735
            LOG("reading from socket failed");
736
            rc = -EIO;
737
            goto out;
738
        }
739
    }
740
    rc = 0;
741

    
742
out:
743
    return rc;
744
}
745

    
746
static int nbd_trip(NBDClient *client)
747
{
748
    NBDExport *exp = client->exp;
749
    NBDRequest *req = nbd_request_get(exp);
750
    int csock = client->sock;
751
    struct nbd_request request;
752
    struct nbd_reply reply;
753
    int rc = -1;
754
    int ret;
755

    
756
    TRACE("Reading request.");
757

    
758
    ret = nbd_do_receive_request(csock, &request, req->data);
759
    if (ret == -EIO) {
760
        goto out;
761
    }
762

    
763
    reply.handle = request.handle;
764
    reply.error = 0;
765

    
766
    if (ret < 0) {
767
        reply.error = -ret;
768
        goto error_reply;
769
    }
770

    
771
    if ((request.from + request.len) > exp->size) {
772
            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
773
            ", Offset: %" PRIu64 "\n",
774
                    request.from, request.len,
775
                    (uint64_t)exp->size, exp->dev_offset);
776
        LOG("requested operation past EOF--bad client?");
777
        goto invalid_request;
778
    }
779

    
780
    switch (request.type & NBD_CMD_MASK_COMMAND) {
781
    case NBD_CMD_READ:
782
        TRACE("Request type is READ");
783

    
784
        ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512,
785
                        req->data, request.len / 512);
786
        if (ret < 0) {
787
            LOG("reading from file failed");
788
            reply.error = -ret;
789
            goto error_reply;
790
        }
791

    
792
        TRACE("Read %u byte(s)", request.len);
793
        if (nbd_do_send_reply(csock, &reply, req->data, request.len) < 0)
794
            goto out;
795
        break;
796
    case NBD_CMD_WRITE:
797
        TRACE("Request type is WRITE");
798

    
799
        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {
800
            TRACE("Server is read-only, return error");
801
            reply.error = EROFS;
802
            goto error_reply;
803
        }
804

    
805
        TRACE("Writing to device");
806

    
807
        ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512,
808
                         req->data, request.len / 512);
809
        if (ret < 0) {
810
            LOG("writing to file failed");
811
            reply.error = -ret;
812
            goto error_reply;
813
        }
814

    
815
        if (request.type & NBD_CMD_FLAG_FUA) {
816
            ret = bdrv_flush(exp->bs);
817
            if (ret < 0) {
818
                LOG("flush failed");
819
                reply.error = -ret;
820
                goto error_reply;
821
            }
822
        }
823

    
824
        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
825
            goto out;
826
        break;
827
    case NBD_CMD_DISC:
828
        TRACE("Request type is DISCONNECT");
829
        errno = 0;
830
        return 1;
831
    case NBD_CMD_FLUSH:
832
        TRACE("Request type is FLUSH");
833

    
834
        ret = bdrv_flush(exp->bs);
835
        if (ret < 0) {
836
            LOG("flush failed");
837
            reply.error = -ret;
838
        }
839

    
840
        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
841
            goto out;
842
        break;
843
    case NBD_CMD_TRIM:
844
        TRACE("Request type is TRIM");
845
        ret = bdrv_discard(exp->bs, (request.from + exp->dev_offset) / 512,
846
                           request.len / 512);
847
        if (ret < 0) {
848
            LOG("discard failed");
849
            reply.error = -ret;
850
        }
851
        if (nbd_do_send_reply(csock, &reply, NULL, 0) < 0)
852
            goto out;
853
        break;
854
    default:
855
        LOG("invalid request type (%u) received", request.type);
856
    invalid_request:
857
        reply.error = -EINVAL;
858
    error_reply:
859
        if (nbd_do_send_reply(csock, &reply, NULL, 0) == -1)
860
            goto out;
861
        break;
862
    }
863

    
864
    TRACE("Request/Reply complete");
865

    
866
    rc = 0;
867
out:
868
    nbd_request_put(exp, req);
869
    return rc;
870
}
871

    
872
static void nbd_read(void *opaque)
873
{
874
    NBDClient *client = opaque;
875

    
876
    nbd_client_get(client);
877
    if (nbd_trip(client) != 0) {
878
        nbd_client_close(client);
879
    }
880

    
881
    nbd_client_put(client);
882
}
883

    
884
NBDClient *nbd_client_new(NBDExport *exp, int csock,
885
                          void (*close)(NBDClient *))
886
{
887
    NBDClient *client;
888
    if (nbd_send_negotiate(csock, exp->size, exp->nbdflags) == -1) {
889
        return NULL;
890
    }
891
    client = g_malloc0(sizeof(NBDClient));
892
    client->refcount = 1;
893
    client->exp = exp;
894
    client->sock = csock;
895
    client->close = close;
896
    qemu_set_fd_handler2(csock, NULL, nbd_read, NULL, client);
897
    return client;
898
}