From 965c7ff9a9d64bb53dd7a808f3193b36ab7b014d Mon Sep 17 00:00:00 2001 From: sr Date: Sat, 25 Aug 2012 16:14:20 +0200 Subject: [*] Fix bug in serializer_get_* [CLIENT/KERNEL] Change ioctl to handle volume names instead if vids [*] Make protocol endian safe [CLIENT] Display ioctl errorcode on failure --- src/client/client.c | 17 ++++++++++------- src/kernel/blk.c | 24 +++++++++++++++++++++--- src/kernel/core.c | 2 ++ src/kernel/net.c | 24 +++++++++++++++++------- src/serialize.c | 7 ++++--- src/server/net.c | 7 +++++-- src/server/server.c | 1 + src/types.h | 2 ++ 8 files changed, 62 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/client/client.c b/src/client/client.c index a48cab9..86b7cb9 100644 --- a/src/client/client.c +++ b/src/client/client.c @@ -123,7 +123,7 @@ int main(int argc, char *argv[]) break; case 'h': dnbd3_get_ip(optarg, msg.addr, &msg.addrtype); - printf("Host set to %s (type %d)\n", optarg, (int)msg.addrtype); + printf("Host set to %s (type %d)\n", inet_ntoa(*(struct in_addr*)msg.addr), (int)msg.addrtype); break; case 'i': msg.imgname = strdup(optarg); @@ -166,9 +166,10 @@ int main(int argc, char *argv[]) fd = open(dev, O_WRONLY); printf("INFO: Closing device %s\n", dev); - if (ioctl(fd, IOCTL_CLOSE, &msg) < 0) + const int ret = ioctl(fd, IOCTL_OPEN, &msg); + if (ret < 0) { - printf("ERROR: ioctl not successful (close)\n"); + printf("ERROR: ioctl not successful (close, errcode: %d)\n", ret); exit(EXIT_FAILURE); } @@ -199,9 +200,10 @@ int main(int argc, char *argv[]) fd = open(dev, O_WRONLY); printf("INFO: Connecting %s to %s (%s rid:%i)\n", dev, "", msg.imgname, msg.rid); - if (ioctl(fd, IOCTL_OPEN, &msg) < 0) + const int ret = ioctl(fd, IOCTL_OPEN, &msg); + if (ret < 0) { - printf("ERROR: ioctl not successful (connect)\n"); + printf("ERROR: ioctl not successful (connect, errcode: %d)\n", ret); exit(EXIT_FAILURE); } @@ -235,9 +237,10 @@ int main(int argc, char *argv[]) fd = open(dev, O_WRONLY); printf("INFO: Connecting %s to %s (%s rid:%i)\n", dev, "", msg.imgname, msg.rid); - if (ioctl(fd, IOCTL_OPEN, &msg) < 0) + const int ret = ioctl(fd, IOCTL_OPEN, &msg); + if (ret < 0) { - printf("ERROR: ioctl not successful (connect)\n"); + printf("ERROR: ioctl not successful (config file, errcode: %d)\n", ret); exit(EXIT_FAILURE); } diff --git a/src/kernel/blk.c b/src/kernel/blk.c index 1177f3a..b0b0912 100644 --- a/src/kernel/blk.c +++ b/src/kernel/blk.c @@ -123,12 +123,17 @@ int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u } copy_from_user(imgname, msg->imgname, msg->imgnamelen); imgname[msg->imgnamelen] = '\0'; + //printk("IOCTL Image name of len %d is %s\n", (int)msg->imgnamelen, imgname); } switch (cmd) { case IOCTL_OPEN: - if (imgname == NULL) + if (dev->imgname != NULL) + { + result = -EBUSY; + } + else if (imgname == NULL) { result = -EINVAL; } @@ -138,10 +143,18 @@ int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u dev->cur_server.port = msg->port; dev->cur_server.hostaddrtype = msg->addrtype; dev->imgname = imgname; - imgname = NULL; dev->rid = msg->rid; blk_queue->backing_dev_info.ra_pages = (msg->read_ahead_kb * 1024) / PAGE_CACHE_SIZE; - result = dnbd3_net_connect(dev); + if (dnbd3_net_connect(dev) == 0) + { + result = 0; + imgname = NULL; // Prevent kfree at the end + } + else + { + result = -ENOENT; + dev->imgname = NULL; + } } break; @@ -149,6 +162,11 @@ int dnbd3_blk_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, u set_capacity(dev->disk, 0); result = dnbd3_net_disconnect(dev); dnbd3_blk_fail_all_requests(dev); + if (dev->imgname) + { + kfree(dev->imgname); + dev->imgname = NULL; + } break; case IOCTL_SWITCH: diff --git a/src/kernel/core.c b/src/kernel/core.c index d87bccf..63d71d1 100644 --- a/src/kernel/core.c +++ b/src/kernel/core.c @@ -40,6 +40,8 @@ static int __init dnbd3_init(void) return -EIO; } + printk("DNBD3 kernel module loaded. Machine type: " ENDIAN_MODE "\n"); + // add MAX_NUMBER_DEVICES devices for (i = 0; i < max_devs; i++) { diff --git a/src/kernel/net.c b/src/kernel/net.c index 4d33842..41f3e5f 100644 --- a/src/kernel/net.c +++ b/src/kernel/net.c @@ -87,7 +87,7 @@ int dnbd3_net_connect(dnbd3_device_t *dev) sin.sin_family = AF_INET; memcpy(&(sin.sin_addr.s_addr), dev->cur_server.hostaddr, 4); sin.sin_port = dev->cur_server.port; - if (kernel_connect(dev->sock, (struct sockaddr *) &sin, sizeof(sin), 0) < 0) + if (kernel_connect(dev->sock, (struct sockaddr *) &sin, sizeof(sin), 0) != 0) { printk("ERROR: Couldn't connect to host %pI4 : %d\n", dev->cur_server.hostaddr, (int)ntohs(dev->cur_server.port)); goto error; @@ -105,14 +105,23 @@ int dnbd3_net_connect(dnbd3_device_t *dev) serializer_put_uint16(&dev->payload_buffer, dev->rid); iov[1].iov_base = &dev->payload_buffer; iov[1].iov_len = serializer_get_written_length(&dev->payload_buffer); - if (kernel_sendmsg(dev->sock, &msg, iov, 2, sizeof(dnbd3_request) + iov[1].iov_len) <= 0) + if (kernel_sendmsg(dev->sock, &msg, iov, 2, sizeof(dnbd3_request) + iov[1].iov_len) != sizeof(dnbd3_request) + iov[1].iov_len) + { + printk("ERROR: Couldn't send CMD_SIZE_REQUEST to %pI4 : %d\n", dev->cur_server.hostaddr, (int)ntohs(dev->cur_server.port)); goto error; + } // receive reply header iov[0].iov_base = &dnbd3_reply; iov[0].iov_len = sizeof(dnbd3_reply); - if (kernel_recvmsg(dev->sock, &msg, iov, 1, sizeof(dnbd3_reply), msg.msg_flags) != sizeof(dnbd3_reply) || dnbd3_reply.cmd != CMD_GET_SIZE || dnbd3_reply.size < 3 || dnbd3_reply.size > MAX_PAYLOAD || dnbd3_reply.magic != dnbd3_packet_magic) + if (kernel_recvmsg(dev->sock, &msg, iov, 1, sizeof(dnbd3_reply), msg.msg_flags) != sizeof(dnbd3_reply)) + { + printk("FATAL: Received corrupted reply header after CMD_SIZE_REQUEST.\n"); + goto error; + } + fixup_reply(dnbd3_reply); + if (dnbd3_reply.cmd != CMD_GET_SIZE || dnbd3_reply.size < 3 || dnbd3_reply.size > MAX_PAYLOAD || dnbd3_reply.magic != dnbd3_packet_magic) { - printk("FATAL: Requested image does not exist on server.\n"); + printk("FATAL: Received invalid reply to CMD_SIZE_REQUEST, image doesn't exist on server.\n"); goto error; } // receive reply payload @@ -123,6 +132,7 @@ int dnbd3_net_connect(dnbd3_device_t *dev) printk("FATAL: Cold not read CMD_GET_SIZE payload on handshake.\n"); goto error; } + serializer_reset_read(&dev->payload_buffer, dnbd3_reply.size); // read reply payload dev->cur_server.protocol_version = serializer_get_uint16(&dev->payload_buffer); if (dev->cur_server.protocol_version < MIN_SUPPORTED_SERVER) @@ -393,7 +403,6 @@ int dnbd3_net_discover(void *data) // Request filesize dnbd3_request.cmd = CMD_GET_SIZE; - dnbd3_request.size = strlen(dev->imgname) + 1 + 2 + 2; // str+\0, version, rid fixup_request(dnbd3_request); iov[0].iov_base = &dnbd3_request; iov[0].iov_len = sizeof(dnbd3_request); @@ -402,7 +411,7 @@ int dnbd3_net_discover(void *data) serializer_put_string(payload, dev->imgname); serializer_put_uint16(payload, dev->rid); iov[1].iov_base = payload; - iov[1].iov_len = serializer_get_written_length(payload); + dnbd3_request.size = iov[1].iov_len = serializer_get_written_length(payload); if (kernel_sendmsg(sock, &msg, iov, 2, sizeof(dnbd3_request) + iov[1].iov_len) != sizeof(dnbd3_request) + iov[1].iov_len) { printk("ERROR: Requesting image size failed (%pI4 : %d, discover)\n", dev->alt_servers[i].hostaddr, (int)ntohs(dev->alt_servers[i].port)); @@ -481,7 +490,8 @@ int dnbd3_net_discover(void *data) return 0; } - do_gettimeofday(&start); // start rtt measurement + // start rtt measurement + do_gettimeofday(&start); // Request block dnbd3_request.cmd = CMD_GET_BLOCK; diff --git a/src/serialize.c b/src/serialize.c index 7961cfe..fa1e878 100644 --- a/src/serialize.c +++ b/src/serialize.c @@ -22,7 +22,7 @@ uint16_t serializer_get_uint16(serialized_buffer_t *buffer) uint16_t ret; if (buffer->buffer_pointer + 2 > buffer->buffer_end) return 0; memcpy(&ret, buffer->buffer_pointer, 2); - *buffer->buffer_pointer += 2; + buffer->buffer_pointer += 2; return net_order_16(ret); } @@ -31,13 +31,14 @@ uint64_t serializer_get_uint64(serialized_buffer_t *buffer) uint64_t ret; if (buffer->buffer_pointer + 8 > buffer->buffer_end) return 0; memcpy(&ret, buffer->buffer_pointer, 8); - *buffer->buffer_pointer += 8; + buffer->buffer_pointer += 8; return net_order_64(ret); } char* serializer_get_string(serialized_buffer_t *buffer) { char *ptr = buffer->buffer_pointer, *start = buffer->buffer_pointer; + if (ptr >= buffer->buffer_end) return NULL; while (ptr < buffer->buffer_end && *ptr) ++ptr; if (*ptr) return NULL; // String did not terminate within buffer (possibly corrupted/malicious packet) buffer->buffer_pointer = ptr + 1; @@ -62,7 +63,7 @@ void serializer_put_uint64(serialized_buffer_t *buffer, uint64_t value) void serializer_put_string(serialized_buffer_t *buffer, char *value) { - size_t len = strlen(value) + 1; + const size_t len = strlen(value) + 1; if (buffer->buffer_pointer + len > buffer->buffer_end) return; memcpy(buffer->buffer_pointer, value, len); buffer->buffer_pointer += len; diff --git a/src/server/net.c b/src/server/net.c index 9ae168a..bf680a3 100644 --- a/src/server/net.c +++ b/src/server/net.c @@ -42,7 +42,7 @@ static char recv_request_header(int sock, dnbd3_request_t *request) { // Read request heade from socket - if (recv(sock, request, sizeof(dnbd3_request_t), MSG_WAITALL) != sizeof(dnbd3_request_t)) + if (recv(sock, request, sizeof(*request), MSG_WAITALL) != sizeof(*request)) { printf("[DEBUG] Error receiving request: Could not read message header\n"); return 0; @@ -152,6 +152,7 @@ void *dnbd3_handle_query(void *dnbd3_client) } else { + printf("Payload len: %d\n", (int)request.size); if (recv_request_payload(client->sock, request.size, &payload)) { client_version = serializer_get_uint16(&payload); @@ -174,7 +175,7 @@ void *dnbd3_handle_query(void *dnbd3_client) image = dnbd3_get_image(image_name, rid, 0); if (!image) { - printf("[DEBUG] Client requested non-existent image '%s'\n", image_name); + printf("[DEBUG] Client requested non-existent image '%s' (rid:%d, protocol:%d)\n", image_name, (int)rid, (int)client_version); } else { @@ -384,6 +385,8 @@ int dnbd3_setup_socket() memlogf("ERROR: Socket setup failure\n"); return -1; } + const int opt = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; // IPv4 diff --git a/src/server/server.c b/src/server/server.c index 0a206d1..b2a36a5 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -173,6 +173,7 @@ int main(int argc, char* argv[]) pthread_spin_init(&_spinlock, PTHREAD_PROCESS_PRIVATE); initmemlog(); + memlogf("DNBD3 server starting.... Machine type: " ENDIAN_MODE); // load config file dnbd3_load_config(_config_file_name); diff --git a/src/types.h b/src/types.h index 5332dc4..6ba7629 100644 --- a/src/types.h +++ b/src/types.h @@ -44,6 +44,7 @@ const uint16_t dnbd3_packet_magic = (0x73 << 8) | (0x72); (a).cmd = net_order_16((a).cmd); \ (a).size = net_order_32((a).size); \ } while (0) +#define ENDIAN_MODE "Big Endian" #elif defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) static const uint16_t dnbd3_packet_magic = (0x73) | (0x72 << 8); // Make little endian our network byte order as probably 99.999% of machines this will be used on are LE @@ -52,6 +53,7 @@ static const uint16_t dnbd3_packet_magic = (0x73) | (0x72 << 8); #define net_order_16(a) (a) #define fixup_request(a) while(0) #define fixup_reply(a) while(0) +#define ENDIAN_MODE "Little Endian" #else #error "Unknown Endianness" #endif -- cgit v1.2.3-55-g7522