~ubuntu-branches/debian/jessie/qemu/jessie

« back to all changes in this revision

Viewing changes to nbd.c

  • Committer: Package Import Robot
  • Author(s): Vagrant Cascadian
  • Date: 2011-10-03 12:29:18 UTC
  • mfrom: (1.2.13) (10.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20111003122918-zc4kv6epchrbgdta
Tags: 0.15.0+dfsg-1
* New upstream version.
* Install new qemu-system, qemu-user and qemu-user-static variants: 
  lm32, microblazeel, s390x, unicore32
* Patch from upstream to set QEMU_INCLUDES before QEMU_CFLAGS.
* Update debian/watch to check http://qemu.org/download.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 
50
50
/* This is all part of the "official" NBD API */
51
51
 
52
 
#define NBD_REPLY_SIZE          (4 + 4 + 8)
 
52
#define NBD_REPLY_SIZE          (4 + 4 + 8)
53
53
#define NBD_REQUEST_MAGIC       0x25609513
54
54
#define NBD_REPLY_MAGIC         0x67446698
55
55
 
59
59
#define NBD_DO_IT               _IO(0xab, 3)
60
60
#define NBD_CLEAR_SOCK          _IO(0xab, 4)
61
61
#define NBD_CLEAR_QUE           _IO(0xab, 5)
62
 
#define NBD_PRINT_DEBUG         _IO(0xab, 6)
63
 
#define NBD_SET_SIZE_BLOCKS     _IO(0xab, 7)
 
62
#define NBD_PRINT_DEBUG         _IO(0xab, 6)
 
63
#define NBD_SET_SIZE_BLOCKS     _IO(0xab, 7)
64
64
#define NBD_DISCONNECT          _IO(0xab, 8)
65
65
 
66
 
#define NBD_OPT_EXPORT_NAME     (1 << 0)
 
66
#define NBD_OPT_EXPORT_NAME     (1 << 0)
67
67
 
68
68
/* That's all folks */
69
69
 
78
78
        ssize_t len;
79
79
 
80
80
        if (do_read) {
81
 
            len = recv(fd, buffer + offset, size - offset, 0);
 
81
            len = qemu_recv(fd, buffer + offset, size - offset, 0);
82
82
        } else {
83
83
            len = send(fd, buffer + offset, size - offset, 0);
84
84
        }
107
107
    return offset;
108
108
}
109
109
 
 
110
static void combine_addr(char *buf, size_t len, const char* address,
 
111
                         uint16_t port)
 
112
{
 
113
    /* If the address-part contains a colon, it's an IPv6 IP so needs [] */
 
114
    if (strstr(address, ":")) {
 
115
        snprintf(buf, len, "[%s]:%u", address, port);
 
116
    } else {
 
117
        snprintf(buf, len, "%s:%u", address, port);
 
118
    }
 
119
}
 
120
 
110
121
int tcp_socket_outgoing(const char *address, uint16_t port)
111
122
{
112
 
    int s;
113
 
    struct in_addr in;
114
 
    struct sockaddr_in addr;
115
 
 
116
 
    s = socket(PF_INET, SOCK_STREAM, 0);
117
 
    if (s == -1) {
118
 
        return -1;
119
 
    }
120
 
 
121
 
    if (inet_aton(address, &in) == 0) {
122
 
        struct hostent *ent;
123
 
 
124
 
        ent = gethostbyname(address);
125
 
        if (ent == NULL) {
126
 
            goto error;
127
 
        }
128
 
 
129
 
        memcpy(&in, ent->h_addr, sizeof(in));
130
 
    }
131
 
 
132
 
    addr.sin_family = AF_INET;
133
 
    addr.sin_port = htons(port);
134
 
    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
135
 
 
136
 
    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
137
 
        goto error;
138
 
    }
139
 
 
140
 
    return s;
141
 
error:
142
 
    closesocket(s);
143
 
    return -1;
 
123
    char address_and_port[128];
 
124
    combine_addr(address_and_port, 128, address, port);
 
125
    return tcp_socket_outgoing_spec(address_and_port);
 
126
}
 
127
 
 
128
int tcp_socket_outgoing_spec(const char *address_and_port)
 
129
{
 
130
    return inet_connect(address_and_port, SOCK_STREAM);
144
131
}
145
132
 
146
133
int tcp_socket_incoming(const char *address, uint16_t port)
147
134
{
148
 
    int s;
149
 
    struct in_addr in;
150
 
    struct sockaddr_in addr;
151
 
    int opt;
152
 
 
153
 
    s = socket(PF_INET, SOCK_STREAM, 0);
154
 
    if (s == -1) {
155
 
        return -1;
156
 
    }
157
 
 
158
 
    if (inet_aton(address, &in) == 0) {
159
 
        struct hostent *ent;
160
 
 
161
 
        ent = gethostbyname(address);
162
 
        if (ent == NULL) {
163
 
            goto error;
164
 
        }
165
 
 
166
 
        memcpy(&in, ent->h_addr, sizeof(in));
167
 
    }
168
 
 
169
 
    addr.sin_family = AF_INET;
170
 
    addr.sin_port = htons(port);
171
 
    memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
172
 
 
173
 
    opt = 1;
174
 
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
175
 
                   (const void *) &opt, sizeof(opt)) == -1) {
176
 
        goto error;
177
 
    }
