Statistics
| Branch: | Revision:

root / nbd.c @ 2c7989a9

History | View | Annotate | Download (18.5 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

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

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

    
37
#include "qemu_socket.h"
38

    
39
//#define DEBUG_NBD
40

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

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

    
55
/* This is all part of the "official" NBD API */
56

    
57
#define NBD_REPLY_SIZE          (4 + 4 + 8)
58
#define NBD_REQUEST_MAGIC       0x25609513
59
#define NBD_REPLY_MAGIC         0x67446698
60

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

    
73
#define NBD_OPT_EXPORT_NAME     (1 << 0)
74

    
75
/* That's all folks */
76

    
77
#define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
78
#define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false)
79

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

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

    
92
    while (offset < size) {
93
        ssize_t len;
94

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

    
101
        if (len == -1)
102
            errno = socket_error();
103

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

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

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

    
119
        offset += len;
120
    }
121

    
122
    return offset;
123
}
124

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

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

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

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

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

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

    
167
    return unix_listen(path, ostr, olen);
168
}
169

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

    
175
/* Basic flow
176

177
   Server         Client
178

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

    
189
int nbd_negotiate(int csock, off_t size, uint32_t flags)
190
{
191
    char buf[8 + 8 + 8 + 128];
192

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

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

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

    
215
    TRACE("Negotiation succeeded.");
216

    
217
    return 0;
218
}
219

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

    
227
    TRACE("Receiving negotiation.");
228

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

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

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

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

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

    
266
    if (name) {
267
        uint32_t reserved = 0;
268
        uint32_t opt;
269
        uint32_t namesize;
270

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

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

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

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

    
357
#ifdef __linux__
358
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
359
{
360
    TRACE("Setting block size to %lu", (unsigned long)blocksize);
361

    
362
    if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
363
        int serrno = errno;
364
        LOG("Failed setting NBD block size");
365
        errno = serrno;
366
        return -1;
367
    }
368

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

    
371
    if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
372
        int serrno = errno;
373
        LOG("Failed setting size (in blocks)");
374
        errno = serrno;
375
        return -1;
376
    }
377

    
378
    if (flags & NBD_FLAG_READ_ONLY) {
379
        int read_only = 1;
380
        TRACE("Setting readonly attribute");
381

    
382
        if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
383
            int serrno = errno;
384
            LOG("Failed setting read-only attribute");
385
            errno = serrno;
386
            return -1;
387
        }
388
    }
389

    
390
    if (ioctl(fd, NBD_SET_FLAGS, flags) < 0
391
        && errno != ENOTTY) {
392
        int serrno = errno;
393
        LOG("Failed setting flags");
394
        errno = serrno;
395
        return -1;
396
    }
397

    
398
    TRACE("Clearing NBD socket");
399

    
400
    if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
401
        int serrno = errno;
402
        LOG("Failed clearing NBD socket");
403
        errno = serrno;
404
        return -1;
405
    }
406

    
407
    TRACE("Setting NBD socket");
408

    
409
    if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
410
        int serrno = errno;
411
        LOG("Failed to set NBD socket");
412
        errno = serrno;
413
        return -1;
414
    }
415

    
416
    TRACE("Negotiation ended");
417

    
418
    return 0;
419
}
420

    
421
int nbd_disconnect(int fd)
422
{
423
    ioctl(fd, NBD_CLEAR_QUE);
424
    ioctl(fd, NBD_DISCONNECT);
425
    ioctl(fd, NBD_CLEAR_SOCK);
426
    return 0;
427
}
428

    
429
int nbd_client(int fd)
430
{
431
    int ret;
432
    int serrno;
433

    
434
    TRACE("Doing NBD loop");
435

    
436
    ret = ioctl(fd, NBD_DO_IT);
437
    if (ret == -1 && errno == EPIPE) {
438
        /* NBD_DO_IT normally returns EPIPE when someone has disconnected
439
         * the socket via NBD_DISCONNECT.  We do not want to return 1 in
440
         * that case.
441
         */
442
        ret = 0;
443
    }
444
    serrno = errno;
445

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

    
448
    TRACE("Clearing NBD queue");
