root/sys/dev/iscsi/iscsi_proto.h
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2012 The FreeBSD Foundation
 *
 * This software was developed by Edward Tomasz Napierala under sponsorship
 * from the FreeBSD Foundation.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef ISCSI_PROTO_H
#define ISCSI_PROTO_H

#ifndef CTASSERT
#define CTASSERT(x)             _CTASSERT(x, __LINE__)
#define _CTASSERT(x, y)         __CTASSERT(x, y)
#define __CTASSERT(x, y)        typedef char __assert_ ## y [(x) ? 1 : -1]
#endif

#define ISCSI_SNGT(x, y)        ((int32_t)(x) - (int32_t)(y) > 0)
#define ISCSI_SNLT(x, y)        ((int32_t)(x) - (int32_t)(y) < 0)

#define ISCSI_BHS_SIZE                  48
#define ISCSI_HEADER_DIGEST_SIZE        4
#define ISCSI_DATA_DIGEST_SIZE          4

#define ISCSI_BHS_OPCODE_IMMEDIATE      0x40

#define ISCSI_BHS_OPCODE_NOP_OUT        0x00
#define ISCSI_BHS_OPCODE_SCSI_COMMAND   0x01
#define ISCSI_BHS_OPCODE_TASK_REQUEST   0x02
#define ISCSI_BHS_OPCODE_LOGIN_REQUEST  0x03
#define ISCSI_BHS_OPCODE_TEXT_REQUEST   0x04
#define ISCSI_BHS_OPCODE_SCSI_DATA_OUT  0x05
#define ISCSI_BHS_OPCODE_LOGOUT_REQUEST 0x06

#define ISCSI_BHS_OPCODE_NOP_IN         0x20
#define ISCSI_BHS_OPCODE_SCSI_RESPONSE  0x21
#define ISCSI_BHS_OPCODE_TASK_RESPONSE  0x22
#define ISCSI_BHS_OPCODE_LOGIN_RESPONSE 0x23
#define ISCSI_BHS_OPCODE_TEXT_RESPONSE  0x24
#define ISCSI_BHS_OPCODE_SCSI_DATA_IN   0x25
#define ISCSI_BHS_OPCODE_LOGOUT_RESPONSE        0x26
#define ISCSI_BHS_OPCODE_R2T            0x31
#define ISCSI_BHS_OPCODE_ASYNC_MESSAGE  0x32
#define ISCSI_BHS_OPCODE_REJECT         0x3f

struct iscsi_bhs {
        uint8_t         bhs_opcode;
        uint8_t         bhs_opcode_specific1[3];
        uint8_t         bhs_total_ahs_len;
        uint8_t         bhs_data_segment_len[3];
        uint64_t        bhs_lun;
        uint8_t         bhs_inititator_task_tag[4];
        uint8_t         bhs_opcode_specific4[28];
};
CTASSERT(sizeof(struct iscsi_bhs) == ISCSI_BHS_SIZE);

#define BHSSC_FLAGS_F           0x80
#define BHSSC_FLAGS_R           0x40
#define BHSSC_FLAGS_W           0x20
#define BHSSC_FLAGS_ATTR        0x07

#define BHSSC_FLAGS_ATTR_UNTAGGED       0
#define BHSSC_FLAGS_ATTR_SIMPLE         1
#define BHSSC_FLAGS_ATTR_ORDERED        2
#define BHSSC_FLAGS_ATTR_HOQ            3
#define BHSSC_FLAGS_ATTR_ACA            4

#define BHSSC_PRI_MASK          0xf0
#define BHSSC_PRI_SHIFT         4

struct iscsi_bhs_scsi_command {
        uint8_t         bhssc_opcode;
        uint8_t         bhssc_flags;
        uint8_t         bhssc_pri;
        uint8_t         bhssc_reserved;
        uint8_t         bhssc_total_ahs_len;
        uint8_t         bhssc_data_segment_len[3];
        uint64_t        bhssc_lun;
        uint32_t        bhssc_initiator_task_tag;
        uint32_t        bhssc_expected_data_transfer_length;
        uint32_t        bhssc_cmdsn;
        uint32_t        bhssc_expstatsn;
        uint8_t         bhssc_cdb[16];
};
CTASSERT(sizeof(struct iscsi_bhs_scsi_command) == ISCSI_BHS_SIZE);

