Beispiel #1
0
int
iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
		      void *private_data)
{
	struct iscsi_pdu *pdu;
	char *str;

	if (iscsi->session_type != ISCSI_SESSION_DISCOVERY) {
		iscsi_set_error(iscsi, "Trying to do discovery on "
				"non-discovery session.");
		return -1;
	}

	pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_TEXT_REQUEST,
				 ISCSI_PDU_TEXT_RESPONSE,
				 iscsi_itt_post_increment(iscsi),
				 ISCSI_PDU_DROP_ON_RECONNECT);
	if (pdu == NULL) {
		iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
				"text pdu.");
		return -1;
	}

	/* immediate */
	iscsi_pdu_set_immediate(pdu);

	/* cmdsn is not increased if Immediate delivery*/
	iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);

	/* flags */
	iscsi_pdu_set_pduflags(pdu, ISCSI_PDU_TEXT_FINAL);

	/* target transfer tag */
	iscsi_pdu_set_ttt(pdu, 0xffffffff);

	/* sendtargets */
	str = (char *)"SendTargets=All";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1)
	    != 0) {
		iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed.");
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	pdu->callback     = cb;
	pdu->private_data = private_data;

	if (iscsi_queue_pdu(iscsi, pdu) != 0) {
		iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
				"text pdu.");
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	return 0;
}
Beispiel #2
0
int iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb, unsigned char *data, int len, void *private_data)
{
	struct iscsi_pdu *pdu;

	if (iscsi == NULL) {
		printf("trying to send nop-out on NULL context\n");
		return -1;
	}

	if (iscsi->is_loggedin == 0) {
		printf("trying send nop-out while not logged in\n");
		return -2;
	}

	pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_NOP_OUT, ISCSI_PDU_NOP_IN);
	if (pdu == NULL) {
		printf("Failed to allocate nop-out pdu\n");
		return -3;
	}

	/* immediate flag */
	iscsi_pdu_set_immediate(pdu);

	/* flags */
	iscsi_pdu_set_pduflags(pdu, 0x80);

	/* ttt */
	iscsi_pdu_set_ttt(pdu, 0xffffffff);

	/* lun */
	iscsi_pdu_set_lun(pdu, 2);

	/* cmdsn is not increased if Immediate delivery*/
	iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
	pdu->cmdsn = iscsi->cmdsn;
