Exemple #1
0
void
iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
{
	if (pdu == NULL) {
		iscsi_set_error(iscsi, "trying to free NULL pdu");
		return;
	}

	if (pdu->outdata.size <= iscsi->smalloc_size) {
		iscsi_sfree(iscsi, pdu->outdata.data);
	} else {
		iscsi_free(iscsi, pdu->outdata.data);
	}
	pdu->outdata.data = NULL;

	if (pdu->indata.size <= iscsi->smalloc_size) {
		iscsi_sfree(iscsi, pdu->indata.data);
	} else {
		iscsi_free(iscsi, pdu->indata.data);
	}
	pdu->indata.data = NULL;

	if (iscsi->outqueue_current == pdu) {
		iscsi->outqueue_current = NULL;
	}

	iscsi_sfree(iscsi, pdu);
}
Exemple #2
0
void iscsi_sfree(struct iscsi_context *iscsi, void* ptr) {
	if (ptr == NULL) {
		return;
	}
	if (!iscsi->cache_allocations) {
		iscsi_free(iscsi, ptr);
	} else if (iscsi->smalloc_free == SMALL_ALLOC_MAX_FREE) {
		/* SMALL_ALLOC_MAX_FREE should be adjusted that this */
		/* happens rarely */
		ISCSI_LOG(iscsi, 6, "smalloc free == SMALLOC_MAX_FREE");
		iscsi_free(iscsi, ptr);
	} else {
		iscsi->smalloc_ptrs[iscsi->smalloc_free++] = ptr;
	}
}
Exemple #3
0
static void
iscsi_free_discovery_addresses(struct iscsi_context *iscsi, struct iscsi_discovery_address *addresses)
{
	while (addresses != NULL) {
		struct iscsi_discovery_address *next = addresses->next;

		iscsi_free(iscsi, discard_const(addresses->target_name));
		addresses->target_name = NULL;

		iscsi_free(iscsi, discard_const(addresses->target_address));
		addresses->target_address = NULL;

		addresses->next = NULL;
		iscsi_free(iscsi, addresses);
		addresses = next;
	}
}
Exemple #4
0
int iscsi_init_transport(struct iscsi_context *iscsi,
			 enum iscsi_transport_type transport) {
	struct tcp_transport *tcp_transport;
#ifdef HAVE_LINUX_ISER
	struct iser_transport *iser_transport;
#endif

	if (iscsi->t) {
		iscsi_free(iscsi, iscsi->t);
		iscsi->t = NULL;
	}
	iscsi->transport = transport;

	switch (iscsi->transport) {
	case TCP_TRANSPORT:
		tcp_transport = iscsi_malloc(iscsi, sizeof(struct tcp_transport));
		if (tcp_transport == NULL) {
			iscsi_set_error(iscsi, "Couldn't allocate memory for transport\n");
			return -1;
		}
		iscsi->t = &tcp_transport->t;
		iscsi_init_tcp_transport(iscsi);
		break;
#ifdef HAVE_LINUX_ISER
	case ISER_TRANSPORT:
		iser_transport = iscsi_malloc(iscsi, sizeof(struct iser_transport));
		if (iser_transport == NULL) {
			iscsi_set_error(iscsi, "Couldn't allocate memory for transport\n");
			return -1;
		}
		iscsi->t = &iser_transport->t;
		iscsi_init_iser_transport(iscsi);
		break;
#endif
	default:
		iscsi_set_error(iscsi, "Unfamiliar transport type");
		return -1;
	}

	return 0;
}
Exemple #5
0
struct iscsi_pdu *
iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
		   enum iscsi_opcode response_opcode, uint32_t itt,
		   uint32_t flags)
{
	struct iscsi_pdu *pdu;

	pdu = iscsi_szmalloc(iscsi, sizeof(struct iscsi_pdu));
	if (pdu == NULL) {
		iscsi_set_error(iscsi, "failed to allocate pdu");
		return NULL;
	}

	pdu->outdata.size = ISCSI_HEADER_SIZE;
	pdu->outdata.data = iscsi_szmalloc(iscsi, pdu->outdata.size);

	if (pdu->outdata.data == NULL) {
		iscsi_set_error(iscsi, "failed to allocate pdu header");
		iscsi_free(iscsi, pdu);
		return NULL;
	}

	/* opcode */
	pdu->outdata.data[0] = opcode;
	pdu->response_opcode = response_opcode;

	/* isid */
	if (opcode == ISCSI_PDU_LOGIN_REQUEST) {
		memcpy(&pdu->outdata.data[8], &iscsi->isid[0], 6);
	}

	/* itt */
	iscsi_pdu_set_itt(pdu, itt);
	pdu->itt = itt;

	/* flags */
	pdu->flags = flags;

	return pdu;
}
Exemple #6
0
int
iscsi_process_text_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
			 struct iscsi_in_pdu *in)
{
	struct iscsi_discovery_address *targets = NULL;
	unsigned char *ptr = in->data;
	int size = in->data_pos;