#define BHSSR_FLAGS_RESIDUAL_UNDERFLOW          0x02
#define BHSSR_FLAGS_RESIDUAL_OVERFLOW           0x04

#define BHSSR_RESPONSE_COMMAND_COMPLETED        0x00

struct iscsi_bhs_scsi_response {
        uint8_t         bhssr_opcode;
        uint8_t         bhssr_flags;
        uint8_t         bhssr_response;
        uint8_t         bhssr_status;
        uint8_t         bhssr_total_ahs_len;
        uint8_t         bhssr_data_segment_len[3];
        uint16_t        bhssr_status_qualifier;
        uint16_t        bhssr_reserved;
        uint32_t        bhssr_reserved2;
        uint32_t        bhssr_initiator_task_tag;
        uint32_t        bhssr_snack_tag;
        uint32_t        bhssr_statsn;
        uint32_t        bhssr_expcmdsn;
        uint32_t        bhssr_maxcmdsn;
        uint32_t        bhssr_expdatasn;
        uint32_t        bhssr_bidirectional_read_residual_count;
        uint32_t        bhssr_residual_count;
};
CTASSERT(sizeof(struct iscsi_bhs_scsi_response) == ISCSI_BHS_SIZE);

#define BHSTMR_FUNCTION_ABORT_TASK              1
#define BHSTMR_FUNCTION_ABORT_TASK_SET          2
#define BHSTMR_FUNCTION_CLEAR_ACA               3
#define BHSTMR_FUNCTION_CLEAR_TASK_SET          4
#define BHSTMR_FUNCTION_LOGICAL_UNIT_RESET      5
#define BHSTMR_FUNCTION_TARGET_WARM_RESET       6
#define BHSTMR_FUNCTION_TARGET_COLD_RESET       7
#define BHSTMR_FUNCTION_TASK_REASSIGN           8
#define BHSTMR_FUNCTION_QUERY_TASK              9
#define BHSTMR_FUNCTION_QUERY_TASK_SET          10
#define BHSTMR_FUNCTION_I_T_NEXUS_RESET         11
#define BHSTMR_FUNCTION_QUERY_ASYNC_EVENT       12

struct iscsi_bhs_task_management_request {
        uint8_t         bhstmr_opcode;
        uint8_t         bhstmr_function;
        uint8_t         bhstmr_reserved[2];
        uint8_t         bhstmr_total_ahs_len;
        uint8_t         bhstmr_data_segment_len[3];
        uint64_t        bhstmr_lun;
        uint32_t        bhstmr_initiator_task_tag;
        uint32_t        bhstmr_referenced_task_tag;
        uint32_t        bhstmr_cmdsn;
        uint32_t        bhstmr_expstatsn;
        uint32_t        bhstmr_refcmdsn;
        uint32_t        bhstmr_expdatasn;
        uint64_t        bhstmr_reserved2;
};
CTASSERT(sizeof(struct iscsi_bhs_task_management_request) == ISCSI_BHS_SIZE);

#define BHSTMR_RESPONSE_FUNCTION_COMPLETE       0
#define BHSTMR_RESPONSE_TASK_DOES_NOT_EXIST     1
#define BHSTMR_RESPONSE_LUN_DOES_NOT_EXIST      2
#define BHSTMR_RESPONSE_TASK_STILL_ALLEGIANT    3
#define BHSTMR_RESPONSE_TASK_ALL_REASS_NOT_SUPP 4
#define BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED  5
#define BHSTMR_RESPONSE_FUNCTION_AUTH_FAIL      6
#define BHSTMR_RESPONSE_FUNCTION_SUCCEEDED      7
#define BHSTMR_RESPONSE_FUNCTION_REJECTED       255

struct iscsi_bhs_task_management_response {
        uint8_t         bhstmr_opcode;
        uint8_t         bhstmr_flags;
        uint8_t         bhstmr_response;
        uint8_t         bhstmr_reserved;
        uint8_t         bhstmr_total_ahs_len;
        uint8_t         bhstmr_data_segment_len[3];
        uint8_t         bhstmr_additional_reponse_information[3];
        uint8_t         bhstmr_reserved2[5];
        uint32_t        bhstmr_initiator_task_tag;
        uint32_t        bhstmr_reserved3;
        uint32_t        bhstmr_statsn;
        uint32_t        bhstmr_expcmdsn;
        uint32_t        bhstmr_maxcmdsn;
        uint8_t         bhstmr_reserved4[12];
};
CTASSERT(sizeof(struct iscsi_bhs_task_management_response) == ISCSI_BHS_SIZE);