178
 
 
179
 
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
180
 
        goto error;
181
 
    }
182
 
 
183
 
    if (listen(s, 128) == -1) {
184
 
        goto error;
185
 
    }
186
 
 
187
 
    return s;
188
 
error:
189
 
    closesocket(s);
190
 
    return -1;
191
 
}
192
 
 
193
 
#ifndef _WIN32
194
 
int unix_socket_incoming(const char *path)
195
 
{
196
 
    int s;
197
 
    struct sockaddr_un addr;
198
 
 
199
 
    s = socket(PF_UNIX, SOCK_STREAM, 0);
200
 
    if (s == -1) {
201
 
        return -1;
202
 
    }
203
 
 
204
 
    memset(&addr, 0, sizeof(addr));
205
 
    addr.sun_family = AF_UNIX;
206
 
    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
207
 
 
208
 
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
209
 
        goto error;
210
 
    }
211
 
 
212
 
    if (listen(s, 128) == -1) {
213
 
        goto error;
214
 
    }
215
 
 
216
 
    return s;
217
 
error:
218
 
    closesocket(s);
219
 
    return -1;
220
 
}
221
 
 
222
 
int unix_socket_outgoing(const char *path)
223
 
{
224
 
    int s;
225
 
    struct sockaddr_un addr;
226
 
 
227
 
    s = socket(PF_UNIX, SOCK_STREAM, 0);
228
 
    if (s == -1) {
229
 
        return -1;
230
 
    }
231
 
 
232
 
    memset(&addr, 0, sizeof(addr));
233
 
    addr.sun_family = AF_UNIX;
234
 
    pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
235
 
 
236
 
    if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
237
 
        goto error;
238
 
    }
239
 
 
240
 
    return s;
241
 
error:
242
 
    closesocket(s);
243
 
    return -1;
244
 
}
245
 
#else
246
 
int unix_socket_incoming(const char *path)
247
 
{
248
 
    errno = ENOTSUP;
249
 
    return -1;
250
 
}
251
 
 
252
 
int unix_socket_outgoing(const char *path)
253
 
{
254
 
    errno = ENOTSUP;
255
 
    return -1;
256
 
}
257
 
#endif
258
 
 
 
135
    char address_and_port[128];
 
136
    combine_addr(address_and_port, 128, address, port);
 
137
    return tcp_socket_incoming_spec(address_and_port);
 
138
}
 
139
 
 
140
int tcp_socket_incoming_spec(const char *address_and_port)
 
141
{
 
142
    char *ostr  = NULL;
 
143
    int olen = 0;
 
144
    return inet_listen(address_and_port, ostr, olen, SOCK_STREAM, 0);
 
145
}
 
146
 
 
147
int unix_socket_incoming(const char *path)
 
148
{
 
149
    char *ostr = NULL;
 
150
    int olen = 0;
 
151
 
 
152
    return unix_listen(path, ostr, olen);
 
153
}
 
154
 
 
155
int unix_socket_outgoing(const char *path)
 
156
{
 
157
    return unix_connect(path);
 
158
}
259
159
 
260
160
/* Basic flow
261
161
 
273
173
 
274
174
int nbd_negotiate(int csock, off_t size)
275
175
{
276
 
        char buf[8 + 8 + 8 + 128];
277
 
 
278
 
        /* Negotiate
279
 
           [ 0 ..   7]   passwd   ("NBDMAGIC")
280
 
           [ 8 ..  15]   magic    (0x00420281861253)
281
 
           [16 ..  23]   size
282
 
           [24 .. 151]   reserved (0)
283
 
         */
284
 
 
285
 
        TRACE("Beginning negotiation.");
286
 
        memcpy(buf, "NBDMAGIC", 8);
287
 
        cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
288
 
        cpu_to_be64w((uint64_t*)(buf + 16), size);
289
 
        memset(buf + 24, 0, 128);
290
 
 
291
 
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
292
 
                LOG("write failed");
293
 
                errno = EINVAL;
294
 
                return -1;
295
 
        }
296
 
 
297
 
        TRACE("Negotation succeeded.");
298
 
 
299
 
        return 0;
 
176
    char buf[8 + 8 + 8 + 128];
 
177
 
 
178
    /* Negotiate
 
179
        [ 0 ..   7]   passwd   ("NBDMAGIC")
 
180
        [ 8 ..  15]   magic    (0x00420281861253)
 
181
        [16 ..  23]   size
 
182
        [24 .. 151]   reserved (0)
 
183
     */
 
184
 
 
185
    TRACE("Beginning negotiation.");
 
186
    memcpy(buf, "NBDMAGIC", 8);
 
187
    cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
 
188
    cpu_to_be64w((uint64_t*)(buf + 16), size);
 
189
    memset(buf + 24, 0, 128);
 
190
 
 
191
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
 
192
        LOG("write failed");
 
193
        errno = EINVAL;
 
194
        return -1;
 
195
    }
 
