Exemple #1
0
static int
iscsi_read_from_socket(struct iscsi_context *iscsi)
{
	struct iscsi_in_pdu *in;
	ssize_t data_size, count;

	if (iscsi->incoming == NULL) {
		iscsi->incoming = malloc(sizeof(struct iscsi_in_pdu));
		if (iscsi->incoming == NULL) {
			iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
			return -1;
		}
		memset(iscsi->incoming, 0, sizeof(struct iscsi_in_pdu));
	}
	in = iscsi->incoming;

	/* first we must read the header, including any digests */
	if (in->hdr_pos < ISCSI_HEADER_SIZE) {
		/* try to only read the header, the socket is nonblocking, so
		 * no need to limit the read to what is available in the socket
		 */
		count = ISCSI_HEADER_SIZE - in->hdr_pos;
		count = recv(iscsi->fd, &in->hdr[in->hdr_pos], count, 0);
		if (count == 0) {
			return -1;
		}
		if (count < 0) {
			if (errno == EINTR || errno == EAGAIN) {
				return 0;
			}
			iscsi_set_error(iscsi, "read from socket failed, "
				"errno:%d", errno);
			return -1;
		}
		in->hdr_pos  += count;
	}

	if (in->hdr_pos < ISCSI_HEADER_SIZE) {
		/* we dont have the full header yet, so return */
		return 0;
	}

	data_size = iscsi_get_pdu_data_size(&in->hdr[0]);
	if (data_size < 0 || data_size > iscsi->initiator_max_recv_data_segment_length) {
		iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size);
		return -1;
	}
	if (data_size != 0) {
		unsigned char *buf = NULL;

		count = data_size - in->data_pos;

		/* first try to see if we already have a user buffer */
		buf = iscsi_get_user_in_buffer(iscsi, in, in->data_pos, &count);
		/* if not, allocate one */
		if (buf == NULL) {
			if (in->data == NULL) {
				in->data = malloc(data_size);
				if (in->data == NULL) {
					iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
					return -1;
				}
			}
			buf = &in->data[in->data_pos];
		}

		count = recv(iscsi->fd, buf, count, 0);
		if (count == 0) {
			return -1;
		}
		if (count < 0) {
			if (errno == EINTR || errno == EAGAIN) {
				return 0;
			}
			iscsi_set_error(iscsi, "read from socket failed, "
				"errno:%d", errno);
			return -1;
		}
		in->data_pos += count;
	}

	if (in->data_pos < data_size) {
		return 0;
	}

	SLIST_ADD_END(&iscsi->inqueue, in);
	iscsi->incoming = NULL;


	while (iscsi->inqueue != NULL) {
		struct iscsi_in_pdu *current = iscsi->inqueue;

		if (iscsi_process_pdu(iscsi, current) != 0) {
			return -1;
		}
		SLIST_REMOVE(&iscsi->inqueue, current);
		iscsi_free_iscsi_in_pdu(current);
	}


	return 0;
}
Exemple #2
0
static int
iscsi_read_from_socket(struct iscsi_context *iscsi)
{
	struct iscsi_in_pdu *in;
	ssize_t data_size, count, padding_size;

	if (iscsi->incoming == NULL) {
		iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu));
		iscsi->incoming->hdr = iscsi_szmalloc(iscsi, ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE);
		if (iscsi->incoming == NULL) {
			iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
			return -1;
		}
	}
	in = iscsi->incoming;

	/* first we must read the header, including any digests */
	if (in->hdr_pos < ISCSI_HEADER_SIZE) {
		/* try to only read the header, the socket is nonblocking, so
		 * no need to limit the read to what is available in the socket
		 */
		count = ISCSI_HEADER_SIZE - in->hdr_pos;
		count = recv(iscsi->fd, &in->hdr[in->hdr_pos], count, 0);
		if (count == 0) {
			return -1;
		}
		if (count < 0) {
			if (errno == EINTR || errno == EAGAIN) {
				return 0;
			}
			iscsi_set_error(iscsi, "read from socket failed, "
				"errno:%d", errno);
			return -1;
		}
		in->hdr_pos  += count;
	}

	if (in->hdr_pos < ISCSI_HEADER_SIZE) {
		/* we don't have the full header yet, so return */
		return 0;
	}

	padding_size = iscsi_get_pdu_padding_size(&in->hdr[0]);
	data_size = iscsi_get_pdu_data_size(&in->hdr[0]) + padding_size;

	if (data_size < 0 || data_size > (ssize_t)iscsi->initiator_max_recv_data_segment_length) {
		iscsi_set_error(iscsi, "Invalid data size received from target (%d)", (int)data_size);
		return -1;
	}
	if (data_size != 0) {
		unsigned char padding_buf[3];
		unsigned char *buf = padding_buf;
		struct scsi_iovector * iovector_in;

		count = data_size - in->data_pos;

		/* first try to see if we already have a user buffer */
		iovector_in = iscsi_get_scsi_task_iovector_in(iscsi, in);
		if (iovector_in != NULL && count > padding_size) {
			uint32_t offset = scsi_get_uint32(&in->hdr[40]);
			count = iscsi_iovector_readv_writev(iscsi, iovector_in, in->data_pos + offset, count - padding_size, 0);
		} else {
			if (iovector_in == NULL) {
				if (in->data == NULL) {
					in->data = iscsi_malloc(iscsi, data_size);
					if (in->data == NULL) {
						iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu->data(%d)", (int)data_size);
						return -1;
					}
				}
				buf = &in->data[in->data_pos];
			}
			count = recv(iscsi->fd, buf, count, 0);
		}
		
		if (count == 0) {
			return -1;
		}
		if (count < 0) {
			if (errno == EINTR || errno == EAGAIN) {
				return 0;
			}
			iscsi_set_error(iscsi, "read from socket failed, "
					"errno:%d %s", errno,
					iscsi_get_error(iscsi));
			return -1;
		}

		in->data_pos += count;
	}

	if (in->data_pos < data_size) {
		return 0;
	}

	ISCSI_LIST_ADD_END(&iscsi->inqueue, in);
	iscsi->incoming = NULL;


	while (iscsi->inqueue != NULL) {
		struct iscsi_in_pdu *current = iscsi->inqueue;

		if (iscsi_process_pdu(iscsi, current) != 0) {
			return -1;
		}
		ISCSI_LIST_REMOVE(&iscsi->inqueue, current);
		iscsi_free_iscsi_in_pdu(iscsi, current);
	}


	return 0;
}
Exemple #3
0
static int iscsi_read_from_socket(struct iscsi_context *iscsi)
{
	int available;
	int size;
	unsigned char *buf;
	ssize_t count;

	if (ioctl(iscsi->fd, FIONREAD, &available) != 0) {
		printf("ioctl FIONREAD returned error : %d\n", errno);
		return -1;
	}
	if (available == 0) {
		printf("no data readable in socket, socket is closed\n");
		return -2;
	}
	size = iscsi->insize - iscsi->inpos + available;
	buf = malloc(size);
	if (buf == NULL) {
		printf("failed to allocate %d bytes for input buffer\n", size);
		return -3;
	}
	if (iscsi->insize > iscsi->inpos) {
		memcpy(buf, iscsi->inbuf + iscsi->inpos, iscsi->insize - iscsi->inpos);
		iscsi->insize -= iscsi->inpos;
		iscsi->inpos   = 0;
	}

	count = read(iscsi->fd, buf + iscsi->insize, available);
	if (count == -1) {
		if (errno == EINTR) {
			free(buf);
			buf = NULL;
			return 0;
		}
		printf("read from socket failed, errno:%d\n", errno);
		free(buf);
		buf = NULL;
		return -4;
	}

	if (iscsi->inbuf != NULL) {
		free(iscsi->inbuf);
	}
	iscsi->inbuf   = buf;
	iscsi->insize += count;

	while (1) {
		if (iscsi->insize - iscsi->inpos < 48) {
			return 0;
		}
		count = iscsi_get_pdu_size(iscsi->inbuf + iscsi->inpos);
		if (iscsi->insize + iscsi->inpos < count) {
			return 0;
		}
		if (iscsi_process_pdu(iscsi, iscsi->inbuf + iscsi->inpos, count) != 0) {
			printf("failed to process pdu\n");
			return -5;
		}
		iscsi->inpos += count;
		if (iscsi->inpos == iscsi->insize) {
			free(iscsi->inbuf);
			iscsi->inbuf = NULL;
			iscsi->insize = 0;
			iscsi->inpos = 0;
		}
		if (iscsi->inpos > iscsi->insize) {
			printf("inpos > insize. bug!\n");
			return -6;
		}
	}

	return 0;
}