コード例 #1
0
ファイル: nbd.c プロジェクト: EgoIncarnate/qemu-rr
int nbd_negotiate(int csock, off_t size)
{
	char buf[8 + 8 + 8 + 128];

	/* Negotiate
	   [ 0 ..   7]   passwd   ("NBDMAGIC")
	   [ 8 ..  15]   magic    (0x00420281861253)
	   [16 ..  23]   size
	   [24 .. 151]   reserved (0)
	 */

	TRACE("Beginning negotiation.");
	memcpy(buf, "NBDMAGIC", 8);
	cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
	cpu_to_be64w((uint64_t*)(buf + 16), size);
	memset(buf + 24, 0, 128);

	if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
		LOG("write failed");
		errno = EINVAL;
		return -1;
	}

	TRACE("Negotation succeeded.");

	return 0;
}
コード例 #2
0
ファイル: nbd.c プロジェクト: marsleezm/qemu
ssize_t nbd_send_request(int csock, struct nbd_request *request)
{
    uint8_t buf[4 + 4 + 8 + 8 + 4];
    ssize_t ret;

    cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
    cpu_to_be32w((uint32_t*)(buf + 4), request->type);
    cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
    cpu_to_be64w((uint64_t*)(buf + 16), request->from);
    cpu_to_be32w((uint32_t*)(buf + 24), request->len);

    TRACE("Sending request to client: "
          "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
          request->from, request->len, request->handle, request->type);

    ret = write_sync(csock, buf, sizeof(buf));
    if (ret < 0) {
        return ret;
    }

    if (ret != sizeof(buf)) {
        LOG("writing to socket failed");
        return -EINVAL;
    }
    return 0;
}
コード例 #3
0
ファイル: nbd.c プロジェクト: marsleezm/qemu
static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply)
{
    uint8_t buf[4 + 4 + 8];
    ssize_t ret;

    /* Reply
       [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
       [ 4 ..  7]    error   (0 == no error)
       [ 7 .. 15]    handle
     */
    cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC);
    cpu_to_be32w((uint32_t*)(buf + 4), reply->error);
    cpu_to_be64w((uint64_t*)(buf + 8), reply->handle);

    TRACE("Sending response to client");

    ret = write_sync(csock, buf, sizeof(buf));
    if (ret < 0) {
        return ret;
    }

    if (ret != sizeof(buf)) {
        LOG("writing to socket failed");
        return -EINVAL;
    }
    return 0;
}
コード例 #4
0
ファイル: nbd.c プロジェクト: EgoIncarnate/qemu-rr
int nbd_send_request(int csock, struct nbd_request *request)
{
	uint8_t buf[4 + 4 + 8 + 8 + 4];

	cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
	cpu_to_be32w((uint32_t*)(buf + 4), request->type);
	cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
	cpu_to_be64w((uint64_t*)(buf + 16), request->from);
	cpu_to_be32w((uint32_t*)(buf + 24), request->len);

	TRACE("Sending request to client");

	if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
		LOG("writing to socket failed");
		errno = EINVAL;
		return -1;
	}
	return 0;
}
コード例 #5
0
ファイル: nbd.c プロジェクト: marsleezm/qemu
static int nbd_send_negotiate(int csock, off_t size, uint32_t flags)
{
    char buf[8 + 8 + 8 + 128];
    int rc;

    /* Negotiate
        [ 0 ..   7]   passwd   ("NBDMAGIC")
        [ 8 ..  15]   magic    (0x00420281861253)
        [16 ..  23]   size
        [24 ..  27]   flags
        [28 .. 151]   reserved (0)
     */

    socket_set_block(csock);
    rc = -EINVAL;

    TRACE("Beginning negotiation.");
    memcpy(buf, "NBDMAGIC", 8);
    cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
    cpu_to_be64w((uint64_t*)(buf + 16), size);
    cpu_to_be32w((uint32_t*)(buf + 24),
                 flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM |
                 NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA);
    memset(buf + 28, 0, 124);

    if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
        LOG("write failed");
        goto fail;
    }

    TRACE("Negotiation succeeded.");
    rc = 0;
fail:
    socket_set_nonblock(csock);
    return rc;
}
コード例 #6
0
ファイル: nbd.c プロジェクト: 16aug/nvmeqemu
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
             off_t *offset, bool readonly, uint8_t *data, int data_size)
{
    struct nbd_request request;
    struct nbd_reply reply;

    TRACE("Reading request.");

    if (nbd_receive_request(csock, &request) == -1)
        return -1;

    if (request.len + NBD_REPLY_SIZE > data_size) {
        LOG("len (%u) is larger than max len (%u)",
            request.len + NBD_REPLY_SIZE, data_size);
        errno = EINVAL;
        return -1;
    }

    if ((request.from + request.len) < request.from) {
        LOG("integer overflow detected! "
            "you're probably being attacked");
        errno = EINVAL;
        return -1;
    }

    if ((request.from + request.len) > size) {
            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
            ", Offset: %" PRIu64 "\n",
                    request.from, request.len, (uint64_t)size, dev_offset);
        LOG("requested operation past EOF--bad client?");
        errno = EINVAL;
        return -1;
    }

    TRACE("Decoding type");

    reply.handle = request.handle;
    reply.error = 0;

    switch (request.type) {
    case NBD_CMD_READ:
        TRACE("Request type is READ");

        if (bdrv_read(bs, (request.from + dev_offset) / 512,
                  data + NBD_REPLY_SIZE,
                  request.len / 512) == -1) {
            LOG("reading from file failed");
            errno = EINVAL;
            return -1;
        }
        *offset += request.len;

        TRACE("Read %u byte(s)", request.len);

        /* Reply
           [ 0 ..  3]    magic   (NBD_REPLY_MAGIC)
           [ 4 ..  7]    error   (0 == no error)
           [ 7 .. 15]    handle
         */

        cpu_to_be32w((uint32_t*)data, NBD_REPLY_MAGIC);
        cpu_to_be32w((uint32_t*)(data + 4), reply.error);
        cpu_to_be64w((uint64_t*)(data + 8), reply.handle);

        TRACE("Sending data to client");

        if (write_sync(csock, data,
                   request.len + NBD_REPLY_SIZE) !=
                   request.len + NBD_REPLY_SIZE) {
            LOG("writing to socket failed");
            errno = EINVAL;
            return -1;
        }
        break;
    case NBD_CMD_WRITE:
        TRACE("Request type is WRITE");

        TRACE("Reading %u byte(s)", request.len);

        if (read_sync(csock, data, request.len) != request.len) {
            LOG("reading from socket failed");
            errno = EINVAL;
            return -1;
        }

        if (readonly) {
            TRACE("Server is read-only, return error");
            reply.error = 1;
        } else {
            TRACE("Writing to device");

            if (bdrv_write(bs, (request.from + dev_offset) / 512,
                       data, request.len / 512) == -1) {
                LOG("writing to file failed");
                errno = EINVAL;
                return -1;
            }

            *offset += request.len;
        }

        if (nbd_send_reply(csock, &reply) == -1)
            return -1;
        break;
    case NBD_CMD_DISC:
        TRACE("Request type is DISCONNECT");
        errno = 0;
        return 1;
    default:
        LOG("invalid request type (%u) received", request.type);
        errno = EINVAL;
        return -1;
    }

    TRACE("Request/Reply complete");

    return 0;
}