#define BHSLR_FLAGS_TRANSIT             0x80
#define BHSLR_FLAGS_CONTINUE            0x40

#define BHSLR_STAGE_SECURITY_NEGOTIATION        0
#define BHSLR_STAGE_OPERATIONAL_NEGOTIATION     1
#define BHSLR_STAGE_FULL_FEATURE_PHASE          3 /* Yes, 3. */

struct iscsi_bhs_login_request {
        uint8_t         bhslr_opcode;
        uint8_t         bhslr_flags;
        uint8_t         bhslr_version_max;
        uint8_t         bhslr_version_min;
        uint8_t         bhslr_total_ahs_len;
        uint8_t         bhslr_data_segment_len[3];
        uint8_t         bhslr_isid[6];
        uint16_t        bhslr_tsih;
        uint32_t        bhslr_initiator_task_tag;
        uint16_t        bhslr_cid;
        uint16_t        bhslr_reserved;
        uint32_t        bhslr_cmdsn;
        uint32_t        bhslr_expstatsn;
        uint8_t         bhslr_reserved2[16];
};
CTASSERT(sizeof(struct iscsi_bhs_login_request) == ISCSI_BHS_SIZE);

struct iscsi_bhs_login_response {
        uint8_t         bhslr_opcode;
        uint8_t         bhslr_flags;
        uint8_t         bhslr_version_max;
        uint8_t         bhslr_version_active;
        uint8_t         bhslr_total_ahs_len;
        uint8_t         bhslr_data_segment_len[3];
        uint8_t         bhslr_isid[6];
        uint16_t        bhslr_tsih;
        uint32_t        bhslr_initiator_task_tag;
        uint32_t        bhslr_reserved;
        uint32_t        bhslr_statsn;
        uint32_t        bhslr_expcmdsn;
        uint32_t        bhslr_maxcmdsn;
        uint8_t         bhslr_status_class;
        uint8_t         bhslr_status_detail;
        uint16_t        bhslr_reserved2;
        uint8_t         bhslr_reserved3[8];
};
CTASSERT(sizeof(struct iscsi_bhs_login_response) == ISCSI_BHS_SIZE);

#define BHSTR_FLAGS_FINAL               0x80
#define BHSTR_FLAGS_CONTINUE            0x40

struct iscsi_bhs_text_request {
        uint8_t         bhstr_opcode;
        uint8_t         bhstr_flags;
        uint16_t        bhstr_reserved;
        uint8_t         bhstr_total_ahs_len;
        uint8_t         bhstr_data_segment_len[3];
        uint64_t        bhstr_lun;
        uint32_t        bhstr_initiator_task_tag;
        uint32_t        bhstr_target_transfer_tag;
        uint32_t        bhstr_cmdsn;
        uint32_t        bhstr_expstatsn;
        uint8_t         bhstr_reserved2[16];
};
CTASSERT(sizeof(struct iscsi_bhs_text_request) == ISCSI_BHS_SIZE);

struct iscsi_bhs_text_response {
        uint8_t         bhstr_opcode;
        uint8_t         bhstr_flags;
        uint16_t        bhstr_reserved;
        uint8_t         bhstr_total_ahs_len;
        uint8_t         bhstr_data_segment_len[3];
        uint64_t        bhstr_lun;
        uint32_t        bhstr_initiator_task_tag;
        uint32_t        bhstr_target_transfer_tag;
        uint32_t        bhstr_statsn;
        uint32_t        bhstr_expcmdsn;
        uint32_t        bhstr_maxcmdsn;
        uint8_t         bhstr_reserved2[12];
};
CTASSERT(sizeof(struct iscsi_bhs_text_response) == ISCSI_BHS_SIZE);

#define BHSDO_FLAGS_F   0x80

