]> Git Repo - qemu.git/blob - nbd.c
Move main signal handler setup to os specificfiles.
[qemu.git] / nbd.c
1 /*
2  *  Copyright (C) 2005  Anthony Liguori <[email protected]>
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
21 #include <errno.h>
22 #include <string.h>
23 #ifndef _WIN32
24 #include <sys/ioctl.h>
25 #endif
26 #ifdef __sun__
27 #include <sys/ioccom.h>
28 #endif
29 #include <ctype.h>
30 #include <inttypes.h>
31
32 #include "qemu_socket.h"
33
34 //#define DEBUG_NBD
35
36 #ifdef DEBUG_NBD
37 #define TRACE(msg, ...) do { \
38     LOG(msg, ## __VA_ARGS__); \
39 } while(0)
40 #else
41 #define TRACE(msg, ...) \
42     do { } while (0)
43 #endif
44
45 #define LOG(msg, ...) do { \
46     fprintf(stderr, "%s:%s():L%d: " msg "\n", \
47             __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
48 } while(0)
49
50 /* This is all part of the "official" NBD API */
51
52 #define NBD_REQUEST_MAGIC       0x25609513
53 #define NBD_REPLY_MAGIC         0x67446698
54
55 #define NBD_SET_SOCK            _IO(0xab, 0)
56 #define NBD_SET_BLKSIZE         _IO(0xab, 1)
57 #define NBD_SET_SIZE            _IO(0xab, 2)
58 #define NBD_DO_IT               _IO(0xab, 3)
59 #define NBD_CLEAR_SOCK          _IO(0xab, 4)
60 #define NBD_CLEAR_QUE           _IO(0xab, 5)
61 #define NBD_PRINT_DEBUG         _IO(0xab, 6)
62 #define NBD_SET_SIZE_BLOCKS     _IO(0xab, 7)
63 #define NBD_DISCONNECT          _IO(0xab, 8)
64
65 /* That's all folks */
66
67 #define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
68 #define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false)
69
70 size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
71 {
72     size_t offset = 0;
73
74     while (offset < size) {
75         ssize_t len;
76
77         if (do_read) {
78             len = recv(fd, buffer + offset, size - offset, 0);
79         } else {
80             len = send(fd, buffer + offset, size - offset, 0);
81         }
82
83         if (len == -1)
84             errno = socket_error();
85
86         /* recoverable error */
87         if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
88             continue;
89         }
90
91         /* eof */
92         if (len == 0) {
93             break;
94         }
95
96         /* unrecoverable error */
97         if (len == -1) {
98             return 0;
99         }
100
101         offset += len;
102     }
103
104     return offset;
105 }
106
107 int tcp_socket_outgoing(const char *address, uint16_t port)
108 {
109     int s;
110     struct in_addr in;
111     struct sockaddr_in addr;
112
113     s = socket(PF_INET, SOCK_STREAM, 0);
114     if (s == -1) {
115         return -1;
116     }
117
118     if (inet_aton(address, &in) == 0) {
119         struct hostent *ent;
120
121         ent = gethostbyname(address);
122         if (ent == NULL) {
123             goto error;
124         }
125
126         memcpy(&in, ent->h_addr, sizeof(in));
127     }
128
129     addr.sin_family = AF_INET;
130     addr.sin_port = htons(port);
131     memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
132
133     if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
134         goto error;
135     }
136
137     return s;
138 error:
139     closesocket(s);
140     return -1;
141 }
142
143 int tcp_socket_incoming(const char *address, uint16_t port)
144 {
145     int s;
146     struct in_addr in;
147     struct sockaddr_in addr;
148     int opt;
149
150     s = socket(PF_INET, SOCK_STREAM, 0);
151     if (s == -1) {
152         return -1;
153     }
154
155     if (inet_aton(address, &in) == 0) {
156         struct hostent *ent;
157
158         ent = gethostbyname(address);
159         if (ent == NULL) {
160             goto error;
161         }
162
163         memcpy(&in, ent->h_addr, sizeof(in));
164     }
165
166     addr.sin_family = AF_INET;
167     addr.sin_port = htons(port);
168     memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
169
170     opt = 1;
171     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
172                    (const void *) &opt, sizeof(opt)) == -1) {
173         goto error;
174     }
175
176     if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
177         goto error;
178     }
179
180     if (listen(s, 128) == -1) {
181         goto error;
182     }
183
184     return s;
185 error:
186     closesocket(s);
187     return -1;
188 }
189
190 #ifndef _WIN32
191 int unix_socket_incoming(const char *path)
192 {
193     int s;
194     struct sockaddr_un addr;
195
196     s = socket(PF_UNIX, SOCK_STREAM, 0);
197     if (s == -1) {
198         return -1;
199     }
200
201     memset(&addr, 0, sizeof(addr));
202     addr.sun_family = AF_UNIX;
203     pstrcpy(addr.sun_path, sizeof(addr.sun_path), path);
204
205     if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
206         goto error;
207     }
208
209     if (listen(s, 128) == -1) {
210         goto error;
211     }
212
213     return s;
214 error:
215     closesocket(s);
216     return -1;
217 }
218
219 int unix_socket_outgoing(const char *path)
220 {
221     int s;
222     struct sockaddr_un addr;
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     closesocket(s);
240     return -1;
241 }
242 #else
243 int unix_socket_incoming(const char *path)
244 {
245     errno = ENOTSUP;
246     return -1;
247 }
248
249 int unix_socket_outgoing(const char *path)
250 {
251     errno = ENOTSUP;
252     return -1;
253 }
254 #endif
255
256
257 /* Basic flow
258
259    Server         Client
260
261    Negotiate
262                   Request
263    Response
264                   Request
265    Response
266                   ...
267    ...
268                   Request (type == 2)
269 */
270
271 int nbd_negotiate(int csock, off_t size)
272 {
273         char buf[8 + 8 + 8 + 128];
274
275         /* Negotiate
276            [ 0 ..   7]   passwd   ("NBDMAGIC")
277            [ 8 ..  15]   magic    (0x00420281861253)
278            [16 ..  23]   size
279            [24 .. 151]   reserved (0)
280          */
281
282         TRACE("Beginning negotiation.");
283         memcpy(buf, "NBDMAGIC", 8);
284         cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
285         cpu_to_be64w((uint64_t*)(buf + 16), size);
286         memset(buf + 24, 0, 128);
287
288         if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
289                 LOG("write failed");
290                 errno = EINVAL;
291                 return -1;
292         }
293
294         TRACE("Negotation succeeded.");
295
296         return 0;
297 }
298
299 int nbd_receive_negotiate(int csock, off_t *size, size_t *blocksize)
300 {
301         char buf[8 + 8 + 8 + 128];
302         uint64_t magic;
303
304         TRACE("Receiving negotation.");
305
306         if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
307                 LOG("read failed");
308                 errno = EINVAL;
309                 return -1;
310         }
311
312         magic = be64_to_cpup((uint64_t*)(buf + 8));
313         *size = be64_to_cpup((uint64_t*)(buf + 16));
314         *blocksize = 1024;
315
316         TRACE("Magic is %c%c%c%c%c%c%c%c",
317               qemu_isprint(buf[0]) ? buf[0] : '.',
318               qemu_isprint(buf[1]) ? buf[1] : '.',
319               qemu_isprint(buf[2]) ? buf[2] : '.',
320               qemu_isprint(buf[3]) ? buf[3] : '.',
321               qemu_isprint(buf[4]) ? buf[4] : '.',
322               qemu_isprint(buf[5]) ? buf[5] : '.',
323               qemu_isprint(buf[6]) ? buf[6] : '.',
324               qemu_isprint(buf[7]) ? buf[7] : '.');
325         TRACE("Magic is 0x%" PRIx64, magic);
326         TRACE("Size is %" PRIu64, *size);
327
328         if (memcmp(buf, "NBDMAGIC", 8) != 0) {
329                 LOG("Invalid magic received");
330                 errno = EINVAL;
331                 return -1;
332         }
333
334         TRACE("Checking magic");
335
336         if (magic != 0x00420281861253LL) {
337                 LOG("Bad magic received");
338                 errno = EINVAL;
339                 return -1;
340         }
341         return 0;
342 }
343
344 #ifndef _WIN32
345 int nbd_init(int fd, int csock, off_t size, size_t blocksize)
346 {
347         TRACE("Setting block size to %lu", (unsigned long)blocksize);
348
349         if (ioctl(fd, NBD_SET_BLKSIZE, blocksize) == -1) {
350                 int serrno = errno;
351                 LOG("Failed setting NBD block size");
352                 errno = serrno;
353                 return -1;
354         }
355
356         TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
357
358         if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
359                 int serrno = errno;
360                 LOG("Failed setting size (in blocks)");
361                 errno = serrno;
362                 return -1;
363         }
364
365         TRACE("Clearing NBD socket");
366
367         if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
368                 int serrno = errno;
369                 LOG("Failed clearing NBD socket");
370                 errno = serrno;
371                 return -1;
372         }
373
374         TRACE("Setting NBD socket");
375
376         if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
377                 int serrno = errno;
378                 LOG("Failed to set NBD socket");
379                 errno = serrno;
380                 return -1;
381         }
382
383         TRACE("Negotiation ended");
384
385         return 0;
386 }
387
388 int nbd_disconnect(int fd)
389 {
390         ioctl(fd, NBD_CLEAR_QUE);
391         ioctl(fd, NBD_DISCONNECT);
392         ioctl(fd, NBD_CLEAR_SOCK);
393         return 0;
394 }
395
396 int nbd_client(int fd, int csock)
397 {
398         int ret;
399         int serrno;
400
401         TRACE("Doing NBD loop");
402
403         ret = ioctl(fd, NBD_DO_IT);
404         serrno = errno;
405
406         TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
407
408         TRACE("Clearing NBD queue");
409         ioctl(fd, NBD_CLEAR_QUE);
410
411         TRACE("Clearing NBD socket");
412         ioctl(fd, NBD_CLEAR_SOCK);
413
414         errno = serrno;
415         return ret;
416 }
417 #else
418 int nbd_init(int fd, int csock, off_t size, size_t blocksize)
419 {
420     errno = ENOTSUP;
421     return -1;
422 }
423
424 int nbd_disconnect(int fd)
425 {
426     errno = ENOTSUP;
427     return -1;
428 }
429
430 int nbd_client(int fd, int csock)
431 {
432     errno = ENOTSUP;
433     return -1;
434 }
435 #endif
436
437 int nbd_send_request(int csock, struct nbd_request *request)
438 {
439         uint8_t buf[4 + 4 + 8 + 8 + 4];
440
441         cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
442         cpu_to_be32w((uint32_t*)(buf + 4), request->type);
443         cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
444         cpu_to_be64w((uint64_t*)(buf + 16), request->from);
445         cpu_to_be32w((uint32_t*)(buf + 24), request->len);
446
447         TRACE("Sending request to client");
448
449         if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
450                 LOG("writing to socket failed");
451                 errno = EINVAL;
452                 return -1;
453         }
454         return 0;
455 }
456
457
458 static int nbd_receive_request(int csock, struct nbd_request *request)
459 {
460         uint8_t buf[4 + 4 + 8 + 8 + 4];
461         uint32_t magic;
462
463         if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
464                 LOG("read failed");
465                 errno = EINVAL;
466                 return -1;
467         }
468
469         /* Request
470            [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
471            [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
472            [ 8 .. 15]   handle
473            [16 .. 23]   from
474            [24 .. 27]   len
475          */
476
477         magic = be32_to_cpup((uint32_t*)buf);
478         request->type  = be32_to_cpup((uint32_t*)(buf + 4));
479         request->handle = be64_to_cpup((uint64_t*)(buf + 8));
480         request->from  = be64_to_cpup((uint64_t*)(buf + 16));
481         request->len   = be32_to_cpup((uint32_t*)(buf + 24));
482
483         TRACE("Got request: "
484               "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
485               magic, request->type, request->from, request->len);
486
487         if (magic != NBD_REQUEST_MAGIC) {
488                 LOG("invalid magic (got 0x%x)", magic);
489                 errno = EINVAL;
490                 return -1;
491         }
492         return 0;
493 }
494
495 int nbd_receive_reply(int csock, struct nbd_reply *reply)
496 {
497         uint8_t buf[4 + 4 + 8];
498         uint32_t magic;
499
500         memset(buf, 0xAA, sizeof(buf));
501
502         if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
503                 LOG("read failed");
504                 errno = EINVAL;
505                 return -1;
506         }
507
508         /* Reply
509            [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
510            [ 4 ..  7]    error   (0 == no error)
511            [ 7 .. 15]    handle
512          */
513
514         magic = be32_to_cpup((uint32_t*)buf);
515         reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
516         reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
517
518         TRACE("Got reply: "
519               "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
520               magic, reply->error, reply->handle);
521
522         if (magic != NBD_REPLY_MAGIC) {
523                 LOG("invalid magic (got 0x%x)", magic);
524                 errno = EINVAL;
525                 return -1;
526         }
527         return 0;
528 }
529
530 static int nbd_send_reply(int csock, struct nbd_reply *reply)
531 {
532         uint8_t buf[4 + 4 + 8];
533
534         /* Reply
535            [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
536            [ 4 ..  7]    error   (0 == no error)
537            [ 7 .. 15]    handle
538          */
539         cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
540         cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
541         cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
542
543         TRACE("Sending response to client");
544
545         if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
546                 LOG("writing to socket failed");
547                 errno = EINVAL;
548                 return -1;
549         }
550         return 0;
551 }
552
553 int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
554              off_t *offset, bool readonly, uint8_t *data, int data_size)
555 {
556         struct nbd_request request;
557         struct nbd_reply reply;
558
559         TRACE("Reading request.");
560
561         if (nbd_receive_request(csock, &request) == -1)
562                 return -1;
563
564         if (request.len > data_size) {
565                 LOG("len (%u) is larger than max len (%u)",
566                     request.len, data_size);
567                 errno = EINVAL;
568                 return -1;
569         }
570
571         if ((request.from + request.len) < request.from) {
572                 LOG("integer overflow detected! "
573                     "you're probably being attacked");
574                 errno = EINVAL;
575                 return -1;
576         }
577
578         if ((request.from + request.len) > size) {
579                 LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
580                     ", Offset: %" PRIu64 "\n",
581                     request.from, request.len, (uint64_t)size, dev_offset);
582                 LOG("requested operation past EOF--bad client?");
583                 errno = EINVAL;
584                 return -1;
585         }
586
587         TRACE("Decoding type");
588
589         reply.handle = request.handle;
590         reply.error = 0;
591
592         switch (request.type) {
593         case NBD_CMD_READ:
594                 TRACE("Request type is READ");
595
596                 if (bdrv_read(bs, (request.from + dev_offset) / 512, data,
597                               request.len / 512) == -1) {
598                         LOG("reading from file failed");
599                         errno = EINVAL;
600                         return -1;
601                 }
602                 *offset += request.len;
603
604                 TRACE("Read %u byte(s)", request.len);
605
606                 if (nbd_send_reply(csock, &reply) == -1)
607                         return -1;
608
609                 TRACE("Sending data to client");
610
611                 if (write_sync(csock, data, request.len) != request.len) {
612                         LOG("writing to socket failed");
613                         errno = EINVAL;
614                         return -1;
615                 }
616                 break;
617         case NBD_CMD_WRITE:
618                 TRACE("Request type is WRITE");
619
620                 TRACE("Reading %u byte(s)", request.len);
621
622                 if (read_sync(csock, data, request.len) != request.len) {
623                         LOG("reading from socket failed");
624                         errno = EINVAL;
625                         return -1;
626                 }
627
628                 if (readonly) {
629                         TRACE("Server is read-only, return error");
630                         reply.error = 1;
631                 } else {
632                         TRACE("Writing to device");
633
634                         if (bdrv_write(bs, (request.from + dev_offset) / 512,
635                                        data, request.len / 512) == -1) {
636                                 LOG("writing to file failed");
637                                 errno = EINVAL;
638                                 return -1;
639                         }
640
641                         *offset += request.len;
642                 }
643
644                 if (nbd_send_reply(csock, &reply) == -1)
645                         return -1;
646                 break;
647         case NBD_CMD_DISC:
648                 TRACE("Request type is DISCONNECT");
649                 errno = 0;
650                 return 1;
651         default:
652                 LOG("invalid request type (%u) received", request.type);
653                 errno = EINVAL;
654                 return -1;
655         }
656
657         TRACE("Request/Reply complete");
658
659         return 0;
660 }
This page took 0.059891 seconds and 4 git commands to generate.