196
 
 
197
    TRACE("Negotation succeeded.");
 
198
 
 
199
    return 0;
300
200
}
301
201
 
302
202
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
303
203
                          off_t *size, size_t *blocksize)
304
204
{
305
 
        char buf[256];
306
 
        uint64_t magic, s;
307
 
        uint16_t tmp;
308
 
 
309
 
        TRACE("Receiving negotation.");
310
 
 
311
 
        if (read_sync(csock, buf, 8) != 8) {
312
 
                LOG("read failed");
313
 
                errno = EINVAL;
314
 
                return -1;
315
 
        }
316
 
 
317
 
        buf[8] = '\0';
318
 
        if (strlen(buf) == 0) {
319
 
                LOG("server connection closed");
320
 
                errno = EINVAL;
321
 
                return -1;
322
 
        }
323
 
 
324
 
        TRACE("Magic is %c%c%c%c%c%c%c%c",
325
 
              qemu_isprint(buf[0]) ? buf[0] : '.',
326
 
              qemu_isprint(buf[1]) ? buf[1] : '.',
327
 
              qemu_isprint(buf[2]) ? buf[2] : '.',
328
 
              qemu_isprint(buf[3]) ? buf[3] : '.',
329
 
              qemu_isprint(buf[4]) ? buf[4] : '.',
330
 
              qemu_isprint(buf[5]) ? buf[5] : '.',
331
 
              qemu_isprint(buf[6]) ? buf[6] : '.',
332
 
              qemu_isprint(buf[7]) ? buf[7] : '.');
333
 
 
334
 
        if (memcmp(buf, "NBDMAGIC", 8) != 0) {
335
 
                LOG("Invalid magic received");
336
 
                errno = EINVAL;
337
 
                return -1;
338
 
        }
339
 
 
340
 
        if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
341
 
                LOG("read failed");
342
 
                errno = EINVAL;
343
 
                return -1;
344
 
        }
345
 
        magic = be64_to_cpu(magic);
346
 
        TRACE("Magic is 0x%" PRIx64, magic);
347
 
 
348
 
        if (name) {
349
 
                uint32_t reserved = 0;
350
 
                uint32_t opt;
351
 
                uint32_t namesize;
352
 
 
353
 
                TRACE("Checking magic (opts_magic)");
354
 
                if (magic != 0x49484156454F5054LL) {
355
 
                        LOG("Bad magic received");
356
 
                        errno = EINVAL;
357
 
                        return -1;
358
 
                }
359
 
                if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
360
 
                        LOG("flags read failed");
361
 
                        errno = EINVAL;
362
 
                        return -1;
363
 
                }
364
 
                *flags = be16_to_cpu(tmp) << 16;
365
 
                /* reserved for future use */
366
 
                if (write_sync(csock, &reserved, sizeof(reserved)) !=
367
 
                    sizeof(reserved)) {
368
 
                        LOG("write failed (reserved)");
369
 
                        errno = EINVAL;
370
 
                        return -1;
371
 
                }
372
 
                /* write the export name */
373
 
                magic = cpu_to_be64(magic);
374
 
                if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
375
 
                        LOG("write failed (magic)");
376
 
                        errno = EINVAL;
377
 
                        return -1;
378
 
                }
379
 
                opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
380
 
                if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
381
 
                        LOG("write failed (opt)");
382
 
                        errno = EINVAL;
383
 
                        return -1;
384
 
                }
385
 
                namesize = cpu_to_be32(strlen(name));
386
 
                if (write_sync(csock, &namesize, sizeof(namesize)) !=
387
 
                    sizeof(namesize)) {
388
 
                        LOG("write failed (namesize)");
389
 
                        errno = EINVAL;
390
 
                        return -1;
391
 
                }
392
 
                if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
393
 
                        LOG("write failed (name)");
394
 
                        errno = EINVAL;
395
 
                        return -1;
396
 
                }
397
 
        } else {
398
 
                TRACE("Checking magic (cli_magic)");
399
 
 
400
 
                if (magic != 0x00420281861253LL) {
401
 
                        LOG("Bad magic received");
402
 
                        errno = EINVAL;
403
 
                        return -1;
404
 
                }
405
 
        }
406
 
 
407
 
        if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
408
 
                LOG("read failed");
409
 
                errno = EINVAL;
410
 
                return -1;
411
 
        }
412
 
        *size = be64_to_cpu(s);
413
 
        *blocksize = 1024;
414
 
        TRACE("Size is %" PRIu64, *size);
415
 
 
416
 
        if (!name) {
417
 
                if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
418
 
                        LOG("read failed (flags)");
419
 
                        errno = EINVAL;
420
 
                        return -1;
421
 
                }
422
 
                *flags = be32_to_cpup(flags);
423
 
        } else {
424
 
                if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
425
 
                        LOG("read failed (tmp)");
426
 
                        errno = EINVAL;
427
 
                        return -1;
428
 
                }
429
 
                *flags |= be32_to_cpu(tmp);
430
 
        }
431
 
        if (read_sync(csock, &buf, 124) != 124) {
432
 
                LOG("read failed (buf)");
433
 
                errno = EINVAL;
434
 
                return -1;
435
 
        }
 