struct iscsi_bhs_data_out {
        uint8_t         bhsdo_opcode;
        uint8_t         bhsdo_flags;
        uint8_t         bhsdo_reserved[2];
        uint8_t         bhsdo_total_ahs_len;
        uint8_t         bhsdo_data_segment_len[3];
        uint64_t        bhsdo_lun;
        uint32_t        bhsdo_initiator_task_tag;
        uint32_t        bhsdo_target_transfer_tag;
        uint32_t        bhsdo_reserved2;
        uint32_t        bhsdo_expstatsn;
        uint32_t        bhsdo_reserved3;
        uint32_t        bhsdo_datasn;
        uint32_t        bhsdo_buffer_offset;
        uint32_t        bhsdo_reserved4;
};
CTASSERT(sizeof(struct iscsi_bhs_data_out) == ISCSI_BHS_SIZE);

#define BHSDI_FLAGS_F   0x80
#define BHSDI_FLAGS_A   0x40
#define BHSDI_FLAGS_O   0x04
#define BHSDI_FLAGS_U   0x02
#define BHSDI_FLAGS_S   0x01

struct iscsi_bhs_data_in {
        uint8_t         bhsdi_opcode;
        uint8_t         bhsdi_flags;
        uint8_t         bhsdi_reserved;
        uint8_t         bhsdi_status;
        uint8_t         bhsdi_total_ahs_len;
        uint8_t         bhsdi_data_segment_len[3];
        uint64_t        bhsdi_lun;
        uint32_t        bhsdi_initiator_task_tag;
        uint32_t        bhsdi_target_transfer_tag;
        uint32_t        bhsdi_statsn;
        uint32_t        bhsdi_expcmdsn;
        uint32_t        bhsdi_maxcmdsn;
        uint32_t        bhsdi_datasn;
        uint32_t        bhsdi_buffer_offset;
        uint32_t        bhsdi_residual_count;
};
CTASSERT(sizeof(struct iscsi_bhs_data_in) == ISCSI_BHS_SIZE);

struct iscsi_bhs_r2t {
        uint8_t         bhsr2t_opcode;
        uint8_t         bhsr2t_flags;
        uint16_t        bhsr2t_reserved;
        uint8_t         bhsr2t_total_ahs_len;
        uint8_t         bhsr2t_data_segment_len[3];
        uint64_t        bhsr2t_lun;
        uint32_t        bhsr2t_initiator_task_tag;
        uint32_t        bhsr2t_target_transfer_tag;
        uint32_t        bhsr2t_statsn;
        uint32_t        bhsr2t_expcmdsn;
        uint32_t        bhsr2t_maxcmdsn;
        uint32_t        bhsr2t_r2tsn;
        uint32_t        bhsr2t_buffer_offset;
        uint32_t        bhsr2t_desired_data_transfer_length;
};
CTASSERT(sizeof(struct iscsi_bhs_r2t) == ISCSI_BHS_SIZE);

struct iscsi_bhs_nop_out {
        uint8_t         bhsno_opcode;
        uint8_t         bhsno_flags;
        uint16_t        bhsno_reserved;
        uint8_t         bhsno_total_ahs_len;
        uint8_t         bhsno_data_segment_len[3];
        uint64_t        bhsno_lun;
        uint32_t        bhsno_initiator_task_tag;
        uint32_t        bhsno_target_transfer_tag;
        uint32_t        bhsno_cmdsn;
        uint32_t        bhsno_expstatsn;
        uint8_t         bhsno_reserved2[16];
};
CTASSERT(sizeof(struct iscsi_bhs_nop_out) == ISCSI_BHS_SIZE);

struct iscsi_bhs_nop_in {
        uint8_t         bhsni_opcode;
        uint8_t         bhsni_flags;
        uint16_t        bhsni_reserved;
        uint8_t         bhsni_total_ahs_len;
        uint8_t         bhsni_data_segment_len[3];
        uint64_t        bhsni_lun;
        uint32_t        bhsni_initiator_task_tag;
        uint32_t        bhsni_target_transfer_tag;
        uint32_t        bhsni_statsn;
        uint32_t        bhsni_expcmdsn;
        uint32_t        bhsni_maxcmdsn;
        uint8_t         bhsno_reserved2[12];
};
CTASSERT(sizeof(struct iscsi_bhs_nop_in) == ISCSI_BHS_SIZE);

#define BHSLR_REASON_CLOSE_SESSION              0
#define BHSLR_REASON_CLOSE_CONNECTION           1
#define BHSLR_REASON_REMOVE_FOR_RECOVERY        2

