File:  [Qemu by Fabrice Bellard] / qemu / nbd.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:33:08 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

    1: /*
    2:  *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
    3:  *
    4:  *  Network Block Device
    5:  *
    6:  *  This program is free software; you can redistribute it and/or modify
    7:  *  it under the terms of the GNU General Public License as published by
    8:  *  the Free Software Foundation; under version 2 of the License.
    9:  *
   10:  *  This program is distributed in the hope that it will be useful,
   11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13:  *  GNU General Public License for more details.
   14:  *
   15:  *  You should have received a copy of the GNU General Public License
   16:  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
   17:  */
   18: 
   19: #include "nbd.h"
   20: 
   21: #include <errno.h>
   22: #include <string.h>
   23: #ifndef _WIN32
   24: #include <sys/ioctl.h>
   25: #endif
   26: #if defined(__sun__) || defined(__HAIKU__)
   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_REPLY_SIZE		(4 + 4 + 8)
   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: 
   66: #define NBD_OPT_EXPORT_NAME	(1 << 0)
   67: 
   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;
  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: 
  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: 
  302: int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
  303:                           off_t *size, size_t *blocksize)
  304: {
  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: 	}
  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: 
  451:         TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
  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: 
  491: int nbd_client(int fd)
  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: 
  525: int nbd_client(int fd)
  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: {
  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;
  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: 
  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",
  676:                     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;
  765: }

unix.superglobalmegacorp.com