205
    char buf[256];
 
206
    uint64_t magic, s;
 
207
    uint16_t tmp;
 
208
 
 
209
    TRACE("Receiving negotation.");
 
210
 
 
211
    if (read_sync(csock, buf, 8) != 8) {
 
212
        LOG("read failed");
 
213
        errno = EINVAL;
 
214
        return -1;
 
215
    }
 
216
 
 
217
    buf[8] = '\0';
 
218
    if (strlen(buf) == 0) {
 
219
        LOG("server connection closed");
 
220
        errno = EINVAL;
 
221
        return -1;
 
222
    }
 
223
 
 
224
    TRACE("Magic is %c%c%c%c%c%c%c%c",
 
225
          qemu_isprint(buf[0]) ? buf[0] : '.',
 
226
          qemu_isprint(buf[1]) ? buf[1] : '.',
 
227
          qemu_isprint(buf[2]) ? buf[2] : '.',
 
228
          qemu_isprint(buf[3]) ? buf[3] : '.',
 
229
          qemu_isprint(buf[4]) ? buf[4] : '.',
 
230
          qemu_isprint(buf[5]) ? buf[5] : '.',
 
231
          qemu_isprint(buf[6]) ? buf[6] : '.',
 
232
          qemu_isprint(buf[7]) ? buf[7] : '.');
 
233
 
 
234
    if (memcmp(buf, "NBDMAGIC", 8) != 0) {
 
235
        LOG("Invalid magic received");
 
236
        errno = EINVAL;
 
237
        return -1;
 
238
    }
 
239
 
 
240
    if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
 
241
        LOG("read failed");
 
242
        errno = EINVAL;
 
243
        return -1;
 
244
    }
 
245
    magic = be64_to_cpu(magic);
 
246
    TRACE("Magic is 0x%" PRIx64, magic);
 
247
 
 
248
    if (name) {
 
249
        uint32_t reserved = 0;
 
250
        uint32_t opt;
 
251
        uint32_t namesize;
 
252
 
 
253
        TRACE("Checking magic (opts_magic)");
 
254
        if (magic != 0x49484156454F5054LL) {
 
255
            LOG("Bad magic received");
 
256
            errno = EINVAL;
 
257
            return -1;
 
258
        }
 
259
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
 
260
            LOG("flags read failed");
 
261
            errno = EINVAL;
 
262
            return -1;
 
263
        }
 
264
        *flags = be16_to_cpu(tmp) << 16;
 
265
        /* reserved for future use */
 
266
        if (write_sync(csock, &reserved, sizeof(reserved)) !=
 
267
            sizeof(reserved)) {
 
268
            LOG("write failed (reserved)");
 
269
            errno = EINVAL;
 
270
            return -1;
 
271
        }
 
272
        /* write the export name */
 
273
        magic = cpu_to_be64(magic);
 
274
        if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) {
 
275
            LOG("write failed (magic)");
 
276
            errno = EINVAL;
 
277
            return -1;
 
278
        }
 
279
        opt = cpu_to_be32(NBD_OPT_EXPORT_NAME);
 
280
        if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) {
 
281
            LOG("write failed (opt)");
 
282
            errno = EINVAL;
 
283
            return -1;
 
284
        }
 
285
        namesize = cpu_to_be32(strlen(name));
 
286
        if (write_sync(csock, &namesize, sizeof(namesize)) !=
 
287
            sizeof(namesize)) {
 
288
            LOG("write failed (namesize)");
 
289
            errno = EINVAL;
 
290
            return -1;
 
291
        }
 
292
        if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) {
 
293
            LOG("write failed (name)");
 
294
            errno = EINVAL;
 
295
            return -1;
 
296
        }
 
297
    } else {
 
298
        TRACE("Checking magic (cli_magic)");
 
299
 
 
300
        if (magic != 0x00420281861253LL) {
 
301
            LOG("Bad magic received");
 
302
            errno = EINVAL;
 
303
            return -1;
 
304
        }
 
305
    }
 
306
 
 
307
    if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) {
 
308
        LOG("read failed");
 
309
        errno = EINVAL;
 
310
        return -1;
 
311
    }
 
312
    *size = be64_to_cpu(s);
 
313
    *blocksize = 1024;
 
314
    TRACE("Size is %" PRIu64, *size);
 
315
 
 
316
    if (!name) {
 
317
        if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) {
 
318
            LOG("read failed (flags)");
 
319
            errno = EINVAL;
 
320
            return -1;
 
321
        }
 
322
        *flags = be32_to_cpup(flags);
 
323
    } else {
 
324
        if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) {
 
325
            LOG("read failed (tmp)");
 
326
            errno = EINVAL;
 
327
            return -1;
 
328
        }
 
329
        *flags |= be32_to_cpu(tmp);
 
330
    }
 
331
    if (read_sync(csock, &buf, 124) != 124) {
 
332
        LOG("read failed (buf)");
 
333
        errno = EINVAL;
 
334
        return -1;
 
335
    }
436
336
        return 0;
437
337
}
438
338
 
