Statistics
| Branch: | Revision:

root / nbd.c @ 2f726488

History | View | Annotate | Download (11.6 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, write to the Free Software
17
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
\*/
19

    
20
#include "nbd.h"
21

    
22
#include <errno.h>
23
#include <string.h>
24
#include <sys/ioctl.h>
25
#include <ctype.h>
26
#include <inttypes.h>
27
#include <sys/socket.h>
28
#include <sys/un.h>
29
#include <netinet/in.h>
30
#include <netinet/tcp.h>
31
#include <arpa/inet.h>
32
#include <netdb.h>
33

    
34
extern int verbose;
35

    
36
#define LOG(msg, ...) do { \
37
    fprintf(stderr, "%s:%s():L%d: " msg "\n", \
38
            __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
39
} while(0)
40

    
41
#define TRACE(msg, ...) do { \
42
    if (verbose) LOG(msg, ## __VA_ARGS__); \
43
} while(0)
44

    
45
/* This is all part of the "official" NBD API */
46

    
47
#define NBD_REQUEST_MAGIC       0x25609513
48
#define NBD_REPLY_MAGIC         0x67446698
49

    
50
#define NBD_SET_SOCK            _IO(0xab, 0)
51
#define NBD_SET_BLKSIZE         _IO(0xab, 1)
52
#define NBD_SET_SIZE            _IO(0xab, 2)
53
#define NBD_DO_IT               _IO(0xab, 3)
54
#define NBD_CLEAR_SOCK          _IO(0xab, 4)
55
#define NBD_CLEAR_QUE           _IO(0xab, 5)
56
#define NBD_PRINT_DEBUG                _IO(0xab, 6)
57
#define NBD_SET_SIZE_BLOCKS        _IO(0xab, 7)
58
#define NBD_DISCONNECT          _IO(0xab, 8)
59

    
60
/* That's all folks */
61

    
62
#define read_sync(fd, buffer, size) wr_sync(fd, buffer, size, true)
63
#define write_sync(fd, buffer, size) wr_sync(fd, buffer, size, false)
64

    
65
static size_t wr_sync(int fd, void *buffer, size_t size, bool do_read)
66
{
67
    size_t offset = 0;
68

    
69
    while (offset < size) {
70
        ssize_t len;
71

    
72
        if (do_read) {
73
            len = read(fd, buffer + offset, size - offset);
74
        } else {
75
            len = write(fd, buffer + offset, size - offset);
76
        }
77

    
78
        /* recoverable error */
79
        if (len == -1 && errno == EAGAIN) {
80
            continue;
81
        }
82

    
83
        /* eof */
84
        if (len == 0) {
85
            break;
86
        }
87

    
88
        /* unrecoverable error */
89
        if (len == -1) {
90
            return 0;
91
        }
92

    
93
        offset += len;
94
    }
95

    
96
    return offset;
97
}
98

    
99
static int tcp_socket_outgoing(const char *address, uint16_t port)
100
{
101
    int s;
102
    struct in_addr in;
103
    struct sockaddr_in addr;
104
    int serrno;
105

    
106
    s = socket(PF_INET, SOCK_STREAM, 0);
107
    if (s == -1) {
108
        return -1;
109
    }
110

    
111
    if (inet_aton(address, &in) == 0) {
112
        struct hostent *ent;
113

    
114
        ent = gethostbyname(address);
115
        if (ent == NULL) {
116
            goto error;
117
        }
118

    
119
        memcpy(&in, ent->h_addr, sizeof(in));
120
    }
121

    
122
    addr.sin_family = AF_INET;
123
    addr.sin_port = htons(port);
124
    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
125

    
126
    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
127
        goto error;
128
    }
129

    
130
    return s;
131
error:
132
    serrno = errno;
133
    close(s);
134
    errno = serrno;
135
    return -1;
136
}
137

    
138
int tcp_socket_incoming(const char *address, uint16_t port)
139
{
140
    int s;
141
    struct in_addr in;
142
    struct sockaddr_in addr;
143
    int serrno;
144
    int opt;
145

    
146
    s = socket(PF_INET, SOCK_STREAM, 0);
147
    if (s == -1) {
148
        return -1;
149
    }
150

    
151
    if (inet_aton(address, &in) == 0) {
152
        struct hostent *ent;
153

    
154
        ent = gethostbyname(address);
155
        if (ent == NULL) {
156
            goto error;
157
        }
158

    
159
        memcpy(&in, ent->h_addr, sizeof(in));
160
    }
161

    
162
    addr.sin_family = AF_INET;
163
    addr.sin_port = htons(port);
164
    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
165

    
166
    opt = 1;
167
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
168
        goto error;
169
    }
170

    
171
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
172
        goto error;
173
    }
174

    
175
    if (listen(s, 128) == -1) {
176
        goto error;
177
    }
178

    
179
    return s;
180
error:
181
    serrno = errno;
182
    close(s);
183
    errno = serrno;
184
    return -1;
