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); }
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; } }
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; } }
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; }
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; }
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; }
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; }