439
339
#ifndef _WIN32
440
340
int nbd_init(int fd, int csock, off_t size, size_t blocksize)
441
341
{
442
 
        TRACE("Setting block size to %lu", (unsigned long)blocksize);
 
342
    TRACE("Setting block size to %lu", (unsigned long)blocksize);
443
343
 
444
 
        if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
445
 
                int serrno = errno;
446
 
                LOG("Failed setting NBD block size");
447
 
                errno = serrno;
448
 
                return -1;
449
 
        }
 
344
    if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
 
345
        int serrno = errno;
 
346
        LOG("Failed setting NBD block size");
 
347
        errno = serrno;
 
348
        return -1;
 
349
    }
450
350
 
451
351
        TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
452
352
 
453
 
        if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
454
 
                int serrno = errno;
455
 
                LOG("Failed setting size (in blocks)");
456
 
                errno = serrno;
457
 
                return -1;
458
 
        }
459
 
 
460
 
        TRACE("Clearing NBD socket");
461
 
 
462
 
        if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
463
 
                int serrno = errno;
464
 
                LOG("Failed clearing NBD socket");
465
 
                errno = serrno;
466
 
                return -1;
467
 
        }
468
 
 
469
 
        TRACE("Setting NBD socket");
470
 
 
471
 
        if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
472
 
                int serrno = errno;
473
 
                LOG("Failed to set NBD socket");
474
 
                errno = serrno;
475
 
                return -1;
476
 
        }
477
 
 
478
 
        TRACE("Negotiation ended");
479
 
 
480
 
        return 0;
 
353
    if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
 
354
        int serrno = errno;
 
355
        LOG("Failed setting size (in blocks)");
 
356
        errno = serrno;
 
357
        return -1;
 
358
    }
 
359
 
 
360
    TRACE("Clearing NBD socket");
 
361
 
 
362
    if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
 
363
        int serrno = errno;
 
364
        LOG("Failed clearing NBD socket");
 
365
        errno = serrno;
 
366
        return -1;
 
367
    }
 
368
 
 
369
    TRACE("Setting NBD socket");
 
370
 
 
371
    if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
 
372
        int serrno = errno;
 
373
        LOG("Failed to set NBD socket");
 
374
        errno = serrno;
 
375
        return -1;
 
376
    }
 
377
 
 
378
    TRACE("Negotiation ended");
 
379
 
 
380
    return 0;
481
381
}
482
382
 
483
383
int nbd_disconnect(int fd)
484
384
{
485
 
        ioctl(fd, NBD_CLEAR_QUE);
486
 
        ioctl(fd, NBD_DISCONNECT);
487
 
        ioctl(fd, NBD_CLEAR_SOCK);
488
 
        return 0;
 
385
    ioctl(fd, NBD_CLEAR_QUE);
 
386
    ioctl(fd, NBD_DISCONNECT);
 
387
    ioctl(fd, NBD_CLEAR_SOCK);
 
388
    return 0;
489
389
}
490
390
 
491
391
int nbd_client(int fd)
492
392
{
493
 
        int ret;
494
 
        int serrno;
495
 
 
496
 
        TRACE("Doing NBD loop");
497
 
 
498
 
        ret = ioctl(fd, NBD_DO_IT);
499
 
        serrno = errno;
500
 
 
501
 
        TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
502
 
 
503
 
        TRACE("Clearing NBD queue");
504
 
        ioctl(fd, NBD_CLEAR_QUE);
505
 
 
506
 
        TRACE("Clearing NBD socket");
507
 
        ioctl(fd, NBD_CLEAR_SOCK);
508
 
 
509
 
        errno = serrno;
510
 
        return ret;
 
393
    int ret;
 
394
    int serrno;
 
395
 
 
396
    TRACE("Doing NBD loop");
 
397
 
 
398
    ret = ioctl(fd, NBD_DO_IT);
 
399
    serrno = errno;
 
400
 
 
401
    TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
 
402
 
 
403
    TRACE("Clearing NBD queue");
 
404
    ioctl(fd, NBD_CLEAR_QUE);
 
405
 
 
406
    TRACE("Clearing NBD socket");
 
407
    ioctl(fd, NBD_CLEAR_SOCK);
 
408
 
 
409
    errno = serrno;
 
410
    return ret;
511
411
}
512
412
#else
513
413
int nbd_init(int fd, int csock, off_t size, size_t blocksize)
531
431
 
532
432
int nbd_send_request(int csock, struct nbd_request *request)
533
433
{
534
 
        uint8_t buf[4 + 4 + 8 + 8 + 4];
535
 
 
536
 
        cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
537
 
        cpu_to_be32w((uint32_t*)(buf + 4), request->type);
538
 
        cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
539
 
        cpu_to_be64w((uint64_t*)(buf + 16), request->from);
540
 
        cpu_to_be32w((uint32_t*)(buf + 24), request->len);
541
 
 
542
 
        TRACE("Sending request to client");
543
 
 
544
 
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
545
 
                LOG("writing to socket failed");
546
 
                errno = EINVAL;
547
 
                return -1;
548
 
        }
549
 
        return 0;
 
