File:  [Qemu by Fabrice Bellard] / qemu / nbd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:13 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.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, write to the Free Software
   17:  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
   18:  */
   19: 
   20: #include "nbd.h"
   21: 
   22: #include <errno.h>
   23: #include <string.h>
   24: #ifndef _WIN32
   25: #include <sys/ioctl.h>
   26: #endif
   27: #ifdef __sun__
   28: #include <sys/ioccom.h>
   29: #endif
   30: #include <ctype.h>
   31: #include <inttypes.h>
   32: 
   33: #include "qemu_socket.h"
   34: 
   35: //#define DEBUG_NBD
   36: 
   37: #ifdef DEBUG_NBD
   38: #define TRACE(msg, ...) do { \
   39:     LOG(msg, ## __VA_ARGS__); \
   40: } while(0)
   41: #else
   42: #define TRACE(msg, ...) \
   43:     do { } while (0)
   44: #endif
   45: 
   46: #define LOG(msg, ...) do { \
   47:     fprintf(stderr, "%s:%s():L%d: " msg "\n", \
   48:             __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
   49: } while(0)
   50: 
   51: /* This is all part of the "official" NBD API */
   52: 
   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: /* That's all folks */
   67: 
   68: #define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
   69: #define write_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, false)
   70: 
   71: size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read)
   72: {
   73:     size_t offset = 0;
   74: 
   75:     while (offset < size) {
   76:         ssize_t len;
   77: 
   78:         if (do_read) {
   79:             len = recv(fd, buffer + offset, size - offset, 0);
   80:         } else {
   81:             len = send(fd, buffer + offset, size - offset, 0);
   82:         }
   83: 
   84:         if (len == -1)
   85:             errno = socket_error();
   86: 
   87:         /* recoverable error */
   88:         if (len == -1 && (errno == EAGAIN || errno == EINTR)) {
   89:             continue;
   90:         }
   91: 
   92:         /* eof */
   93:         if (len == 0) {
   94:             break;
   95:         }
   96: 
   97:         /* unrecoverable error */
   98:         if (len == -1) {
   99:             return 0;
  100:         }
  101: 
  102:         offset += len;
  103:     }
  104: 
  105:     return offset;
  106: }
  107: 
  108: int tcp_socket_outgoing(const char *address, uint16_t port)
  109: {
  110:     int s;
  111:     struct in_addr in;
  112:     struct sockaddr_in addr;
  113: 
  114:     s = socket(PF_INET, SOCK_STREAM, 0);
  115:     if (s == -1) {
  116:         return -1;
  117:     }
  118: 
  119:     if (inet_aton(address, &in) == 0) {
  120:         struct hostent *ent;
  121: 
  122:         ent = gethostbyname(address);
  123:         if (ent == NULL) {
  124:             goto error;
  125:         }
  126: 
  127:         memcpy(&in, ent->h_addr, sizeof(in));
  128:     }
  129: 
  130:     addr.sin_family = AF_INET;
  131:     addr.sin_port = htons(port);
  132:     memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
  133: 
  134:     if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  135:         goto error;
  136:     }
  137: 
  138:     return s;
  139: error:
  140:     closesocket(s);
  141:     return -1;
  142: }
  143: 
  144: int tcp_socket_incoming(const char *address, uint16_t port)
  145: {
  146:     int s;
  147:     struct in_addr in;
  148:     struct sockaddr_in addr;
  149:     int opt;
  150: 
  151:     s = socket(PF_INET, SOCK_STREAM, 0);
  152:     if (s == -1) {
  153:         return -1;
  154:     }
  155: 
  156:     if (inet_aton(address, &in) == 0) {
  157:         struct hostent *ent;
  158: 
  159:         ent = gethostbyname(address);
  160:         if (ent == NULL) {
  161:             goto error;
  162:         }
  163: 
  164:         memcpy(&in, ent->h_addr, sizeof(in));
  165:     }
  166: 
  167:     addr.sin_family = AF_INET;
  168:     addr.sin_port = htons(port);
  169:     memcpy(&addr.sin_addr.s_addr, &in, sizeof(in));
  170: 
  171:     opt = 1;
  172:     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &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 %llu block(s)",
  357: 	      (unsigned long long)(size / blocksize));
  358: 
  359: 	if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
  360: 		int serrno = errno;
  361: 		LOG("Failed setting size (in blocks)");
  362: 		errno = serrno;
  363: 		return -1;
  364: 	}
  365: 
  366: 	TRACE("Clearing NBD socket");
  367: 
  368: 	if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
  369: 		int serrno = errno;
  370: 		LOG("Failed clearing NBD socket");
  371: 		errno = serrno;
  372: 		return -1;
  373: 	}
  374: 
  375: 	TRACE("Setting NBD socket");
  376: 
  377: 	if (ioctl(fd, NBD_SET_SOCK, csock) == -1) {
  378: 		int serrno = errno;
  379: 		LOG("Failed to set NBD socket");
  380: 		errno = serrno;
  381: 		return -1;
  382: 	}
  383: 
  384: 	TRACE("Negotiation ended");
  385: 
  386: 	return 0;
  387: }
  388: 
  389: int nbd_disconnect(int fd)
  390: {
  391: 	ioctl(fd, NBD_CLEAR_QUE);
  392: 	ioctl(fd, NBD_DISCONNECT);
  393: 	ioctl(fd, NBD_CLEAR_SOCK);
  394: 	return 0;
  395: }
  396: 
  397: int nbd_client(int fd, int csock)
  398: {
  399: 	int ret;
  400: 	int serrno;
  401: 
  402: 	TRACE("Doing NBD loop");
  403: 
  404: 	ret = ioctl(fd, NBD_DO_IT);
  405: 	serrno = errno;
  406: 
  407: 	TRACE("NBD loop returned %d: %s", ret, strerror(serrno));
  408: 
  409: 	TRACE("Clearing NBD queue");
  410: 	ioctl(fd, NBD_CLEAR_QUE);
  411: 
  412: 	TRACE("Clearing NBD socket");
  413: 	ioctl(fd, NBD_CLEAR_SOCK);
  414: 
  415: 	errno = serrno;
  416: 	return ret;
  417: }
  418: #else
  419: int nbd_init(int fd, int csock, off_t size, size_t blocksize)
  420: {
  421:     errno = ENOTSUP;
  422:     return -1;
  423: }
  424: 
  425: int nbd_disconnect(int fd)
  426: {
  427:     errno = ENOTSUP;
  428:     return -1;
  429: }
  430: 
  431: int nbd_client(int fd, int csock)
  432: {
  433:     errno = ENOTSUP;
  434:     return -1;
  435: }
  436: #endif
  437: 
  438: int nbd_send_request(int csock, struct nbd_request *request)
  439: {
  440: 	uint8_t buf[4 + 4 + 8 + 8 + 4];
  441: 
  442: 	cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
  443: 	cpu_to_be32w((uint32_t*)(buf + 4), request->type);
  444: 	cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
  445: 	cpu_to_be64w((uint64_t*)(buf + 16), request->from);
  446: 	cpu_to_be32w((uint32_t*)(buf + 24), request->len);
  447: 
  448: 	TRACE("Sending request to client");
  449: 
  450: 	if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
  451: 		LOG("writing to socket failed");
  452: 		errno = EINVAL;
  453: 		return -1;
  454: 	}
  455: 	return 0;
  456: }
  457: 
  458: 
  459: static int nbd_receive_request(int csock, struct nbd_request *request)
  460: {
  461: 	uint8_t buf[4 + 4 + 8 + 8 + 4];
  462: 	uint32_t magic;
  463: 
  464: 	if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
  465: 		LOG("read failed");
  466: 		errno = EINVAL;
  467: 		return -1;
  468: 	}
  469: 
  470: 	/* Request
  471: 	   [ 0 ..  3]   magic   (NBD_REQUEST_MAGIC)
  472: 	   [ 4 ..  7]   type    (0 == READ, 1 == WRITE)
  473: 	   [ 8 .. 15]   handle
  474: 	   [16 .. 23]   from
  475: 	   [24 .. 27]   len
  476: 	 */
  477: 
  478: 	magic = be32_to_cpup((uint32_t*)buf);
  479: 	request->type  = be32_to_cpup((uint32_t*)(buf + 4));
  480: 	request->handle = be64_to_cpup((uint64_t*)(buf + 8));
  481: 	request->from  = be64_to_cpup((uint64_t*)(buf + 16));
  482: 	request->len   = be32_to_cpup((uint32_t*)(buf + 24));
  483: 
  484: 	TRACE("Got request: "
  485: 	      "{ magic = 0x%x, .type = %d, from = %" PRIu64" , len = %u }",
  486: 	      magic, request->type, request->from, request->len);
  487: 
  488: 	if (magic != NBD_REQUEST_MAGIC) {
  489: 		LOG("invalid magic (got 0x%x)", magic);
  490: 		errno = EINVAL;
  491: 		return -1;
  492: 	}
  493: 	return 0;
  494: }
  495: 
  496: int nbd_receive_reply(int csock, struct nbd_reply *reply)
  497: {
  498: 	uint8_t buf[4 + 4 + 8];
  499: 	uint32_t magic;
  500: 
  501: 	memset(buf, 0xAA, sizeof(buf));
  502: 
  503: 	if (read_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
  504: 		LOG("read failed");
  505: 		errno = EINVAL;
  506: 		return -1;
  507: 	}
  508: 
  509: 	/* Reply
  510: 	   [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
  511: 	   [ 4 ..  7]    error   (0 == no error)
  512: 	   [ 7 .. 15]    handle
  513: 	 */
  514: 
  515: 	magic = be32_to_cpup((uint32_t*)buf);
  516: 	reply->error  = be32_to_cpup((uint32_t*)(buf + 4));
  517: 	reply->handle = be64_to_cpup((uint64_t*)(buf + 8));
  518: 
  519: 	TRACE("Got reply: "
  520: 	      "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }",
  521: 	      magic, reply->error, reply->handle);
  522: 
  523: 	if (magic != NBD_REPLY_MAGIC) {
  524: 		LOG("invalid magic (got 0x%x)", magic);
  525: 		errno = EINVAL;
  526: 		return -1;
  527: 	}
  528: 	return 0;
  529: }
  530: 
  531: static int nbd_send_reply(int csock, struct nbd_reply *reply)
  532: {
  533: 	uint8_t buf[4 + 4 + 8];
  534: 
  535: 	/* Reply
  536: 	   [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
  537: 	   [ 4 ..  7]    error   (0 == no error)
  538: 	   [ 7 .. 15]    handle
  539: 	 */
  540: 	cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
  541: 	cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
  542: 	cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);
  543: 
  544: 	TRACE("Sending response to client");
  545: 
  546: 	if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
  547: 		LOG("writing to socket failed");
  548: 		errno = EINVAL;
  549: 		return -1;
  550: 	}
  551: 	return 0;
  552: }
  553: 
  554: int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
  555:              off_t *offset, bool readonly, uint8_t *data, int data_size)
  556: {
  557: 	struct nbd_request request;
  558: 	struct nbd_reply reply;
  559: 
  560: 	TRACE("Reading request.");
  561: 
  562: 	if (nbd_receive_request(csock, &request) == -1)
  563: 		return -1;
  564: 
  565: 	if (request.len > data_size) {
  566: 		LOG("len (%u) is larger than max len (%u)",
  567: 		    request.len, data_size);
  568: 		errno = EINVAL;
  569: 		return -1;
  570: 	}
  571: 
  572: 	if ((request.from + request.len) < request.from) {
  573: 		LOG("integer overflow detected! "
  574: 		    "you're probably being attacked");
  575: 		errno = EINVAL;
  576: 		return -1;
  577: 	}
  578: 
  579: 	if ((request.from + request.len) > size) {
  580: 	        LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
  581: 		    ", Offset: %" PRIu64 "\n",
  582: 		     request.from, request.len, size, dev_offset);
  583: 		LOG("requested operation past EOF--bad client?");
  584: 		errno = EINVAL;
  585: 		return -1;
  586: 	}
  587: 
  588: 	TRACE("Decoding type");
  589: 
  590: 	reply.handle = request.handle;
  591: 	reply.error = 0;
  592: 
  593: 	switch (request.type) {
  594: 	case NBD_CMD_READ:
  595: 		TRACE("Request type is READ");
  596: 
  597: 		if (bdrv_read(bs, (request.from + dev_offset) / 512, data,
  598: 			      request.len / 512) == -1) {
  599: 			LOG("reading from file failed");
  600: 			errno = EINVAL;
  601: 			return -1;
  602: 		}
  603: 		*offset += request.len;
  604: 
  605: 		TRACE("Read %u byte(s)", request.len);
  606: 
  607: 		if (nbd_send_reply(csock, &reply) == -1)
  608: 			return -1;
  609: 
  610: 		TRACE("Sending data to client");
  611: 
  612: 		if (write_sync(csock, data, request.len) != request.len) {
  613: 			LOG("writing to socket failed");
  614: 			errno = EINVAL;
  615: 			return -1;
  616: 		}
  617: 		break;
  618: 	case NBD_CMD_WRITE:
  619: 		TRACE("Request type is WRITE");
  620: 
  621: 		TRACE("Reading %u byte(s)", request.len);
  622: 
  623: 		if (read_sync(csock, data, request.len) != request.len) {
  624: 			LOG("reading from socket failed");
  625: 			errno = EINVAL;
  626: 			return -1;
  627: 		}
  628: 
  629: 		if (readonly) {
  630: 			TRACE("Server is read-only, return error");
  631: 			reply.error = 1;
  632: 		} else {
  633: 			TRACE("Writing to device");
  634: 
  635: 			if (bdrv_write(bs, (request.from + dev_offset) / 512,
  636: 				       data, request.len / 512) == -1) {
  637: 				LOG("writing to file failed");
  638: 				errno = EINVAL;
  639: 				return -1;
  640: 			}
  641: 
  642: 			*offset += request.len;
  643: 		}
  644: 
  645: 		if (nbd_send_reply(csock, &reply) == -1)
  646: 			return -1;
  647: 		break;
  648: 	case NBD_CMD_DISC:
  649: 		TRACE("Request type is DISCONNECT");
  650: 		errno = 0;
  651: 		return 1;
  652: 	default:
  653: 		LOG("invalid request type (%u) received", request.type);
  654: 		errno = EINVAL;
  655: 		return -1;
  656: 	}
  657: 
  658: 	TRACE("Request/Reply complete");
  659: 
  660: 	return 0;
  661: }

unix.superglobalmegacorp.com