185
}
186

    
187
int unix_socket_incoming(const char *path)
188
{
189
    int s;
190
    struct sockaddr_un addr;
191
    int serrno;
192

    
193
    s = socket(PF_UNIX, SOCK_STREAM, 0);
194
    if (s == -1) {
195
        return -1;
196
    }
197

    
198
    memset(&addr, 0, sizeof(addr));
199
    addr.sun_family = AF_UNIX;
200
    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
201

    
202
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
203
        goto error;
204
    }
205

    
206
    if (listen(s, 128) == -1) {
207
        goto error;
208
    }
209

    
210
    return s;
211
error:
212
    serrno = errno;
213
    close(s);
214
    errno = serrno;
215
    return -1;
216
}
217

    
218
int unix_socket_outgoing(const char *path)
219
{
220
    int s;
221
    struct sockaddr_un addr;
222
    int serrno;
223

    
224
    s = socket(PF_UNIX, SOCK_STREAM, 0);
225
    if (s == -1) {
226
        return -1;
227
    }
228

    
229
    memset(&addr, 0, sizeof(addr));
230
    addr.sun_family = AF_UNIX;
231
    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
232

    
233
    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
234
        goto error;
235
    }
236

    
237
    return s;
238
error:
239
    serrno = errno;
240
    close(s);
241
    errno = serrno;
242
    return -1;
243
}
244

    
245

    
246
/* Basic flow
247

248
   Server         Client
249

250
   Negotiate
251
                  Request
252
   Response
253
                  Request
254
   Response
255
                  ...
256
   ...
257
                  Request (type == 2)
258
*/
259

    
260
int nbd_negotiate(BlockDriverState *bs, int csock, off_t size)
261
{
262
        char buf[8 + 8 + 8 + 128];
263

    
264
        /* Negotiate
265
           [ 0 ..   7]   passwd   ("NBDMAGIC")
266
           [ 8 ..  15]   magic    (0x00420281861253)
267
           [16 ..  23]   size
268
           [24 .. 151]   reserved (0)
269
         */
270

    
271
        TRACE("Beginning negotiation.");
272
        memcpy(buf, "NBDMAGIC", 8);
273
        cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
274
        cpu_to_be64w((uint64_t*)(buf + 16), size);
275
        memset(buf + 24, 0, 128);
276

    
277
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
278
                LOG("write failed");
279
                errno = EINVAL;
280
                return -1;
281
        }
282

    
283
        TRACE("Negotation succeeded.");
284

    
285
        return 0;
286
}
287

    
288
int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize)
289
{
290
        char buf[8 + 8 + 8 + 128];
291
        uint64_t magic;
292

    
293
        TRACE("Receiving negotation.");
294

    
295
        if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
296
                LOG("read failed");
297
                errno = EINVAL;
298
                return -1;
299
        }
300

    
301
        magic = be64_to_cpup((uint64_t*)(buf + 8));
302
        *size = be64_to_cpup((uint64_t*)(buf + 16));
303
        *blocksize = 1024;
304

    
305
        TRACE("Magic is %c%c%c%c%c%c%c%c",
306
              isprint(buf[0]) ? buf[0] : '.',
307
              isprint(buf[1]) ? buf[1] : '.',
308
              isprint(buf[2]) ? buf[2] : '.',
309
              isprint(buf[3]) ? buf[3] : '.',
310
              isprint(buf[4]) ? buf[4] : '.',
311
              isprint(buf[5]) ? buf[5] : '.',
312
              isprint(buf[6]) ? buf[6] : '.',
313
              isprint(buf[7]) ? buf[7] : '.');
314
        TRACE("Magic is 0x%" PRIx64, magic);
315
        TRACE("Size is %" PRIu64, *size);
316

    
317
        if (memcmp(buf, "NBDMAGIC", 8) != 0) {
318
                LOG("Invalid magic received");
319
                errno = EINVAL;
320
                return -1;
321
        }
322

    
323
        TRACE("Checking magic");
324

    
325
        if (magic != 0x00420281861253LL) {
326
                LOG("Bad magic received");
327
                errno = EINVAL;
328
                return -1;
329
        }
330
        return 0;
331
}
332

    
333
int nbd_init(int fd, int csock, off_t size, size_t blocksize)
334
{
335
        TRACE("Setting block size to %lu", (unsigned long)blocksize);
336

    
337
        if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
338
                int serrno = errno;
339
                LOG("Failed setting NBD block size");
340
                errno = serrno;
341
                return -1;
342
        }
343

    
344
        TRACE("Setting size to %llu block(s)",
345
              (unsigned long long)(size / blocksize));
346

    
347
        if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
348
                int serrno = errno;
349
                LOG("Failed setting size (in blocks)");
350
                errno = serrno;
351
                return -1;
352
        }
353

    
354
        TRACE("Clearing NBD socket");
355

    
356
        if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
357
                int serrno = errno;
358
                LOG("Failed clearing NBD socket");
359
                errno = serrno;
360
                return -1;
361
        }
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("Negotiation ended");
373

    
374
        return 0;