434
    uint8_t buf[4 + 4 + 8 + 8 + 4];
 
435
 
 
436
    cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
 
437
    cpu_to_be32w((uint32_t*)(buf + 4), request->type);
 
438
    cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
 
439
    cpu_to_be64w((uint64_t*)(buf + 16), request->from);
 
440
    cpu_to_be32w((uint32_t*)(buf + 24), request->len);
 
441
 
 
442
    TRACE("Sending request to client: "
 
443
          "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
 
444
          request->from, request->len, request->handle, request->type);
 
445
 
 
446
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
 
447
        LOG("writing to socket failed");
 
448
        errno = EINVAL;
 
449
        return -1;
 
450
    }
 
451
    return 0;
550
452
}
551
453
 
552
 
 
553
454
static int nbd_receive_request(int csock, struct nbd_request *request)
554
455
{
555
 
        uint8_t buf[4 + 4 + 8 + 8 + 4];
556
 
        uint32_t magic;
557
 
 
558
 
        if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
559
 
                LOG("read failed");
560
 
                errno = EINVAL;
561
 
                return -1;
562
 
        }
563
 
 
564
 
        /* Request
565
 
           [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
566
 
           [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
567
 
           [ 8 .. 15]   handle
568
 
           [16 .. 23]   from
569
 
           [24 .. 27]   len
570
 
         */
571
 
 
572
 
        magic = be32_to_cpup((uint32_t*)buf);
573
 
        request->type  = be32_to_cpup((uint32_t*)(buf + 4));
574
 
        request->handle = be64_to_cpup((uint64_t*)(buf + 8));
575
 
        request->from  = be64_to_cpup((uint64_t*)(buf + 16));
576
 
        request->len   = be32_to_cpup((uint32_t*)(buf + 24));
577
 
 
578
 
        TRACE("Got request: "
579
 
              "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
580
 
              magic, request->type, request->from, request->len);
581
 
 
582
 
        if (magic != NBD_REQUEST_MAGIC) {
583
 
                LOG("invalid magic (got 0x%x)", magic);
584
 
                errno = EINVAL;
585
 
                return -1;
586
 
        }
587
 
        return 0;
 
456
    uint8_t buf[4 + 4 + 8 + 8 + 4];
 
457
    uint32_t magic;
 
458
 
 
459
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
 
460
        LOG("read failed");
 
461
        errno = EINVAL;
 
462
        return -1;
 
463
    }
 
464
 
 
465
    /* Request
 
466
       [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
 
467
       [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
 
468
       [ 8 .. 15]   handle
 
469
       [16 .. 23]   from
 
470
       [24 .. 27]   len
 
471
     */
 
472
 
 
473
    magic = be32_to_cpup((uint32_t*)buf);
 
474
    request->type  = be32_to_cpup((uint32_t*)(buf + 4));
 
475
    request->handle = be64_to_cpup((uint64_t*)(buf + 8));
 
476
    request->from  = be64_to_cpup((uint64_t*)(buf + 16));
 
477
    request->len   = be32_to_cpup((uint32_t*)(buf + 24));
 
478
 
 
479
    TRACE("Got request: "
 
480
          "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
 
481
          magic, request->type, request->from, request->len);
 
482
 
 
483
    if (magic != NBD_REQUEST_MAGIC) {
 
484
        LOG("invalid magic (got 0x%x)", magic);
 
485
        errno = EINVAL;
 
486
        return -1;
 
487
    }
 
488
    return 0;
588
489
}
589
490
 
590
491
int nbd_receive_reply(int csock, struct nbd_reply *reply)
591
492
{
592
 
        uint8_t buf[NBD_REPLY_SIZE];
593
 
        uint32_t magic;
594
 
 
595
 
        memset(buf, 0xAA, sizeof(buf));
596
 
 
597
 
        if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
598
 
                LOG("read failed");
599
 
                errno = EINVAL;
600
 
                return -1;
601
 
        }
602
 
 
603
 
        /* Reply
604
 
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
605
 
           [ 4 ..  7]    error   (0 == no error)
606
 
           [ 7 .. 15]    handle
607
 
         */
608
 
 
609
 
        magic = be32_to_cpup((uint32_t*)buf);
610
 
        reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
611
 
        reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
612
 
 
613
 
        TRACE("Got reply: "
614
 
              "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
615
 
              magic, reply->error, reply->handle);
616
 
 
617
 
        if (magic != NBD_REPLY_MAGIC) {
618
 
                LOG("invalid magic (got 0x%x)", magic);
619
 
                errno = EINVAL;
620
 
                return -1;
621
 
        }
622
 
        return 0;
 
493
    uint8_t buf[NBD_REPLY_SIZE];
 
494
    uint32_t magic;
 
495
 
 
496
    memset(buf, 0xAA, sizeof(buf));
 
497
 
 
498
    if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
 
499
        LOG("read failed");
 
500
        errno = EINVAL;
 
501
        return -1;
 
502
    }
 
503
 
 
504
    /* Reply
 
505
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
 
506
       [ 4 ..  7]    error   (0 == no error)
 
507
       [ 7 .. 15]    handle
 
508
     */
 
