Annotation of qemu/nbd.c, revision 1.1.1.4

1.1       root        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
1.1.1.2   root       16:  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1.1       root       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
1.1.1.4 ! root       26: #if defined(__sun__) || defined(__HAIKU__)
1.1       root       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: 
1.1.1.4 ! root       52: #define NBD_REPLY_SIZE         (4 + 4 + 8)
1.1       root       53: #define NBD_REQUEST_MAGIC       0x25609513
                     54: #define NBD_REPLY_MAGIC         0x67446698
                     55: 
                     56: #define NBD_SET_SOCK            _IO(0xab, 0)
                     57: #define NBD_SET_BLKSIZE         _IO(0xab, 1)
                     58: #define NBD_SET_SIZE            _IO(0xab, 2)
                     59: #define NBD_DO_IT               _IO(0xab, 3)
                     60: #define NBD_CLEAR_SOCK          _IO(0xab, 4)
                     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)
                     64: #define NBD_DISCONNECT          _IO(0xab, 8)
                     65: 
1.1.1.4 ! root       66: #define NBD_OPT_EXPORT_NAME    (1 << 0)
        !            67: 
1.1       root       68: /* That's all folks */
                     69: 
                     70: #define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
                     71: #define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false)
                     72: 
                     73: size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
                     74: {
                     75:     size_t offset = 0;
                     76: 
                     77:     while (offset < size) {
                     78:         ssize_t len;
                     79: 
                     80:         if (do_read) {
                     81:             len = recv(fd, buffer + offset, size - offset, 0);
                     82:         } else {
                     83:             len = send(fd, buffer + offset, size - offset, 0);
                     84:         }
                     85: 
                     86:         if (len == -1)
                     87:             errno = socket_error();
                     88: 
                     89:         /* recoverable error */
                     90:         if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
                     91:             continue;
                     92:         }
                     93: 
                     94:         /* eof */
                     95:         if (len == 0) {
                     96:             break;
                     97:         }
                     98: 
                     99:         /* unrecoverable error */
                    100:         if (len == -1) {
                    101:             return 0;
                    102:         }
                    103: 
                    104:         offset += len;
                    105:     }
                    106: 
                    107:     return offset;
                    108: }
                    109: 
                    110: int tcp_socket_outgoing(const char *address, uint16_t port)
                    111: {
                    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;
                    144: }
                    145: 
                    146: int tcp_socket_incoming(const char *address, uint16_t port)
                    147: {
                    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;
1.1.1.2   root      174:     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                    175:                    (const void *) &opt, sizeof(opt)) == -1) {
1.1       root      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: 
                    259: 
                    260: /* Basic flow
                    261: 
                    262:    Server         Client
                    263: 
                    264:    Negotiate
                    265:                   Request
                    266:    Response
                    267:                   Request
                    268:    Response
                    269:                   ...
                    270:    ...
                    271:                   Request (type == 2)
                    272: */
                    273: 
                    274: int nbd_negotiate(int csock, off_t size)
                    275: {
                    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;
                    300: }
                    301: 
1.1.1.4 ! root      302: int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
        !           303:                           off_t *size, size_t *blocksize)
1.1       root      304: {
1.1.1.4 ! root      305:        char buf[256];
        !           306:        uint64_t magic, s;
        !           307:        uint16_t tmp;
1.1       root      308: 
                    309:        TRACE("Receiving negotation.");
                    310: 
1.1.1.4 ! root      311:        if (read_sync(csock, buf, 8) != 8) {
1.1       root      312:                LOG("read failed");
                    313:                errno = EINVAL;
                    314:                return -1;
                    315:        }
                    316: 
1.1.1.4 ! root      317:        buf[8] = '\0';
        !           318:        if (strlen(buf) == 0) {
        !           319:                LOG("server connection closed");
        !           320:                errno = EINVAL;
        !           321:                return -1;
        !           322:        }
1.1       root      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: 
1.1.1.4 ! root      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);
1.1       root      415: 
1.1.1.4 ! root      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)");
1.1       root      433:                errno = EINVAL;
                    434:                return -1;
                    435:        }
                    436:         return 0;
                    437: }
                    438: 
                    439: #ifndef _WIN32
                    440: int nbd_init(int fd, int csock, off_t size, size_t blocksize)
                    441: {
                    442:        TRACE("Setting block size to %lu", (unsigned long)blocksize);
                    443: 
                    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:        }
                    450: 
1.1.1.3   root      451:         TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
1.1       root      452: 
                    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;
                    481: }
                    482: 
                    483: int nbd_disconnect(int fd)
                    484: {
                    485:        ioctl(fd, NBD_CLEAR_QUE);
                    486:        ioctl(fd, NBD_DISCONNECT);
                    487:        ioctl(fd, NBD_CLEAR_SOCK);
                    488:        return 0;
                    489: }
                    490: 
1.1.1.4 ! root      491: int nbd_client(int fd)
1.1       root      492: {
                    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;
                    511: }
                    512: #else
                    513: int nbd_init(int fd, int csock, off_t size, size_t blocksize)
                    514: {
                    515:     errno = ENOTSUP;
                    516:     return -1;
                    517: }
                    518: 
                    519: int nbd_disconnect(int fd)
                    520: {
                    521:     errno = ENOTSUP;
                    522:     return -1;
                    523: }
                    524: 
1.1.1.4 ! root      525: int nbd_client(int fd)
1.1       root      526: {
                    527:     errno = ENOTSUP;
                    528:     return -1;
                    529: }
                    530: #endif
                    531: 
                    532: int nbd_send_request(int csock, struct nbd_request *request)
                    533: {
                    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;
                    550: }
                    551: 
                    552: 
                    553: static int nbd_receive_request(int csock, struct nbd_request *request)
                    554: {
                    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;
                    588: }
                    589: 
                    590: int nbd_receive_reply(int csock, struct nbd_reply *reply)
                    591: {
1.1.1.4 ! root      592:        uint8_t buf[NBD_REPLY_SIZE];
1.1       root      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;
                    623: }
                    624: 
                    625: static int nbd_send_reply(int csock, struct nbd_reply *reply)
                    626: {
                    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;
                    646: }
                    647: 
                    648: int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
                    649:              off_t *offset, bool readonly, uint8_t *data, int data_size)
                    650: {
                    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: 
1.1.1.4 ! root      659:        if (request.len + NBD_REPLY_SIZE > data_size) {
1.1       root      660:                LOG("len (%u) is larger than max len (%u)",
1.1.1.4 ! root      661:                    request.len + NBD_REPLY_SIZE, data_size);
1.1       root      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",
1.1.1.2   root      676:                     request.from, request.len, (uint64_t)size, dev_offset);
1.1       root      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: 
1.1.1.4 ! root      691:                if (bdrv_read(bs, (request.from + dev_offset) / 512,
        !           692:                              data + NBD_REPLY_SIZE,
1.1       root      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: 
1.1.1.4 ! root      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);
1.1       root      711: 
                    712:                TRACE("Sending data to client");
                    713: 
1.1.1.4 ! root      714:                if (write_sync(csock, data,
        !           715:                               request.len + NBD_REPLY_SIZE) !=
        !           716:                               request.len + NBD_REPLY_SIZE) {
1.1       root      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;
                    765: }

unix.superglobalmegacorp.com