449
    ioctl(fd, NBD_CLEAR_QUE);
450

    
451
    TRACE("Clearing NBD socket");
452
    ioctl(fd, NBD_CLEAR_SOCK);
453

    
454
    errno = serrno;
455
    return ret;
456
}
457
#else
458
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
459
{
460
    errno = ENOTSUP;
461
    return -1;
462
}
463

    
464
int nbd_disconnect(int fd)
465
{
466
    errno = ENOTSUP;
467
    return -1;
468
}
469

    
470
int nbd_client(int fd)
471
{
472
    errno = ENOTSUP;
473
    return -1;
474
}
475
#endif
476

    
477
int nbd_send_request(int csock, struct nbd_request *request)
478
{
479
    uint8_t buf[4 + 4 + 8 + 8 + 4];
480

    
481
    cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
482
    cpu_to_be32w((uint32_t*)(buf + 4), request->type);
483
    cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
484
    cpu_to_be64w((uint64_t*)(buf + 16), request->from);
485
    cpu_to_be32w((uint32_t*)(buf + 24), request->len);
486

    
487
    TRACE("Sending request to client: "
488
          "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
489
          request->from, request->len, request->handle, request->type);
490

    
491
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
492
        LOG("writing to socket failed");
493
        errno = EINVAL;
494
        return -1;
495
    }
496
    return 0;
497
}
498

    
499
static int nbd_receive_request(int csock, struct nbd_request *request)
500
{
501
    uint8_t buf[4 + 4 + 8 + 8 + 4];
502
    uint32_t magic;
503

    
504
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
505
        LOG("read failed");
506
        errno = EINVAL;
507
        return -1;
508
    }
509

    
510
    /* Request
511
       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
512
       [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
513
       [ 8 .. 15]   handle
514
       [16 .. 23]   from
515
       [24 .. 27]   len
516
     */
517

    
518
    magic = be32_to_cpup((uint32_t*)buf);
519
    request->type  = be32_to_cpup((uint32_t*)(buf + 4));
520
    request->handle = be64_to_cpup((uint64_t*)(buf + 8));
521
    request->from  = be64_to_cpup((uint64_t*)(buf + 16));
522
    request->len   = be32_to_cpup((uint32_t*)(buf + 24));
523

    
524
    TRACE("Got request: "
525
          "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
526
          magic, request->type, request->from, request->len);
527

    
528
    if (magic != NBD_REQUEST_MAGIC) {
529
        LOG("invalid magic (got 0x%x)", magic);
530
        errno = EINVAL;
531
        return -1;
532
    }
533
    return 0;
534
}
535

    
536
int nbd_receive_reply(int csock, struct nbd_reply *reply)
537
{
538
    uint8_t buf[NBD_REPLY_SIZE];
539
    uint32_t magic;
540

    
541
    memset(buf, 0xAA, sizeof(buf));
542

    
543
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
544
        LOG("read failed");
545
        errno = EINVAL;
546
        return -1;
547
    }
548

    
549
    /* Reply
550
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
551
       [ 4 ..  7]    error   (0 == no error)
552
       [ 7 .. 15]    handle
553
     */
554

    
555
    magic = be32_to_cpup((uint32_t*)buf);
556
    reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
557
    reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
558

    
559
    TRACE("Got reply: "
560
          "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
561
          magic, reply->error, reply->handle);
562

    
563
    if (magic != NBD_REPLY_MAGIC) {
564
        LOG("invalid magic (got 0x%x)", magic);
565
        errno = EINVAL;
566
        return -1;
567
    }
568
    return 0;
569
}
570

    
571
static int nbd_send_reply(int csock, struct nbd_reply *reply)
572
{
573
    uint8_t buf[4 + 4 + 8];
574

    
575
    /* Reply
576
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
577
       [ 4 ..  7]    error   (0 == no error)
578
       [ 7 .. 15]    handle
579
     */
580
    cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
581
    cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
582
    cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
583

    
584
    TRACE("Sending response to client");
585

    
586
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
587
        LOG("writing to socket failed");
588
        errno = EINVAL;
589
        return -1;
590
    }
591
    return 0;