509
 
 
510
    magic = be32_to_cpup((uint32_t*)buf);
 
511
    reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
 
512
    reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
 
513
 
 
514
    TRACE("Got reply: "
 
515
          "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
 
516
          magic, reply->error, reply->handle);
 
517
 
 
518
    if (magic != NBD_REPLY_MAGIC) {
 
519
        LOG("invalid magic (got 0x%x)", magic);
 
520
        errno = EINVAL;
 
521
        return -1;
 
522
    }
 
523
    return 0;
623
524
}
624
525
 
625
526
static int nbd_send_reply(int csock, struct nbd_reply *reply)
626
527
{
627
 
        uint8_t buf[4 + 4 + 8];
628
 
 
629
 
        /* Reply
630
 
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
631
 
           [ 4 ..  7]    error   (0 == no error)
632
 
           [ 7 .. 15]    handle
633
 
         */
634
 
        cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
635
 
        cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
636
 
        cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
637
 
 
638
 
        TRACE("Sending response to client");
639
 
 
640
 
        if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
641
 
                LOG("writing to socket failed");
642
 
                errno = EINVAL;
643
 
                return -1;
644
 
        }
645
 
        return 0;
 
528
    uint8_t buf[4 + 4 + 8];
 
529
 
 
530
    /* Reply
 
531
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
 
532
       [ 4 ..  7]    error   (0 == no error)
 
533
       [ 7 .. 15]    handle
 
534
     */
 
535
    cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
 
536
    cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
 
537
    cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
 
538
 
 
539
    TRACE("Sending response to client");
 
540
 
 
541
    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
 
542
        LOG("writing to socket failed");
 
543
        errno = EINVAL;
 
544
        return -1;
 
545
    }
 
546
    return 0;
646
547
}
647
548
 
648
549
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
649
550
             off_t *offset, bool readonly, uint8_t *data, int data_size)
650
551
{
651
 
        struct nbd_request request;
652
 
        struct nbd_reply reply;
653
 
 
654
 
        TRACE("Reading request.");
655
 
 
656
 
        if (nbd_receive_request(csock, &request) == -1)
657
 
                return -1;
658
 
 
659
 
        if (request.len + NBD_REPLY_SIZE > data_size) {
660
 
                LOG("len (%u) is larger than max len (%u)",
661
 
                    request.len + NBD_REPLY_SIZE, data_size);
662
 
                errno = EINVAL;
663
 
                return -1;
664
 
        }
665
 
 
666
 
        if ((request.from + request.len) < request.from) {
667
 
                LOG("integer overflow detected! "
668
 
                    "you're probably being attacked");
669
 
                errno = EINVAL;
670
 
                return -1;
671
 
        }
672
 
 
673
 
        if ((request.from + request.len) > size) {
674
 
                LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
675
 
                    ", Offset: %" PRIu64 "\n",
 
552
    struct nbd_request request;
 
553
    struct nbd_reply reply;
 
554
 
 
555
    TRACE("Reading request.");
 
556
 
 
557
    if (nbd_receive_request(csock, &request) == -1)
 
558
        return -1;
 
559
 
 
560
    if (request.len + NBD_REPLY_SIZE > data_size) {
 
561
        LOG("len (%u) is larger than max len (%u)",
 
562
            request.len + NBD_REPLY_SIZE, data_size);
 
563
        errno = EINVAL;
 
564
        return -1;
 
565
    }
 
566
 
 
567
    if ((request.from + request.len) < request.from) {
 
568
        LOG("integer overflow detected! "
 
569
            "you're probably being attacked");
 
570
        errno = EINVAL;
 
571
        return -1;
 
572
    }
 
573
 
 
574
    if ((request.from + request.len) > size) {
 
575
            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
 
576
            ", Offset: %" PRIu64 "\n",
676
577
                    request.from, request.len, (uint64_t)size, dev_offset);
677
 
                LOG("requested operation past EOF--bad client?");
678
 
                errno = EINVAL;
679
 
                return -1;
680
 
        }
681
 
 
682
 
        TRACE("Decoding type");
683
 
 
684
 
        reply.handle = request.handle;
685
 
        reply.error = 0;
686
 
 
687
 
        switch (request.type) {
688
 
        case NBD_CMD_READ:
689
 
                TRACE("Request type is READ");
690
 
 
691
 
                if (bdrv_read(bs, (request.from + dev_offset) / 512,
692
 
                              data + NBD_REPLY_SIZE,
693
 
                              request.len / 512) == -1) {
694
 
                        LOG("reading from file failed");
695
 
                        errno = EINVAL;
696
 
                        return -1;
697
 
                }
698
 
                *offset += request.len;
699
 
 
700
 
                TRACE("Read %u byte(s)", request.len);
701
 
 
702
 
                /* Reply
703
 
                   [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
704
 
                   [ 4 ..  7]    error   (0 == no error)
705
 
                   [ 7 .. 15]    handle
706
 
                 */
707
 
 
708
 
                cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
709
 
                cpu_to_be32w((uint32_t*)(data + 4), reply.error);
710
 
                cpu_to_be64w((uint64_t*)(data + 8), reply.handle);
711
 
 
712
 
                TRACE("Sending data to client");
713
 
 
714
 
                if (write_sync(csock, data,
715
 
                               request.len + NBD_REPLY_SIZE) !=
716
 
                               request.len + NBD_REPLY_SIZE) {
717
 
                        LOG("writing to socket failed");
718
 
                        errno = EINVAL;
719
 
                        return -1;
720
 
                }
721
 
                break;
722
 
        case NBD_CMD_WRITE:
723
 
                TRACE("Request type is WRITE");
724
 
 
725
 
                TRACE("Reading %u byte(s)", request.len);
726
 
 
727
 
                if (read_sync(csock, data, request.len) != request.len) {
728
 
                        LOG("reading from socket failed");
729
 
                        errno = EINVAL;
730
 
                        return -1;
731
 
                }
732
 
 
733
 
                if (readonly) {
734
 
                        TRACE("Server is read-only, return error");
735
 
                        reply.error = 1;
736
 
                } else {
737
 
                        TRACE("Writing to device");
738
 
 
739
 
                        if (bdrv_write(bs, (request.from + dev_offset) / 512,
740
 
                                       data, request.len / 512) == -1) {
741
 
                                LOG("writing to file failed");
742
 
                                errno = EINVAL;
743
 
                                return -1;
744
 
                        }
745
 
 
746
 
                        *offset += request.len;
747
 
                }
748
 
 
749
 
                if (nbd_send_reply(csock, &reply) == -1)
750
 
                        return -1;
751
 
                break;
752
 
        case NBD_CMD_DISC:
753
 
                TRACE("Request type is DISCONNECT");
754
 
                errno = 0;
755
 
                return 1;
756
 
        default:
757
 
                LOG("invalid request type (%u) received", request.type);
758
 
                errno = EINVAL;
759
 
                return -1;
760
 
        }
761
 
 
762
 
        TRACE("Request/Reply complete");
763
 
 
764
 
        return 0;
 
578
        LOG("requested operation past EOF--bad client?");
 
579
        errno = EINVAL;
 
580
        return -1;
 
581
    }
 