375
}
376

    
377
int nbd_disconnect(int fd)
378
{
379
        ioctl(fd, NBD_CLEAR_QUE);
380
        ioctl(fd, NBD_DISCONNECT);
381
        ioctl(fd, NBD_CLEAR_SOCK);
382
        return 0;
383
}
384

    
385
int nbd_client(int fd, int csock)
386
{
387
        int ret;
388
        int serrno;
389

    
390
        TRACE("Doing NBD loop");
391

    
392
        ret = ioctl(fd, NBD_DO_IT);
393
        serrno = errno;
394

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

    
397
        TRACE("Clearing NBD queue");
398
        ioctl(fd, NBD_CLEAR_QUE);
399

    
400
        TRACE("Clearing NBD socket");
401
        ioctl(fd, NBD_CLEAR_SOCK);
402

    
403
        errno = serrno;
404
        return ret;
405
}
406

    
407
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
408
             off_t *offset, bool readonly, uint8_t *data, int data_size)
409
{
410
        uint8_t buf[4 + 4 + 8 + 8 + 4];
411
        uint32_t magic;
412
        uint32_t type;
413
        uint64_t from;
414
        uint32_t len;
415

    
416
        TRACE("Reading request.");
417

    
418
        if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
419
                LOG("read failed");
420
                errno = EINVAL;
421
                return -1;
422
        }
423

    
424
        /* Request
425
          [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
426
          [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
427
          [ 8 .. 15]   handle
428
          [16 .. 23]   from
429
          [24 .. 27]   len
430
         */
431

    
432
        magic = be32_to_cpup((uint32_t*)buf);
433
        type  = be32_to_cpup((uint32_t*)(buf + 4));
434
        from  = be64_to_cpup((uint64_t*)(buf + 16));
435
        len   = be32_to_cpup((uint32_t*)(buf + 24));
436

    
437
        TRACE("Got request: "
438
              "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
439
              magic, type, from, len);
440

    
441

    
442
        if (magic != NBD_REQUEST_MAGIC) {
443
                LOG("invalid magic (got 0x%x)", magic);
444
                errno = EINVAL;
445
                return -1;
446
        }
447

    
448
        if (len > data_size) {
449
                LOG("len (%u) is larger than max len (%u)",
450
                    len, data_size);
451
                errno = EINVAL;
452
                return -1;
453
        }
454

    
455
        if ((from + len) < from) {
456
                LOG("integer overflow detected! "
457
                    "you're probably being attacked");
458
                errno = EINVAL;
459
                return -1;
460
        }
461

    
462
        if ((from + len) > size) {
463
                LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
464
                    ", Offset: %" PRIu64 "\n",
465
                     from, len, size, dev_offset);
466
                LOG("requested operation past EOF--bad client?");
467
                errno = EINVAL;
468
                return -1;
469
        }
470

    
471
        /* Reply
472
         [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
473
         [ 4 ..  7]    error   (0 == no error)
474
         [ 7 .. 15]    handle
475
         */
476
        cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
477
        cpu_to_be32w((uint32_t*)(buf + 4), 0);
478

    
479
        TRACE("Decoding type");
480

    
481
        switch (type) {
482
        case 0:
483
                TRACE("Request type is READ");
484

    
485
                if (bdrv_read(bs, (from + dev_offset) / 512, data, len / 512) == -1) {
486
                        LOG("reading from file failed");
487
                        errno = EINVAL;
488
                        return -1;
489
                }
490
                *offset += len;
491

    
492
                TRACE("Read %u byte(s)", len);
493

    
494
                TRACE("Sending OK response");
495

    
496
                if (write_sync(csock, buf, 16) != 16) {
497
                        LOG("writing to socket failed");
498
                        errno = EINVAL;
499
                        return -1;
500
                }
501

    
502
                TRACE("Sending data to client");
503

    
504
                if (write_sync(csock, data, len) != len) {
505
                        LOG("writing to socket failed");
506
                        errno = EINVAL;
507
                        return -1;
508
                }
509
                break;
510
        case 1:
511
                TRACE("Request type is WRITE");
512

    
513
                TRACE("Reading %u byte(s)", len);
514

    
515
                if (read_sync(csock, data, len) != len) {
516
                        LOG("reading from socket failed");
517
                        errno = EINVAL;
518
                        return -1;
519
                }
520

    
521
                if (readonly) {
522
                        TRACE("Server is read-only, return error");
523

    
524
                        cpu_to_be32w((uint32_t*)(buf + 4), 1);
525
                } else {
526
                        TRACE("Writing to device");
527

    
528
                        if (bdrv_write(bs, (from + dev_offset) / 512, data, len / 512) == -1) {
529
                                LOG("writing to file failed");
530
                                errno = EINVAL;
531
                                return -1;
532
                        }
533

    
534
                        *offset += len;
535
                }
536

    
537
                TRACE("Sending response to client");
538

    
539
                if (write_sync(csock, buf, 16) != 16) {
540
                        LOG("writing to socket failed");
541
                        errno = EINVAL;
542
                        return -1;
543
                }
544
                break;
545
        case 2:
546
                TRACE("Request type is DISCONNECT");
547
                errno = 0;
548
                return 1;
549
        default:
550
                LOG("invalid request type (%u) received", type);
551
                errno = EINVAL;
552
                return -1;
553
        }
554

    
555
        TRACE("Request/Reply complete");
556

    
557
        return 0;
558
}