//	iscsi->cmdsn++;

	pdu->callback     = cb;
	pdu->private_data = private_data;

	if (iscsi_pdu_add_data(iscsi, pdu, data, len) != 0) {
		printf("Failed to add outdata to nop-out\n");
		iscsi_free_pdu(iscsi, pdu);
		return -4;
	}


	if (iscsi_queue_pdu(iscsi, pdu) != 0) {
		printf("failed to queue iscsi nop-out pdu\n");
		iscsi_free_pdu(iscsi, pdu);
		return -5;
	}

	return 0;
}
Beispiel #3
0
int iscsi_destroy_context(struct iscsi_context *iscsi)
{
    struct iscsi_pdu *pdu;

    if (iscsi == NULL) {
        return 0;
    }
    if (iscsi->initiator_name != NULL) {
        free(discard_const(iscsi->initiator_name));
        iscsi->initiator_name = NULL;
    }
    if (iscsi->alias != NULL) {
        free(discard_const(iscsi->alias));
        iscsi->alias = NULL;
    }
    if (iscsi->is_loggedin != 0) {
        printf("deswtroying context while logged in\n");
    }
    if (iscsi->fd != -1) {
        iscsi_disconnect(iscsi);
    }

    if (iscsi->inbuf != NULL) {
        free(iscsi->inbuf);
        iscsi->inbuf = NULL;
        iscsi->insize = 0;
        iscsi->inpos = 0;
    }

    while ((pdu = iscsi->outqueue)) {
        DLIST_REMOVE(iscsi->outqueue, pdu);
        pdu->callback(iscsi, ISCSI_STATUS_CANCELLED, NULL, pdu->private_data);
        iscsi_free_pdu(iscsi, pdu);
    }
    while ((pdu = iscsi->waitpdu)) {
        DLIST_REMOVE(iscsi->waitpdu, pdu);
        pdu->callback(iscsi, ISCSI_STATUS_CANCELLED, NULL, pdu->private_data);
        iscsi_free_pdu(iscsi, pdu);
    }

    free(iscsi);

    return 0;
}
Beispiel #4
0
int
iscsi_task_mgmt_async(struct iscsi_context *iscsi,
                      int lun, enum iscsi_task_mgmt_funcs function,
                      uint32_t ritt, uint32_t rcmdsn,
                      iscsi_command_cb cb, void *private_data)
{
    struct iscsi_pdu *pdu;

    if (iscsi->is_loggedin == 0) {
        iscsi_set_error(iscsi, "trying to send task-mgmt while not "
                        "logged in");
        return -1;
    }

    pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_TASK_MANAGEMENT_REQUEST,
                             ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE);
    if (pdu == NULL) {
        iscsi_set_error(iscsi, "Failed to allocate task mgmt pdu");
        return -1;
    }

    /* immediate flag */
    iscsi_pdu_set_immediate(pdu);

    /* flags */
    iscsi_pdu_set_pduflags(pdu, 0x80 | function);

    /* lun */
    iscsi_pdu_set_lun(pdu, lun);

    /* ritt */
    iscsi_pdu_set_ritt(pdu, ritt);

    /* cmdsn is not increased if Immediate delivery*/
    iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
    pdu->cmdsn = iscsi->cmdsn;

    /* rcmdsn */
    iscsi_pdu_set_rcmdsn(pdu, rcmdsn);


    pdu->callback     = cb;
    pdu->private_data = private_data;

    if (iscsi_queue_pdu(iscsi, pdu) != 0) {
        iscsi_set_error(iscsi, "failed to queue iscsi taskmgmt pdu");
        iscsi_free_pdu(iscsi, pdu);
        return -1;
    }

    return 0;
}
Beispiel #5
0
static int
iscsi_write_to_socket(struct iscsi_context *iscsi)
{
	ssize_t count;

	if (iscsi->fd == -1) {
		iscsi_set_error(iscsi, "trying to write but not connected");
		return -1;
	}

	while (iscsi->outqueue) {
		ssize_t total;

		if (iscsi->outqueue->cmdsn > iscsi->maxcmdsn) {
			/* stop sending. maxcmdsn is reached */
			return 0;
		}
	     
		total = iscsi->outqueue->outdata.size;
		total = (total + 3) & 0xfffffffc;

		count = send(iscsi->fd,
			      iscsi->outqueue->outdata.data
			      + iscsi->outqueue->written,
			      total - iscsi->outqueue->written,
			      0);
		if (count == -1) {
			if (errno == EAGAIN || errno == EWOULDBLOCK) {
				return 0;
			}
			iscsi_set_error(iscsi, "Error when writing to "
					"socket :%d", errno);
			return -1;
		}

		iscsi->outqueue->written += count;
		if (iscsi->outqueue->written == total) {
			struct iscsi_pdu *pdu = iscsi->outqueue;

			SLIST_REMOVE(&iscsi->outqueue, pdu);
			if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
				iscsi_free_pdu(iscsi, pdu);
			} else {
				SLIST_ADD_END(&iscsi->waitpdu, pdu);
			}
		}
	}
	return 0;
}
Beispiel #6
0
int
iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
		   void *private_data)
{
	struct iscsi_pdu *pdu;

	iscsi->login_attempts = 0;

	if (iscsi->is_loggedin == 0) {
		iscsi_set_error(iscsi, "Trying to logout while not logged in.");
		return -1;
	}

	pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_LOGOUT_REQUEST,
				 ISCSI_PDU_LOGOUT_RESPONSE);
	if (pdu == NULL) {
		iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
				"logout pdu.");
		return -1;
	}

	/* logout request has the immediate flag set */
	iscsi_pdu_set_immediate(pdu);

	/* flags : close the session */
	iscsi_pdu_set_pduflags(pdu, 0x80);

	/* cmdsn is not increased if Immediate delivery*/
	iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
	pdu->cmdsn = iscsi->cmdsn;

	/* exp statsn */
	iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);

	pdu->callback     = cb;
	pdu->private_data = private_data;

	if (iscsi_queue_pdu(iscsi, pdu) != 0) {
		iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
				"logout pdu.");
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	return 0;
}
Beispiel #7
0
int iscsi_process_reject(struct iscsi_context *iscsi,
				struct iscsi_in_pdu *in)
{
	int size = in->data_pos;
	uint32_t itt;
	struct iscsi_pdu *pdu;