582
 
 
583
    TRACE("Decoding type");
 
584
 
 
585
    reply.handle = request.handle;
 
586
    reply.error = 0;
 
587
 
 
588
    switch (request.type) {
 
589
    case NBD_CMD_READ:
 
590
        TRACE("Request type is READ");
 
591
 
 
592
        if (bdrv_read(bs, (request.from + dev_offset) / 512,
 
593
                  data + NBD_REPLY_SIZE,
 
594
                  request.len / 512) == -1) {
 
595
            LOG("reading from file failed");
 
596
            errno = EINVAL;
 
597
            return -1;
 
598
        }
 
599
        *offset += request.len;
 
600
 
 
601
        TRACE("Read %u byte(s)", request.len);
 
602
 
 
603
        /* Reply
 
604
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
 
605
           [ 4 ..  7]    error   (0 == no error)
 
606
           [ 7 .. 15]    handle
 
607
         */
 
608
 
 
609
        cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
 
610
        cpu_to_be32w((uint32_t*)(data + 4), reply.error);
 
611
        cpu_to_be64w((uint64_t*)(data + 8), reply.handle);
 
612
 
 
613
        TRACE("Sending data to client");
 
614
 
 
615
        if (write_sync(csock, data,
 
616
                   request.len + NBD_REPLY_SIZE) !=
 
617
                   request.len + NBD_REPLY_SIZE) {
 
618
            LOG("writing to socket failed");
 
619
            errno = EINVAL;
 
620
            return -1;
 
621
        }
 
622
        break;
 
623
    case NBD_CMD_WRITE:
 
624
        TRACE("Request type is WRITE");
 
625
 
 
626
        TRACE("Reading %u byte(s)", request.len);
 
627
 
 
628
        if (read_sync(csock, data, request.len) != request.len) {
 
629
            LOG("reading from socket failed");
 
630
            errno = EINVAL;
 
631
            return -1;
 
632
        }
 
633
 
 
634
        if (readonly) {
 
635
            TRACE("Server is read-only, return error");
 
636
            reply.error = 1;
 
637
        } else {
 
638
            TRACE("Writing to device");
 
639
 
 
640
            if (bdrv_write(bs, (request.from + dev_offset) / 512,
 
641
                       data, request.len / 512) == -1) {
 
642
                LOG("writing to file failed");
 
643
                errno = EINVAL;
 
644
                return -1;
 
645
            }
 
646
 
 
647
            *offset += request.len;
 
648
        }
 
649
 
 
650
        if (nbd_send_reply(csock, &reply) == -1)
 
651
            return -1;
 
652
        break;
 
653
    case NBD_CMD_DISC:
 
654
        TRACE("Request type is DISCONNECT");
 
655
        errno = 0;
 
656
        return 1;
 
657
    default:
 
658
        LOG("invalid request type (%u) received", request.type);
 
659
        errno = EINVAL;
 
660
        return -1;
 
661
    }
 
662
 
 
663
    TRACE("Request/Reply complete");
 
664
 
 
665
    return 0;
765
666
}