Example #1
0
int
control_compose(void *ch, u_int16_t type, void *buf, size_t len)
{
	struct pdu *pdu;
	struct ctrlmsghdr *cmh;
	void *ptr;

	if (PDU_LEN(len) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh)))
		return -1;
	if ((pdu = pdu_new()) == NULL)
		return -1;
	if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL)
		goto fail;
	bzero(cmh, sizeof(*cmh));
	cmh->type = type;
	cmh->len[0] = len;
	pdu_addbuf(pdu, cmh, sizeof(*cmh), 0);
	if (len > 0) {
		if ((ptr = pdu_alloc(len)) == NULL)
			goto fail;
		bcopy(buf, ptr, len);
		pdu_addbuf(pdu, ptr, len, 1);
	}

	return control_queue(ch, pdu);
fail:
	pdu_free(pdu);
	return -1;
}
Example #2
0
static struct pdu *
text_receive(struct connection *conn)
{
	struct pdu *response;
	struct iscsi_bhs_text_response *bhstr;

	response = pdu_new(conn);
	pdu_receive(response);
	if (response->pdu_bhs->bhs_opcode != ISCSI_BHS_OPCODE_TEXT_RESPONSE)
		log_errx(1, "protocol error: received invalid opcode 0x%x",
		    response->pdu_bhs->bhs_opcode);
	bhstr = (struct iscsi_bhs_text_response *)response->pdu_bhs;
#if 0
	if ((bhstr->bhstr_flags & BHSTR_FLAGS_FINAL) == 0)
		log_errx(1, "received Text PDU without the \"F\" flag");
#endif
	/*
	 * XXX: Implement the C flag some day.
	 */
	if ((bhstr->bhstr_flags & BHSTR_FLAGS_CONTINUE) != 0)
		log_errx(1, "received Text PDU with unsupported \"C\" flag");
	if (ntohl(bhstr->bhstr_statsn) != conn->conn_statsn + 1) {
		log_errx(1, "received Text PDU with wrong StatSN: "
		    "is %u, should be %u", ntohl(bhstr->bhstr_statsn),
		    conn->conn_statsn + 1);
	}
	conn->conn_statsn = ntohl(bhstr->bhstr_statsn);

	return (response);
}
Example #3
0
int
llc_connection_connect (struct llc_connection *connection)
{
    assert (connection);
    assert (connection->link);

    uint8_t buffer[BUFSIZ];
    size_t len = 0;
    if (connection->remote_uri) {
	int r = parameter_encode_sn (buffer, sizeof (buffer) - len, connection->remote_uri);
	if (r >= 0)
	    len += r;
    }

    struct pdu *pdu = pdu_new (connection->remote_sap, PDU_CONNECT, connection->local_sap, 0, 0, buffer, len);
    int res = llc_link_send_pdu (connection->link, pdu);
    pdu_free (pdu);

    if (res >= 0) {
	connection->link->transmission_handlers[connection->local_sap] = connection;
	connection->status = DLC_NEW;
	res = llc_connection_start (connection);
    }

    return res;
}
Example #4
0
static struct pdu *
login_receive(struct connection *conn, bool initial)
{
	struct pdu *request;
	struct iscsi_bhs_login_request *bhslr;

	request = pdu_new(conn);
	pdu_receive(request);
	if ((request->pdu_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) !=
	    ISCSI_BHS_OPCODE_LOGIN_REQUEST) {
		/*
		 * The first PDU in session is special - if we receive any PDU
		 * different than login request, we have to drop the connection
		 * without sending response ("A target receiving any PDU
		 * except a Login request before the Login Phase is started MUST
		 * immediately terminate the connection on which the PDU
		 * was received.")
		 */
		if (initial == false)
			login_send_error(request, 0x02, 0x0b);
		log_errx(1, "protocol error: received invalid opcode 0x%x",
		    request->pdu_bhs->bhs_opcode);
	}
	bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
	/*
	 * XXX: Implement the C flag some day.
	 */
	if ((bhslr->bhslr_flags & BHSLR_FLAGS_CONTINUE) != 0) {
		login_send_error(request, 0x03, 0x00);
		log_errx(1, "received Login PDU with unsupported \"C\" flag");
	}
	if (bhslr->bhslr_version_max != 0x00) {
		login_send_error(request, 0x02, 0x05);
		log_errx(1, "received Login PDU with unsupported "
		    "Version-max 0x%x", bhslr->bhslr_version_max);
	}
	if (bhslr->bhslr_version_min != 0x00) {
		login_send_error(request, 0x02, 0x05);
		log_errx(1, "received Login PDU with unsupported "
		    "Version-min 0x%x", bhslr->bhslr_version_min);
	}
	if (initial == false &&
	    ISCSI_SNLT(ntohl(bhslr->bhslr_cmdsn), conn->conn_cmdsn)) {
		login_send_error(request, 0x02, 0x00);
		log_errx(1, "received Login PDU with decreasing CmdSN: "
		    "was %u, is %u", conn->conn_cmdsn,
		    ntohl(bhslr->bhslr_cmdsn));
	}
	if (initial == false &&
	    ntohl(bhslr->bhslr_expstatsn) != conn->conn_statsn) {
		login_send_error(request, 0x02, 0x00);
		log_errx(1, "received Login PDU with wrong ExpStatSN: "
		    "is %u, should be %u", ntohl(bhslr->bhslr_expstatsn),
		    conn->conn_statsn);
	}
	conn->conn_cmdsn = ntohl(bhslr->bhslr_cmdsn);

	return (request);
}
Example #5
0
struct pdu *
control_getpdu(char *buf, size_t len)
{
	struct pdu *p;
	struct ctrlmsghdr *cmh;
	void *data;
	size_t n;
	int i;

	if (len < sizeof(*cmh))
		return NULL;

	if (!(p = pdu_new()))
		return NULL;

	n = sizeof(*cmh);
	cmh = pdu_alloc(n);
	bcopy(buf, cmh, n);
	buf += n;
	len -= n;

	if (pdu_addbuf(p, cmh, n, 0)) {
		free(cmh);
fail:
		pdu_free(p);
		return NULL;
	}

	for (i = 0; i < 3; i++) {
		n = cmh->len[i];
		if (n == 0)
			continue;
		if (PDU_LEN(n) > len)
			goto fail;
		if (!(data = pdu_alloc(n)))
			goto fail;
		bcopy(buf, data, n);
		if (pdu_addbuf(p, data, n, i + 1)) {
			free(data);
			goto fail;
		}
		buf += PDU_LEN(n);
		len -= PDU_LEN(n);
	}

	return p;
}
Example #6
0
static struct pdu *
logout_new_request(struct connection *conn)
{
	struct pdu *request;
	struct iscsi_bhs_logout_request *bhslr;

	request = pdu_new(conn);
	bhslr = (struct iscsi_bhs_logout_request *)request->pdu_bhs;
	bhslr->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_REQUEST |
	    ISCSI_BHS_OPCODE_IMMEDIATE;
	bhslr->bhslr_reason = BHSLR_REASON_CLOSE_SESSION;
	bhslr->bhslr_reason |= 0x80;
	bhslr->bhslr_initiator_task_tag = 0; /* XXX */
	bhslr->bhslr_cmdsn = 0; /* XXX */
	bhslr->bhslr_expstatsn = htonl(conn->conn_statsn + 1);

	return (request);
}
Example #7
0
static struct pdu *
text_new_request(struct connection *conn)
{
	struct pdu *request;
	struct iscsi_bhs_text_request *bhstr;

	request = pdu_new(conn);
	bhstr = (struct iscsi_bhs_text_request *)request->pdu_bhs;
	bhstr->bhstr_opcode = ISCSI_BHS_OPCODE_TEXT_REQUEST |
	    ISCSI_BHS_OPCODE_IMMEDIATE;
	bhstr->bhstr_flags = BHSTR_FLAGS_FINAL;
	bhstr->bhstr_initiator_task_tag = 0;
	bhstr->bhstr_target_transfer_tag = 0xffffffff;

	bhstr->bhstr_initiator_task_tag = 0; /* XXX */
	bhstr->bhstr_cmdsn = 0; /* XXX */
	bhstr->bhstr_expstatsn = htonl(conn->conn_statsn + 1);

	return (request);
}
Example #8
0
int
control_build(void *ch, u_int16_t type, int argc, struct ctrldata *argv)
{
	struct pdu *pdu;
	struct ctrlmsghdr *cmh;
	size_t size = 0;
	int i;

	if (argc > (int)nitems(cmh->len))
		return -1;

	for (i = 0; i < argc; i++)
		size += argv[i].len;
	if (PDU_LEN(size) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh)))
		return -1;

	if ((pdu = pdu_new()) == NULL)
		return -1;
	if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL)
		goto fail;
	bzero(cmh, sizeof(*cmh));
	cmh->type = type;
	pdu_addbuf(pdu, cmh, sizeof(*cmh), 0);

	for (i = 0; i < argc; i++)
		if (argv[i].len > 0) {
			void *ptr;

			cmh->len[i] = argv[i].len;
			if ((ptr = pdu_alloc(argv[i].len)) == NULL)
				goto fail;
			memcpy(ptr, argv[i].buf, argv[i].len);
			pdu_addbuf(pdu, ptr, argv[i].len, i + 1);
		}

	control_queue(ch, pdu);
	return 0;