	/* verify the response looks sane */
	if (in->hdr[1] != ISCSI_PDU_TEXT_FINAL) {
		iscsi_set_error(iscsi, "unsupported flags in text "
				"reply %02x", in->hdr[1]);
		if (pdu->callback) {
			pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
			              pdu->private_data);
		}
		return -1;
	}

	while (size > 0) {
		unsigned char *end;
		int len;

		end = memchr(ptr, 0, size);
		if (end == NULL) {
			iscsi_set_error(iscsi, "NUL not found after offset %ld "
					"when parsing discovery data",
					(long)(ptr - in->data));
			if (pdu->callback) {
				pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
				              pdu->private_data);
			}
			iscsi_free_discovery_addresses(iscsi, targets);
			return -1;
		}

		len = end - ptr;
		if (len == 0) {
			break;
		}

		/* parse the strings */
		if (!strncmp((char *)ptr, "TargetName=", 11)) {
			struct iscsi_discovery_address *target;

			target = iscsi_zmalloc(iscsi, sizeof(struct iscsi_discovery_address));
			if (target == NULL) {
				iscsi_set_error(iscsi, "Failed to allocate "
						"data for new discovered "
						"target");
				if (pdu->callback) {
					pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
					              pdu->private_data);
				}
				iscsi_free_discovery_addresses(iscsi, targets);
				return -1;
			}
			target->target_name = iscsi_strdup(iscsi,(char *)ptr+11);
			if (target->target_name == NULL) {
				iscsi_set_error(iscsi, "Failed to allocate "
						"data for new discovered "
						"target name");
				if (pdu->callback) {
					pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
					              pdu->private_data);
				}
				iscsi_free(iscsi, target);
				target = NULL;
				iscsi_free_discovery_addresses(iscsi, targets);
				return -1;
			}
			target->next = targets;
			targets = target;
		} else if (!strncmp((char *)ptr, "TargetAddress=", 14)) {
			struct iscsi_target_portal *portal;

			if (targets == NULL) {
				iscsi_set_error(iscsi, "Invalid discovery "
						"reply");
				if (pdu->callback) {
					pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
					              pdu->private_data);
				}
				iscsi_free_discovery_addresses(iscsi, targets);
				return -1;
			}
			portal = iscsi_zmalloc(iscsi, sizeof(struct iscsi_target_portal));
			if (portal == NULL) {
				iscsi_set_error(iscsi, "Failed to malloc "
						"portal structure");
				if (pdu->callback) {
					pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
					              pdu->private_data);
				}
				iscsi_free_discovery_addresses(iscsi, targets);
				return -1;
			}

			portal->next = targets->portals;
			targets->portals = portal;

			portal->portal = iscsi_strdup(iscsi, (char *)ptr+14);
			if (portal->portal == NULL) {
				iscsi_set_error(iscsi, "Failed to allocate "
						"data for new discovered "
						"target address");
				if (pdu->callback) {
					pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
					              pdu->private_data);
				}
				iscsi_free_discovery_addresses(iscsi, targets);
				return -1;
			}
		} else {
			iscsi_set_error(iscsi, "Don't know how to handle "
					"discovery string : %s", ptr);
			if (pdu->callback) {
				pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
				              pdu->private_data);
			}
			iscsi_free_discovery_addresses(iscsi, targets);
			return -1;
		}

		ptr  += len + 1;
		size -= len + 1;
	}

	if (pdu->callback) {
		pdu->callback(iscsi, SCSI_STATUS_GOOD, targets, pdu->private_data);
	}
	iscsi_free_discovery_addresses(iscsi, targets);

	return 0;
}
Exemple #7
0
int
iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
		    iscsi_command_cb cb, void *private_data)
{
	int port = 3260;
	char *str;
	char *addr, *host;
	struct addrinfo *ai = NULL;
	union socket_address sa;
	int socksize;

	ISCSI_LOG(iscsi, 2, "connecting to portal %s",portal);

	if (iscsi->fd != -1) {
		iscsi_set_error(iscsi,
				"Trying to connect but already connected.");
		return -1;
	}

	addr = iscsi_strdup(iscsi, portal);
	if (addr == NULL) {
		iscsi_set_error(iscsi, "Out-of-memory: "
				"Failed to strdup portal address.");
		return -1;
	}
	host = addr;

	/* check if we have a target portal group tag */
	str = strrchr(host, ',');
	if (str != NULL) {
		str[0] = 0;
	}

	str = strrchr(host, ':');
	if (str != NULL) {
		if (strchr(str, ']') == NULL) {
			if (str != NULL) {
				port = atoi(str+1);
				str[0] = 0;
			}
		}
	}

	/* ipv6 in [...] form ? */
	if (host[0] == '[') {
		host ++;
		str = strchr(host, ']');
		if (str == NULL) {
			iscsi_free(iscsi, addr);
			iscsi_set_error(iscsi, "Invalid target:%s  "
				"Missing ']' in IPv6 address", portal);
			return -1;
		}
		*str = 0;
	}

	/* is it a hostname ? */
	if (getaddrinfo(host, NULL, NULL, &ai) != 0) {
		iscsi_free(iscsi, addr);
		iscsi_set_error(iscsi, "Invalid target:%s  "
			"Can not resolv into IPv4/v6.", portal);
		return -1;
	}
	iscsi_free(iscsi, addr);

	memset(&sa, 0, sizeof(sa));
	switch (ai->ai_family) {
	case AF_INET:
		socksize = sizeof(struct sockaddr_in);
		memcpy(&sa.sin, ai->ai_addr, socksize);
		sa.sin.sin_port = htons(port);
#ifdef HAVE_SOCK_SIN_LEN
		sa.sin.sin_len = socksize;
#endif
		break;
#ifdef HAVE_SOCKADDR_IN6
	case AF_INET6:
		socksize = sizeof(struct sockaddr_in6);
		memcpy(&sa.sin6, ai->ai_addr, socksize);
		sa.sin6.sin6_port = htons(port);
#ifdef HAVE_SOCK_SIN_LEN
		sa.sin6.sin6_len = socksize;
#endif
		break;
#endif
	default:
		iscsi_set_error(iscsi, "Unknown address family :%d. "
				"Only IPv4/IPv6 supported so far.",
				ai->ai_family);
		freeaddrinfo(ai);
		return -1;

	}

	iscsi->socket_status_cb  = cb;
	iscsi->connect_data      = private_data;

	if (iscsi->t->connect(iscsi, &sa, ai->ai_family) < 0) {
		iscsi_set_error(iscsi, "Couldn't connect transport");
		freeaddrinfo(ai);
		return -1;
	}

	freeaddrinfo(ai);
	return 0;
}