	if (size < ISCSI_RAW_HEADER_SIZE) {
		iscsi_set_error(iscsi, "size of REJECT payload is too small."
				       "Need >= %d bytes but got %d.",
				       ISCSI_RAW_HEADER_SIZE, (int)size);
		return -1;
	}

	itt = scsi_get_uint32(&in->data[16]);

	if (iscsi->log_level > 1) {
		iscsi_dump_pdu_header(iscsi, in->data);
	}

	for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
		if (pdu->itt == itt) {
			break;
		}
	}

	if (pdu == NULL) {
		iscsi_set_error(iscsi, "Can not match REJECT with"
				       "any outstanding pdu with itt:0x%08x",
				       itt);
		return -1;
	}

	pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
			      pdu->private_data);

	SLIST_REMOVE(&iscsi->waitpdu, pdu);
	iscsi_free_pdu(iscsi, pdu);
	return 0;
}
Beispiel #8
0
int
iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt)
{
	struct iscsi_pdu *pdu;

	pdu = iscsi_allocate_pdu_with_itt_flags(iscsi, ISCSI_PDU_NOP_OUT, ISCSI_PDU_NO_PDU,
				0xffffffff,ISCSI_PDU_DELETE_WHEN_SENT|ISCSI_PDU_NO_CALLBACK);
	if (pdu == NULL) {
		iscsi_set_error(iscsi, "Failed to allocate nop-out pdu");
		return -1;
	}

	/* immediate flag */
	iscsi_pdu_set_immediate(pdu);

	/* flags */
	iscsi_pdu_set_pduflags(pdu, 0x80);

	/* ttt */
	iscsi_pdu_set_ttt(pdu, ttt);

	/* lun */
	iscsi_pdu_set_lun(pdu, 0);

	/* cmdsn is not increased if Immediate delivery*/
	iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
	pdu->cmdsn = iscsi->cmdsn;

	/* exp statsn */
	iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);

	if (iscsi_queue_pdu(iscsi, pdu) != 0) {
		iscsi_set_error(iscsi, "failed to queue iscsi nop-out pdu");
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	return 0;
}
Beispiel #9
0
int iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb, void *private_data)
{
	struct iscsi_pdu *pdu;

	if (iscsi == NULL) {
		printf("trying to logout on NULL context\n");
		return -1;
	}

	if (iscsi->is_loggedin == 0) {
		printf("trying to logout while not logged in\n");
		return -2;
	}

	pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_LOGOUT_REQUEST, ISCSI_PDU_LOGOUT_RESPONSE);
	if (pdu == NULL) {
		printf("Failed to allocate logout pdu\n");
		return -3;
	}

	/* logout request has the immediate flag set */
	iscsi_pdu_set_immediate(pdu);

	/* flags : close the session */
	iscsi_pdu_set_pduflags(pdu, 0x80);


	pdu->callback     = cb;
	pdu->private_data = private_data;

	if (iscsi_queue_pdu(iscsi, pdu) != 0) {
		printf("failed to queue iscsi logout pdu\n");
		iscsi_free_pdu(iscsi, pdu);
		return -4;
	}

	return 0;
}
Beispiel #10
0
int
iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
{
	uint32_t itt;
	enum iscsi_opcode opcode;
	struct iscsi_pdu *pdu;
	uint8_t	ahslen;

	opcode = in->hdr[0] & 0x3f;
	ahslen = in->hdr[4];
	itt = ntohl(*(uint32_t *)&in->hdr[16]);

	if (ahslen != 0) {
		iscsi_set_error(iscsi, "cant handle expanded headers yet");
		return -1;
	}

	if (opcode == ISCSI_PDU_REJECT) {
		iscsi_set_error(iscsi, "Request was rejected with reason: 0x%02x (%s)", in->hdr[2], iscsi_reject_reason_str(in->hdr[2]));

		if (iscsi_process_reject(iscsi, in) != 0) {
			return -1;
		}
		return 0;
	}

	if (opcode == ISCSI_PDU_NOP_IN && itt == 0xffffffff) {
		if (iscsi_process_target_nop_in(iscsi, in) != 0) {
			return -1;
		}
		return 0;
	}

	for (pdu = iscsi->waitpdu; pdu; pdu = pdu->next) {
		enum iscsi_opcode expected_response = pdu->response_opcode;
		int is_finished = 1;

		if (pdu->itt != itt) {
			continue;
		}

		/* we have a special case with scsi-command opcodes,
		 * they are replied to by either a scsi-response
		 * or a data-in, or a combination of both.
		 */
		if (opcode == ISCSI_PDU_DATA_IN
		    && expected_response == ISCSI_PDU_SCSI_RESPONSE) {
			expected_response = ISCSI_PDU_DATA_IN;
		}

		/* Another special case is if we get a R2T.
		 * In this case we should find the original request and just send an additional
		 * DATAOUT segment for this task.
		 */
		if (opcode == ISCSI_PDU_R2T) {
			expected_response = ISCSI_PDU_R2T;
	        }

		if (opcode != expected_response) {
			iscsi_set_error(iscsi, "Got wrong opcode back for "
					"itt:%d  got:%d expected %d",
					itt, opcode, pdu->response_opcode);
			return -1;
		}
		switch (opcode) {
		case ISCSI_PDU_LOGIN_RESPONSE:
			if (iscsi_process_login_reply(iscsi, pdu, in) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi login reply "
						"failed");
				return -1;
			}
			break;
		case ISCSI_PDU_TEXT_RESPONSE:
			if (iscsi_process_text_reply(iscsi, pdu, in) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi text reply "
						"failed");
				return -1;
			}
			break;
		case ISCSI_PDU_LOGOUT_RESPONSE:
			if (iscsi_process_logout_reply(iscsi, pdu, in) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi logout reply "
						"failed");
				return -1;
			}
			break;
		case ISCSI_PDU_SCSI_RESPONSE:
			if (iscsi_process_scsi_reply(iscsi, pdu, in) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi response reply "
						"failed");
				return -1;
			}
			break;
		case ISCSI_PDU_DATA_IN:
			if (iscsi_process_scsi_data_in(iscsi, pdu, in,
						       &is_finished) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi data in "
						"failed");
				return -1;
			}
			break;
		case ISCSI_PDU_NOP_IN:
			if (iscsi_process_nop_out_reply(iscsi, pdu, in) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi nop-in failed");
				return -1;
			}
			break;
		case ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE:
			if (iscsi_process_task_mgmt_reply(iscsi, pdu,
							  in) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi task-mgmt failed");
				return -1;
			}
			break;
		case ISCSI_PDU_R2T:
			if (iscsi_process_r2t(iscsi, pdu, in) != 0) {
				SLIST_REMOVE(&iscsi->waitpdu, pdu);
				iscsi_free_pdu(iscsi, pdu);
				iscsi_set_error(iscsi, "iscsi r2t "
						"failed");
				return -1;
			}
			is_finished = 0;
			break;
		default:
			iscsi_set_error(iscsi, "Dont know how to handle "
					"opcode 0x%02x", opcode);
			return -1;
		}

		if (is_finished) {
			SLIST_REMOVE(&iscsi->waitpdu, pdu);
			iscsi_free_pdu(iscsi, pdu);
		}
		return 0;
	}

	return 0;
}
Beispiel #11
0
int
iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
		  void *private_data)
{
	struct iscsi_pdu *pdu;
	int transit;

	if (iscsi->login_attempts++ > 10) {
		iscsi_set_error(iscsi, "login took too many tries."
				" giving up.");
		return -1;
	}
 
	if (iscsi->is_loggedin != 0) {
		iscsi_set_error(iscsi, "Trying to login while already logged "
				"in.");
		return -1;
	}

	switch (iscsi->session_type) {
	case ISCSI_SESSION_DISCOVERY:
	case ISCSI_SESSION_NORMAL:
		break;
	default:
		iscsi_set_error(iscsi, "trying to login without setting "
				"session type.");
		return -1;
	}

	pdu = iscsi_allocate_pdu_with_itt_flags(iscsi,
				ISCSI_PDU_LOGIN_REQUEST,
				ISCSI_PDU_LOGIN_RESPONSE,
				iscsi->itt, 0);
	if (pdu == NULL) {
		iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate "
				"login pdu.");
		return -1;
	}

	/* login request */
	iscsi_pdu_set_immediate(pdu);

	if (!iscsi->user[0]) {
		iscsi->current_phase = ISCSI_PDU_LOGIN_CSG_OPNEG;
	}

	if (iscsi->current_phase == ISCSI_PDU_LOGIN_CSG_SECNEG) {
		iscsi->next_phase    = ISCSI_PDU_LOGIN_NSG_OPNEG;
	}
	if (iscsi->current_phase == ISCSI_PDU_LOGIN_CSG_OPNEG) {
		iscsi->next_phase    = ISCSI_PDU_LOGIN_NSG_FF;
	}

	transit = 0;
	if (iscsi->current_phase == ISCSI_PDU_LOGIN_CSG_OPNEG) {
		transit = ISCSI_PDU_LOGIN_TRANSIT;
	}
	if (iscsi->current_phase == ISCSI_PDU_LOGIN_CSG_SECNEG) {
		if (iscsi->secneg_phase == ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP) {
			transit = ISCSI_PDU_LOGIN_TRANSIT;
		}
		if (iscsi->secneg_phase == ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE) {
			transit = ISCSI_PDU_LOGIN_TRANSIT;
		}
	}

	/* flags */
	iscsi_pdu_set_pduflags(pdu, transit
					| iscsi->current_phase
					| iscsi->next_phase);


	/* initiator name */
	if (iscsi_login_add_initiatorname(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* optional alias */
	if (iscsi->alias[0]) {
		if (iscsi_login_add_alias(iscsi, pdu) != 0) {
			iscsi_free_pdu(iscsi, pdu);
			return -1;
		}
	}

	/* target name */
	if (iscsi->session_type == ISCSI_SESSION_NORMAL) {
		if (iscsi_login_add_targetname(iscsi, pdu) != 0) {
			iscsi_free_pdu(iscsi, pdu);
			return -1;
		}
	}

	/* session type */
	if (iscsi_login_add_sessiontype(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* header digest */
	if (iscsi_login_add_headerdigest(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* auth method */
	if (iscsi_login_add_authmethod(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* auth algorithm */
	if (iscsi_login_add_authalgorithm(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* chap username */
	if (iscsi_login_add_chap_username(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* chap response */
	if (iscsi_login_add_chap_response(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* data digest */
	if (iscsi_login_add_datadigest(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* initial r2t */
	if (iscsi_login_add_initialr2t(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* immediate data */
	if (iscsi_login_add_immediatedata(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* max burst length */
	if (iscsi_login_add_maxburstlength(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* first burst length */
	if (iscsi_login_add_firstburstlength(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* default time 2 wait */
	if (iscsi_login_add_defaulttime2wait(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* default time 2 retain */
	if (iscsi_login_add_defaulttime2retain(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* max outstanding r2t */
	if (iscsi_login_add_maxoutstandingr2t(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* errorrecoverylevel */
	if (iscsi_login_add_errorrecoverylevel(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* ifmarker */
	if (iscsi_login_add_ifmarker(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* ofmarker */
	if (iscsi_login_add_ofmarker(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* maxconnections */
	if (iscsi_login_add_maxconnections(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* max recv data segment length */
	if (iscsi_login_add_maxrecvdatasegmentlength(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* data pdu in order */
	if (iscsi_login_add_datapduinorder(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	/* data sequence in order */
	if (iscsi_login_add_datasequenceinorder(iscsi, pdu) != 0) {
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}


	pdu->callback     = cb;
	pdu->private_data = private_data;

	if (iscsi_queue_pdu(iscsi, pdu) != 0) {
		iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
				"pdu.");
		iscsi_free_pdu(iscsi, pdu);
		return -1;
	}

	return 0;
}
Beispiel #12
0
static int iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, struct scsi_task *task, iscsi_command_cb cb, struct iscsi_data *data, void *private_data)
{
    struct iscsi_pdu *pdu;
    struct iscsi_scsi_cbdata *scsi_cbdata;
    int flags;

    if (iscsi == NULL) {
        printf("trying to send command on NULL context\n");
        scsi_free_scsi_task(task);
        return -1;
    }

    if (iscsi->session_type != ISCSI_SESSION_NORMAL) {
        printf("Trying to send command on discovery session\n");
        scsi_free_scsi_task(task);
        return -2;
    }

    if (iscsi->is_loggedin == 0) {
        printf("Trying to send command while not logged in\n");
        scsi_free_scsi_task(task);
        return -3;
    }

    scsi_cbdata = malloc(sizeof(struct iscsi_scsi_cbdata));
    if (scsi_cbdata == NULL) {
        printf("failed to allocate scsi cbdata\n");
        scsi_free_scsi_task(task);
        return -4;
    }
    bzero(scsi_cbdata, sizeof(struct iscsi_scsi_cbdata));
    scsi_cbdata->task         = task;
    scsi_cbdata->callback     = cb;
    scsi_cbdata->private_data = private_data;

    pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_SCSI_REQUEST, ISCSI_PDU_SCSI_RESPONSE);
    if (pdu == NULL) {
        printf("Failed to allocate text pdu\n");
        iscsi_free_scsi_cbdata(scsi_cbdata);
        return -5;
    }
    pdu->scsi_cbdata = scsi_cbdata;

    /* flags */
    flags = ISCSI_PDU_SCSI_FINAL|ISCSI_PDU_SCSI_ATTR_SIMPLE;
    switch (task->xfer_dir) {
    case SCSI_XFER_NONE:
        break;
    case SCSI_XFER_READ:
        flags |= ISCSI_PDU_SCSI_READ;
        break;
    case SCSI_XFER_WRITE:
        flags |= ISCSI_PDU_SCSI_WRITE;
        if (data == NULL) {
            printf("DATA-OUT command but data == NULL\n");
            iscsi_free_pdu(iscsi, pdu);
            return -5;
        }
        if (data->size != task->expxferlen) {
            printf("data size:%d is not same as expected data transfer length:%d\n", data->size, task->expxferlen);
            iscsi_free_pdu(iscsi, pdu);
            return -7;
        }
        if (iscsi_pdu_add_data(iscsi, pdu, data->data, data->size) != 0) {
            printf("Failed to add outdata to the pdu\n");
            iscsi_free_pdu(iscsi, pdu);
            return -6;
        }

        break;
    }
    iscsi_pdu_set_pduflags(pdu, flags);

    /* lun */
    iscsi_pdu_set_lun(pdu, lun);

    /* expxferlen */
    iscsi_pdu_set_expxferlen(pdu, task->expxferlen);

    /* cmdsn */
    iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);
    pdu->cmdsn = iscsi->cmdsn;
    iscsi->cmdsn++;

    /* exp statsn */
    iscsi_pdu_set_expstatsn(pdu, iscsi->statsn+1);

    /* cdb */
    iscsi_pdu_set_cdb(pdu, task);

    pdu->callback     = iscsi_scsi_response_cb;
    pdu->private_data = scsi_cbdata;

    if (iscsi_queue_pdu(iscsi, pdu) != 0) {
        printf("failed to queue iscsi scsi pdu\n");
        iscsi_free_pdu(iscsi, pdu);
        return -6;
    }

    return 0;
}
Beispiel #13
0
int iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb, void *private_data)
{
	struct iscsi_pdu *pdu;
	char *str;
	int ret;

	if (iscsi == NULL) {
		printf("trying to login on NULL context\n");
		return -1;
	}

	if (iscsi->is_loggedin != 0) {
		printf("trying to login while already logged in\n");
		return -2;
	}

	switch (iscsi->session_type) {
	case ISCSI_SESSION_DISCOVERY:
	case ISCSI_SESSION_NORMAL:
		break;
	default:
		printf("trying to login without setting session type\n");
		return -3;
	}

	pdu = iscsi_allocate_pdu(iscsi, ISCSI_PDU_LOGIN_REQUEST, ISCSI_PDU_LOGIN_RESPONSE);
	if (pdu == NULL) {
		printf("Failed to allocate login pdu\n");
		return -4;
	}

	/* login request */
	iscsi_pdu_set_immediate(pdu);

	/* flags */
	iscsi_pdu_set_pduflags(pdu, ISCSI_PDU_LOGIN_TRANSIT|ISCSI_PDU_LOGIN_CSG_OPNEG|ISCSI_PDU_LOGIN_NSG_FF);


	/* initiator name */
	if (asprintf(&str, "InitiatorName=%s", iscsi->initiator_name) == -1) {
		printf("asprintf failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -5;
	}
	ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1);
	free(str);
	if (ret != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -6;
	}

	/* optional alias */
	if (iscsi->alias) {
		if (asprintf(&str, "InitiatorAlias=%s", iscsi->alias) == -1) {
			printf("asprintf failed\n");
			iscsi_free_pdu(iscsi, pdu);
			return -7;
		}
		ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1);
		free(str);
		if (ret != 0) {
			printf("pdu add data failed\n");
			iscsi_free_pdu(iscsi, pdu);
			return -8;
		}
	}

	/* target name */
	if (iscsi->session_type == ISCSI_SESSION_NORMAL) {
		if (iscsi->target_name == NULL) {
			printf("trying normal connect but target name not set\n");
			iscsi_free_pdu(iscsi, pdu);
			return -9;
		}

		if (asprintf(&str, "TargetName=%s", iscsi->target_name) == -1) {
			printf("asprintf failed\n");
			iscsi_free_pdu(iscsi, pdu);
			return -10;
		}
		ret = iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1);
		free(str);
		if (ret != 0) {
			printf("pdu add data failed\n");
			iscsi_free_pdu(iscsi, pdu);
			return -11;
		}
	}

	/* session type */
	switch (iscsi->session_type) {
	case ISCSI_SESSION_DISCOVERY:
		str = "SessionType=Discovery";
		break;
	case ISCSI_SESSION_NORMAL:
		str = "SessionType=Normal";
		break;
	default:
		printf("can not handle sessions %d yet\n", iscsi->session_type);
		return -12;
	}
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -13;
	}

	str = "HeaderDigest=None";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -14;
	}
	str = "DataDigest=None";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -15;
	}
	str = "InitialR2T=Yes";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -16;
	}
	str = "ImmediateData=Yes";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -17;
	}
	str = "MaxBurstLength=262144";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -18;
	}
	str = "FirstBurstLength=262144";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -19;
	}
	str = "MaxRecvDataSegmentLength=262144";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -20;
	}
	str = "DataPDUInOrder=Yes";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -21;
	}
	str = "DataSequenceInOrder=Yes";
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1) != 0) {
		printf("pdu add data failed\n");
		iscsi_free_pdu(iscsi, pdu);
		return -22;
	}


	pdu->callback     = cb;
	pdu->private_data = private_data;

	if (iscsi_queue_pdu(iscsi, pdu) != 0) {
		printf("failed to queue iscsi login pdu\n");
		iscsi_free_pdu(iscsi, pdu);
		return -23;
	}

	return 0;
}