1 /* 2 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #ifndef ISTGT_ISCSI_H 29 #define ISTGT_ISCSI_H 30 31 #include <stdint.h> 32 #include <pthread.h> 33 #include "istgt.h" 34 #include "istgt_iscsi_param.h" 35 #include "istgt_lu.h" 36 #include "istgt_queue.h" 37 38 #define ISCSI_BHS_LEN 48 39 #define ISCSI_DIGEST_LEN 4 40 #define ISCSI_ALIGNMENT 4 41 /* support version - RFC3720(10.12.4) */ 42 #define ISCSI_VERSION 0x00 43 44 #define ISCSI_ALIGN(SIZE) \ 45 (((SIZE) + (ISCSI_ALIGNMENT - 1)) & ~(ISCSI_ALIGNMENT - 1)) 46 47 #define ISCSI_TEXT_MAX_KEY_LEN 64 48 /* for authentication key (non encoded 1024bytes) RFC3720(5.1/11.1.4) */ 49 #define ISCSI_TEXT_MAX_VAL_LEN 8192 50 51 #define SESS_MTX_LOCK(CONN) \ 52 do { \ 53 if (pthread_mutex_lock(&(CONN)->sess->mutex) != 0) { \ 54 ISTGT_ERRLOG("sess lock error\n"); \ 55 pthread_exit(NULL); \ 56 } \ 57 } while (0) 58 #define SESS_MTX_UNLOCK(CONN) \ 59 do { \ 60 if (pthread_mutex_unlock(&(CONN)->sess->mutex) != 0) { \ 61 ISTGT_ERRLOG("sess unlock error\n"); \ 62 pthread_exit(NULL); \ 63 } \ 64 } while (0) 65 66 typedef enum { 67 /* Initiator opcodes */ 68 ISCSI_OP_NOPOUT = 0x00, 69 ISCSI_OP_SCSI = 0x01, 70 ISCSI_OP_TASK = 0x02, 71 ISCSI_OP_LOGIN = 0x03, 72 ISCSI_OP_TEXT = 0x04, 73 ISCSI_OP_SCSI_DATAOUT = 0x05, 74 ISCSI_OP_LOGOUT = 0x06, 75 ISCSI_OP_SNACK = 0x10, 76 ISCSI_OP_VENDOR_1C = 0x1c, 77 ISCSI_OP_VENDOR_1D = 0x1d, 78 ISCSI_OP_VENDOR_1E = 0x1e, 79 80 /* Target opcodes */ 81 ISCSI_OP_NOPIN = 0x20, 82 ISCSI_OP_SCSI_RSP = 0x21, 83 ISCSI_OP_TASK_RSP = 0x22, 84 ISCSI_OP_LOGIN_RSP = 0x23, 85 ISCSI_OP_TEXT_RSP = 0x24, 86 ISCSI_OP_SCSI_DATAIN = 0x25, 87 ISCSI_OP_LOGOUT_RSP = 0x26, 88 ISCSI_OP_R2T = 0x31, 89 ISCSI_OP_ASYNC = 0x32, 90 ISCSI_OP_VENDOR_3C = 0x3c, 91 ISCSI_OP_VENDOR_3D = 0x3d, 92 ISCSI_OP_VENDOR_3E = 0x3e, 93 ISCSI_OP_REJECT = 0x3f, 94 } ISCSI_OP; 95 96 typedef enum { 97 ISCSI_TASK_FUNC_ABORT_TASK = 1, 98 ISCSI_TASK_FUNC_ABORT_TASK_SET = 2, 99 ISCSI_TASK_FUNC_CLEAR_ACA = 3, 100 ISCSI_TASK_FUNC_CLEAR_TASK_SET = 4, 101 ISCSI_TASK_FUNC_LOGICAL_UNIT_RESET = 5, 102 ISCSI_TASK_FUNC_TARGET_WARM_RESET = 6, 103 ISCSI_TASK_FUNC_TARGET_COLD_RESET = 7, 104 ISCSI_TASK_FUNC_TASK_REASSIGN = 8, 105 } ISCSI_TASK_FUNC; 106 107 typedef struct iscsi_bhs_t { 108 /* 0-3 */ 109 uint8_t opcode; 110 uint8_t opcode_specific1[3]; 111 /* 4-7 */ 112 uint8_t total_ahs_len; 113 uint8_t data_segment_len[3]; 114 /* 8-11 */ 115 union { 116 uint8_t lun1[4]; 117 uint8_t opcode_specific2[4]; 118 } u1; 119 /* 12-15 */ 120 union { 121 uint8_t lun2[4]; 122 uint8_t opcode_specific3[4]; 123 } u2; 124 /* 16-19 */ 125 uint8_t inititator_task_tag[4]; 126 /* 20-47 */ 127 uint8_t opcode_specific4[28]; 128 } ISCSI_BHS; 129 130 typedef struct iscsi_ahs_t { 131 /* 0-3 */ 132 uint8_t ahs_len[2]; 133 uint8_t ahs_type; 134 uint8_t ahs_specific1; 135 /* 4-x */ 136 uint8_t ahs_specific2[]; 137 } ISCSI_AHS; 138 139 typedef struct iscsi_pdu_t { 140 ISCSI_BHS bhs; 141 ISCSI_AHS *ahs; 142 uint8_t header_digest[ISCSI_DIGEST_LEN]; 143 uint8_t shortdata[ISTGT_SHORTDATASIZE]; 144 uint8_t *data; 145 uint8_t data_digest[ISCSI_DIGEST_LEN]; 146 size_t total_ahs_len; 147 size_t data_segment_len; 148 int copy_pdu; 149 } ISCSI_PDU; 150 typedef ISCSI_PDU *ISCSI_PDU_Ptr; 151 152 typedef enum { 153 CONN_STATE_INVALID = 0, 154 CONN_STATE_RUNNING = 1, 155 CONN_STATE_EXITING = 2, 156 CONN_STATE_SHUTDOWN = 3, 157 } CONN_STATE; 158 159 typedef enum { 160 ISCSI_LOGIN_PHASE_NONE = 0, 161 ISCSI_LOGIN_PHASE_START = 1, 162 ISCSI_LOGIN_PHASE_SECURITY = 2, 163 ISCSI_LOGIN_PHASE_OPERATIONAL = 3, 164 ISCSI_LOGIN_PHASE_FULLFEATURE = 4, 165 } ISCSI_LOGIN_PHASE; 166 167 typedef enum { 168 ISTGT_CHAP_PHASE_NONE = 0, 169 ISTGT_CHAP_PHASE_WAIT_A = 1, 170 ISTGT_CHAP_PHASE_WAIT_NR = 2, 171 ISTGT_CHAP_PHASE_END = 3, 172 } ISTGT_CHAP_PHASE; 173 174 #define ISTGT_CHAP_CHALLENGE_LEN 1024 175 typedef struct istgt_chap_auth_t { 176 ISTGT_CHAP_PHASE chap_phase; 177 178 char *user; 179 char *secret; 180 char *muser; 181 char *msecret; 182 183 uint8_t chap_id[1]; 184 uint8_t chap_mid[1]; 185 int chap_challenge_len; 186 uint8_t chap_challenge[ISTGT_CHAP_CHALLENGE_LEN]; 187 int chap_mchallenge_len; 188 uint8_t chap_mchallenge[ISTGT_CHAP_CHALLENGE_LEN]; 189 } ISTGT_CHAP_AUTH; 190 191 typedef struct istgt_r2t_task_t { 192 struct istgt_conn_t *conn; 193 ISTGT_LU_Ptr lu; 194 uint64_t lun; 195 uint32_t CmdSN; 196 uint32_t task_tag; 197 uint32_t transfer_len; 198 uint32_t transfer_tag; 199 200 int iobufsize; 201 uint8_t *iobuf; 202 203 uint32_t R2TSN; 204 uint32_t DataSN; 205 int F_bit; 206 int offset; 207 } ISTGT_R2T_TASK; 208 typedef ISTGT_R2T_TASK *ISTGT_R2T_TASK_Ptr; 209 210 typedef struct istgt_conn_t { 211 int id; 212 213 ISTGT_Ptr istgt; 214 PORTAL portal; 215 int sock; 216 int wsock; 217 #ifdef ISTGT_USE_KQUEUE 218 int kq; 219 #endif /* ISTGT_USE_KQUEUE */ 220 int use_sender; 221 pthread_t thread; 222 pthread_t sender_thread; 223 pthread_mutex_t sender_mutex; 224 pthread_cond_t sender_cond; 225 struct istgt_sess_t *sess; 226 227 CONN_STATE state; 228 int exec_logout; 229 230 int max_pending; 231 int queue_depth; 232 pthread_mutex_t wpdu_mutex; 233 pthread_cond_t wpdu_cond; 234 ISTGT_QUEUE pending_pdus; 235 ISCSI_PDU pdu; 236 237 int max_r2t; 238 int pending_r2t; 239 pthread_mutex_t r2t_mutex; 240 ISTGT_R2T_TASK_Ptr *r2t_tasks; 241 242 int task_pipe[2]; 243 int max_task_queue; 244 pthread_mutex_t task_queue_mutex; 245 ISTGT_QUEUE task_queue; 246 pthread_mutex_t result_queue_mutex; 247 pthread_cond_t result_queue_cond; 248 ISTGT_QUEUE result_queue; 249 ISTGT_LU_TASK_Ptr exec_lu_task; 250 int running_tasks; 251 252 uint16_t cid; 253 254 /* IP address */ 255 int initiator_family; 256 char initiator_addr[MAX_INITIATOR_ADDR]; 257 char target_addr[MAX_TARGET_ADDR]; 258 259 /* Initiator/Target port binds */ 260 char initiator_name[MAX_INITIATOR_NAME]; 261 char target_name[MAX_TARGET_NAME]; 262 char initiator_port[MAX_INITIATOR_NAME]; 263 char target_port[MAX_TARGET_NAME]; 264 265 /* for fast access */ 266 int header_digest; 267 int data_digest; 268 int full_feature; 269 270 ISCSI_PARAM *params; 271 ISCSI_LOGIN_PHASE login_phase; 272 ISTGT_CHAP_AUTH auth; 273 int authenticated; 274 int req_auth; 275 int req_mutual; 276 277 int timeout; 278 int nopininterval; 279 280 int TargetMaxRecvDataSegmentLength; 281 int MaxRecvDataSegmentLength; 282 int MaxOutstandingR2T; 283 int FirstBurstLength; 284 int MaxBurstLength; 285 286 int shortpdusize; 287 uint8_t *shortpdu; 288 289 int iobufsize; 290 uint8_t *iobuf; 291 int snsbufsize; 292 uint8_t *snsbuf; 293 294 int recvbufsize; 295 int sendbufsize; 296 uint8_t *recvbuf; 297 uint8_t *sendbuf; 298 299 int worksize; 300 uint8_t *workbuf; 301 302 uint32_t StatSN; 303 } CONN; 304 typedef CONN *CONN_Ptr; 305 306 typedef struct istgt_sess_t { 307 int connections; 308 int max_conns; 309 CONN_Ptr *conns; 310 311 pthread_mutex_t mutex; 312 pthread_cond_t mcs_cond; 313 int req_mcs_cond; 314 315 char *initiator_port; 316 char *target_name; 317 int tag; 318 319 uint64_t isid; 320 uint16_t tsih; 321 ISTGT_LU_Ptr lu; 322 323 ISCSI_PARAM *params; 324 325 int MaxConnections; 326 int MaxOutstandingR2T; 327 int DefaultTime2Wait; 328 int DefaultTime2Retain; 329 int FirstBurstLength; 330 int MaxBurstLength; 331 int InitialR2T; 332 int ImmediateData; 333 int DataPDUInOrder; 334 int DataSequenceInOrder; 335 int ErrorRecoveryLevel; 336 337 int initial_r2t; 338 int immediate_data; 339 340 uint32_t ExpCmdSN; 341 uint32_t MaxCmdSN; 342 } SESS; 343 typedef SESS *SESS_Ptr; 344 345 #endif /* ISTGT_ISCSI_H */ 346