struct iscsi_bhs_logout_request {
        uint8_t         bhslr_opcode;
        uint8_t         bhslr_reason;
        uint16_t        bhslr_reserved;
        uint8_t         bhslr_total_ahs_len;
        uint8_t         bhslr_data_segment_len[3];
        uint64_t        bhslr_reserved2;
        uint32_t        bhslr_initiator_task_tag;
        uint16_t        bhslr_cid;
        uint16_t        bhslr_reserved3;
        uint32_t        bhslr_cmdsn;
        uint32_t        bhslr_expstatsn;
        uint8_t         bhslr_reserved4[16];
};
CTASSERT(sizeof(struct iscsi_bhs_logout_request) == ISCSI_BHS_SIZE);

#define BHSLR_RESPONSE_CLOSED_SUCCESSFULLY      0
#define BHSLR_RESPONSE_RECOVERY_NOT_SUPPORTED   2

struct iscsi_bhs_logout_response {
        uint8_t         bhslr_opcode;
        uint8_t         bhslr_flags;
        uint8_t         bhslr_response;
        uint8_t         bhslr_reserved;
        uint8_t         bhslr_total_ahs_len;
        uint8_t         bhslr_data_segment_len[3];
        uint64_t        bhslr_reserved2;
        uint32_t        bhslr_initiator_task_tag;
        uint32_t        bhslr_reserved3;
        uint32_t        bhslr_statsn;
        uint32_t        bhslr_expcmdsn;
        uint32_t        bhslr_maxcmdsn;
        uint32_t        bhslr_reserved4;
        uint16_t        bhslr_time2wait;
        uint16_t        bhslr_time2retain;
        uint32_t        bhslr_reserved5;
};
CTASSERT(sizeof(struct iscsi_bhs_logout_response) == ISCSI_BHS_SIZE);

#define BHSAM_EVENT_TARGET_REQUESTS_LOGOUT              1
#define BHSAM_EVENT_TARGET_TERMINATES_CONNECTION        2
#define BHSAM_EVENT_TARGET_TERMINATES_SESSION           3

struct iscsi_bhs_asynchronous_message {
        uint8_t         bhsam_opcode;
        uint8_t         bhsam_flags;
        uint16_t        bhsam_reserved;
        uint8_t         bhsam_total_ahs_len;
        uint8_t         bhsam_data_segment_len[3];
        uint64_t        bhsam_lun;
        uint32_t        bhsam_0xffffffff;
        uint32_t        bhsam_reserved2;
        uint32_t        bhsam_statsn;
        uint32_t        bhsam_expcmdsn;
        uint32_t        bhsam_maxcmdsn;
        uint8_t         bhsam_async_event;
        uint8_t         bhsam_async_vcode;
        uint16_t        bhsam_parameter1;
        uint16_t        bhsam_parameter2;
        uint16_t        bhsam_parameter3;
        uint32_t        bhsam_reserved3;
};
CTASSERT(sizeof(struct iscsi_bhs_asynchronous_message) == ISCSI_BHS_SIZE);

#define BHSSR_REASON_DATA_DIGEST_ERROR  0x02
#define BHSSR_PROTOCOL_ERROR            0x04
#define BHSSR_COMMAND_NOT_SUPPORTED     0x05
#define BHSSR_INVALID_PDU_FIELD         0x09

struct iscsi_bhs_reject {
        uint8_t         bhsr_opcode;
        uint8_t         bhsr_flags;
        uint8_t         bhsr_reason;
        uint8_t         bhsr_reserved;
        uint8_t         bhsr_total_ahs_len;
        uint8_t         bhsr_data_segment_len[3];
        uint64_t        bhsr_reserved2;
        uint32_t        bhsr_0xffffffff;
        uint32_t        bhsr_reserved3;
        uint32_t        bhsr_statsn;
        uint32_t        bhsr_expcmdsn;
        uint32_t        bhsr_maxcmdsn;
        uint32_t        bhsr_datasn_r2tsn;
        uint32_t        bhsr_reserved4;
        uint32_t        bhsr_reserved5;
};
CTASSERT(sizeof(struct iscsi_bhs_reject) == ISCSI_BHS_SIZE);

#endif /* !ISCSI_PROTO_H */