/*
* Copyright (C) 2008-2011 Daisuke Aoyama <aoyama@peach.ne.jp>.
* All rights reserved.
*
* 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 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 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 ISTGT_ISCSI_H
#define ISTGT_ISCSI_H
#include <stdint.h>
#include <pthread.h>
#include "istgt.h"
#include "istgt_iscsi_param.h"
#include "istgt_lu.h"
#include "istgt_queue.h"
#define ISCSI_BHS_LEN 48
#define ISCSI_DIGEST_LEN 4
#define ISCSI_ALIGNMENT 4
/* support version - RFC3720(10.12.4) */
#define ISCSI_VERSION 0x00
#define ISCSI_ALIGN(SIZE) \
(((SIZE) + (ISCSI_ALIGNMENT - 1)) & ~(ISCSI_ALIGNMENT - 1))
#define ISCSI_TEXT_MAX_KEY_LEN 64
/* for authentication key (non encoded 1024bytes) RFC3720(5.1/11.1.4) */
#define ISCSI_TEXT_MAX_VAL_LEN 8192
#define SESS_MTX_LOCK(CONN) \
do { \
if (pthread_mutex_lock(&(CONN)->sess->mutex) != 0) { \
ISTGT_ERRLOG("sess lock error\n"); \
pthread_exit(NULL); \
} \
} while (0)
#define SESS_MTX_UNLOCK(CONN) \
do { \
if (pthread_mutex_unlock(&(CONN)->sess->mutex) != 0) { \
ISTGT_ERRLOG("sess unlock error\n"); \
pthread_exit(NULL); \
} \
} while (0)
typedef enum {
/* Initiator opcodes */
ISCSI_OP_NOPOUT = 0x00,
ISCSI_OP_SCSI = 0x01,
ISCSI_OP_TASK = 0x02,
ISCSI_OP_LOGIN = 0x03,
ISCSI_OP_TEXT = 0x04,
ISCSI_OP_SCSI_DATAOUT = 0x05,
ISCSI_OP_LOGOUT = 0x06,
ISCSI_OP_SNACK = 0x10,
ISCSI_OP_VENDOR_1C = 0x1c,
ISCSI_OP_VENDOR_1D = 0x1d,
ISCSI_OP_VENDOR_1E = 0x1e,
/* Target opcodes */
ISCSI_OP_NOPIN = 0x20,
ISCSI_OP_SCSI_RSP = 0x21,
ISCSI_OP_TASK_RSP = 0x22,
ISCSI_OP_LOGIN_RSP = 0x23,
ISCSI_OP_TEXT_RSP = 0x24,
ISCSI_OP_SCSI_DATAIN = 0x25,
ISCSI_OP_LOGOUT_RSP = 0x26,
ISCSI_OP_R2T = 0x31,
ISCSI_OP_ASYNC = 0x32,
ISCSI_OP_VENDOR_3C = 0x3c,
ISCSI_OP_VENDOR_3D = 0x3d,
ISCSI_OP_VENDOR_3E = 0x3e,
ISCSI_OP_REJECT = 0x3f,
} ISCSI_OP;
typedef enum {
ISCSI_TASK_FUNC_ABORT_TASK = 1,
ISCSI_TASK_FUNC_ABORT_TASK_SET = 2,
ISCSI_TASK_FUNC_CLEAR_ACA = 3,
ISCSI_TASK_FUNC_CLEAR_TASK_SET = 4,
ISCSI_TASK_FUNC_LOGICAL_UNIT_RESET = 5,
ISCSI_TASK_FUNC_TARGET_WARM_RESET = 6,
ISCSI_TASK_FUNC_TARGET_COLD_RESET = 7,
ISCSI_TASK_FUNC_TASK_REASSIGN = 8,
} ISCSI_TASK_FUNC;
typedef struct iscsi_bhs_t {
/* 0-3 */
uint8_t opcode;
uint8_t opcode_specific1[3];
/* 4-7 */
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
/* 8-11 */
union {
uint8_t lun1[4];
uint8_t opcode_specific2[4];
} u1;
/* 12-15 */
union {
uint8_t lun2[4];
uint8_t opcode_specific3[4];
} u2;
/* 16-19 */
uint8_t inititator_task_tag[4];
/* 20-47 */
uint8_t opcode_specific4[28];
} ISCSI_BHS;
typedef struct iscsi_ahs_t {
/* 0-3 */
uint8_t ahs_len[2];
uint8_t ahs_type;
uint8_t ahs_specific1;
/* 4-x */
uint8_t ahs_specific2[];
} ISCSI_AHS;
typedef struct iscsi_pdu_t {
ISCSI_BHS bhs;
ISCSI_AHS *ahs;
uint8_t header_digest[ISCSI_DIGEST_LEN];
uint8_t shortdata[ISTGT_SHORTDATASIZE];
uint8_t *data;
uint8_t data_digest[ISCSI_DIGEST_LEN];
int total_ahs_len;
int data_segment_len;
int copy_pdu;
} ISCSI_PDU;
typedef ISCSI_PDU *ISCSI_PDU_Ptr;
typedef enum {
CONN_STATE_INVALID = 0,
CONN_STATE_RUNNING = 1,
CONN_STATE_EXITING = 2,
CONN_STATE_SHUTDOWN = 3,
} CONN_STATE;
typedef enum {
ISCSI_LOGIN_PHASE_NONE = 0,
ISCSI_LOGIN_PHASE_START = 1,
ISCSI_LOGIN_PHASE_SECURITY = 2,
ISCSI_LOGIN_PHASE_OPERATIONAL = 3,
ISCSI_LOGIN_PHASE_FULLFEATURE = 4,
} ISCSI_LOGIN_PHASE;
typedef enum {
ISTGT_CHAP_PHASE_NONE = 0,
ISTGT_CHAP_PHASE_WAIT_A = 1,
ISTGT_CHAP_PHASE_WAIT_NR = 2,
ISTGT_CHAP_PHASE_END = 3,
} ISTGT_CHAP_PHASE;
#define ISTGT_CHAP_CHALLENGE_LEN 1024
typedef struct istgt_chap_auth_t {
ISTGT_CHAP_PHASE chap_phase;
char *user;
char *secret;
char *muser;
char *msecret;
uint8_t chap_id[1];
uint8_t chap_mid[1];
int chap_challenge_len;
uint8_t chap_challenge[ISTGT_CHAP_CHALLENGE_LEN];
int chap_mchallenge_len;
uint8_t chap_mchallenge[ISTGT_CHAP_CHALLENGE_LEN];
} ISTGT_CHAP_AUTH;
typedef struct istgt_r2t_task_t {
struct istgt_conn_t *conn;
ISTGT_LU_Ptr lu;
uint64_t lun;
uint32_t CmdSN;
uint32_t task_tag;
uint32_t transfer_len;
uint32_t transfer_tag;
int iobufsize;
uint8_t *iobuf;
uint32_t R2TSN;
uint32_t DataSN;
int F_bit;
int offset;
} ISTGT_R2T_TASK;
typedef ISTGT_R2T_TASK *ISTGT_R2T_TASK_Ptr;
typedef struct istgt_conn_t {
int id;
ISTGT_Ptr istgt;
PORTAL portal;
int sock;
int wsock;
#ifdef ISTGT_USE_KQUEUE
int kq;
#endif /* ISTGT_USE_KQUEUE */
int use_sender;
pthread_t thread;
pthread_t sender_thread;
pthread_mutex_t sender_mutex;
pthread_cond_t sender_cond;
struct istgt_sess_t *sess;
CONN_STATE state;
int exec_logout;
int max_pending;
int queue_depth;
pthread_mutex_t wpdu_mutex;
pthread_cond_t wpdu_cond;
ISTGT_QUEUE pending_pdus;
ISCSI_PDU pdu;
int max_r2t;
int pending_r2t;
pthread_mutex_t r2t_mutex;
ISTGT_R2T_TASK_Ptr *r2t_tasks;
int task_pipe[2];
int max_task_queue;
pthread_mutex_t task_queue_mutex;
ISTGT_QUEUE task_queue;
pthread_mutex_t result_queue_mutex;
pthread_cond_t result_queue_cond;
ISTGT_QUEUE result_queue;
ISTGT_LU_TASK_Ptr exec_lu_task;
int running_tasks;
uint16_t cid;
/* IP address */
int initiator_family;
char initiator_addr[MAX_INITIATOR_ADDR];
char target_addr[MAX_TARGET_ADDR];
/* Initiator/Target port binds */
char initiator_name[MAX_INITIATOR_NAME];
char target_name[MAX_TARGET_NAME];
char initiator_port[MAX_INITIATOR_NAME];
char target_port[MAX_TARGET_NAME];
/* for fast access */
int header_digest;
int data_digest;
int full_feature;
ISCSI_PARAM *params;
ISCSI_LOGIN_PHASE login_phase;
ISTGT_CHAP_AUTH auth;
int authenticated;
int req_auth;
int req_mutual;
int timeout;
int nopininterval;
int TargetMaxRecvDataSegmentLength;
int MaxRecvDataSegmentLength;
int MaxOutstandingR2T;
int FirstBurstLength;
int MaxBurstLength;
int shortpdusize;
uint8_t *shortpdu;
int iobufsize;
uint8_t *iobuf;
int snsbufsize;
uint8_t *snsbuf;
int recvbufsize;
int sendbufsize;
uint8_t *recvbuf;
uint8_t *sendbuf;
int worksize;
uint8_t *workbuf;
uint32_t StatSN;
} CONN;
typedef CONN *CONN_Ptr;
typedef struct istgt_sess_t {
int connections;
int max_conns;
CONN_Ptr *conns;
pthread_mutex_t mutex;
pthread_cond_t mcs_cond;
int req_mcs_cond;
char *initiator_port;
char *target_name;
int tag;
uint64_t isid;
uint16_t tsih;
ISTGT_LU_Ptr lu;
ISCSI_PARAM *params;
int MaxConnections;
int MaxOutstandingR2T;
int DefaultTime2Wait;
int DefaultTime2Retain;
int FirstBurstLength;
int MaxBurstLength;
int InitialR2T;
int ImmediateData;
int DataPDUInOrder;
int DataSequenceInOrder;
int ErrorRecoveryLevel;
int initial_r2t;
int immediate_data;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
} SESS;
typedef SESS *SESS_Ptr;
#endif /* ISTGT_ISCSI_H */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>