592
}
593

    
594
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
595
             off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size)
596
{
597
    struct nbd_request request;
598
    struct nbd_reply reply;
599
    int ret;
600

    
601
    TRACE("Reading request.");
602

    
603
    if (nbd_receive_request(csock, &request) == -1)
604
        return -1;
605

    
606
    if (request.len + NBD_REPLY_SIZE > data_size) {
607
        LOG("len (%u) is larger than max len (%u)",
608
            request.len + NBD_REPLY_SIZE, data_size);
609
        errno = EINVAL;
610
        return -1;
611
    }
612

    
613
    if ((request.from + request.len) < request.from) {
614
        LOG("integer overflow detected! "
615
            "you're probably being attacked");
616
        errno = EINVAL;
617
        return -1;
618
    }
619

    
620
    if ((request.from + request.len) > size) {
621
            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
622
            ", Offset: %" PRIu64 "\n",
623
                    request.from, request.len, (uint64_t)size, dev_offset);
624
        LOG("requested operation past EOF--bad client?");
625
        errno = EINVAL;
626
        return -1;
627
    }
628

    
629
    TRACE("Decoding type");
630

    
631
    reply.handle = request.handle;
632
    reply.error = 0;
633

    
634
    switch (request.type & NBD_CMD_MASK_COMMAND) {
635
    case NBD_CMD_READ:
636
        TRACE("Request type is READ");
637

    
638
        ret = bdrv_read(bs, (request.from + dev_offset) / 512,
639
                        data + NBD_REPLY_SIZE,
640
                        request.len / 512);
641
        if (ret < 0) {
642
            LOG("reading from file failed");
643
            reply.error = -ret;
644
            request.len = 0;
645
        }
646
        *offset += request.len;
647

    
648
        TRACE("Read %u byte(s)", request.len);
649

    
650
        /* Reply
651
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
652
           [ 4 ..  7]    error   (0 == no error)
653
           [ 7 .. 15]    handle
654
         */
655

    
656
        cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
657
        cpu_to_be32w((uint32_t*)(data + 4), reply.error);
658
        cpu_to_be64w((uint64_t*)(data + 8), reply.handle);
659

    
660
        TRACE("Sending data to client");
661

    
662
        if (write_sync(csock, data,
663
                   request.len + NBD_REPLY_SIZE) !=
664
                   request.len + NBD_REPLY_SIZE) {
665
            LOG("writing to socket failed");
666
            errno = EINVAL;
667
            return -1;
668
        }
669
        break;
670
    case NBD_CMD_WRITE:
671
        TRACE("Request type is WRITE");
672

    
673
        TRACE("Reading %u byte(s)", request.len);
674

    
675
        if (read_sync(csock, data, request.len) != request.len) {
676
            LOG("reading from socket failed");
677
            errno = EINVAL;
678
            return -1;
679
        }
680

    
681
        if (nbdflags & NBD_FLAG_READ_ONLY) {
682
            TRACE("Server is read-only, return error");
683
            reply.error = 1;
684
        } else {
685
            TRACE("Writing to device");
686

    
687
            ret = bdrv_write(bs, (request.from + dev_offset) / 512,
688
                             data, request.len / 512);
689
            if (ret < 0) {
690
                LOG("writing to file failed");
691
                reply.error = -ret;
692
                request.len = 0;
693
            }
694

    
695
            *offset += request.len;
696

    
697
            if (request.type & NBD_CMD_FLAG_FUA) {
698
                ret = bdrv_flush(bs);
699
                if (ret < 0) {
700
                    LOG("flush failed");
701
                    reply.error = -ret;
702
                }
703
            }
704
        }
705

    
706
        if (nbd_send_reply(csock, &reply) == -1)
707
            return -1;
708
        break;
709
    case NBD_CMD_DISC:
710
        TRACE("Request type is DISCONNECT");
711
        errno = 0;
712
        return 1;
713
    default:
714
        LOG("invalid request type (%u) received", request.type);
715
        errno = EINVAL;
716
        return -1;
717
    }
718

    
719
    TRACE("Request/Reply complete");
720

    
721
    return 0;
722
}