fail:
	pdu_free(pdu);
	return -1;
}
Example #9
0
static struct pdu *
logout_receive(struct connection *conn)
{
	struct pdu *response;
	struct iscsi_bhs_logout_response *bhslr;

	response = pdu_new(conn);
	pdu_receive(response);
	if (response->pdu_bhs->bhs_opcode != ISCSI_BHS_OPCODE_LOGOUT_RESPONSE)
		log_errx(1, "protocol error: received invalid opcode 0x%x",
		    response->pdu_bhs->bhs_opcode);
	bhslr = (struct iscsi_bhs_logout_response *)response->pdu_bhs;
	if (ntohs(bhslr->bhslr_response) != BHSLR_RESPONSE_CLOSED_SUCCESSFULLY)
		log_warnx("received Logout Response with reason %d",
		    ntohs(bhslr->bhslr_response));
	if (ntohl(bhslr->bhslr_statsn) != conn->conn_statsn + 1) {
		log_errx(1, "received Logout PDU with wrong StatSN: "
		    "is %u, should be %u", ntohl(bhslr->bhslr_statsn),
		    conn->conn_statsn + 1);
	}
	conn->conn_statsn = ntohl(bhslr->bhslr_statsn);

	return (response);
}
Example #10
0
struct pdu *
pdu_new_response(struct pdu *request)
{

	return (pdu_new(request->pdu_connection));
}