1 /* 2 Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com> 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as published by 6 the Free Software Foundation; either version 2.1 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public License 15 along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 #ifndef __iscsi_private_h__ 18 #define __iscsi_private_h__ 19 20 #include <stdint.h> 21 #include <time.h> 22 23 #if defined(_WIN32) 24 #include <basetsd.h> 25 #define ssize_t SSIZE_T 26 #endif 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 #ifndef discard_const 33 #define discard_const(ptr) ((void *)((intptr_t)(ptr))) 34 #endif 35 36 #ifndef MIN 37 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 38 #endif 39 #ifndef MAX 40 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 41 #endif 42 43 #define ISCSI_RAW_HEADER_SIZE 48 44 #define ISCSI_DIGEST_SIZE 4 45 46 #define ISCSI_HEADER_SIZE(hdr_digest) (ISCSI_RAW_HEADER_SIZE \ 47 + (hdr_digest == ISCSI_HEADER_DIGEST_NONE?0:ISCSI_DIGEST_SIZE)) 48 49 #define SMALL_ALLOC_MAX_FREE (128) /* must be power of 2 */ 50 51 struct iscsi_in_pdu { 52 struct iscsi_in_pdu *next; 53 54 long long hdr_pos; 55 unsigned char *hdr; 56 57 long long data_pos; 58 unsigned char *data; 59 }; 60 void iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in); 61 62 /* size of chap response field */ 63 #define CHAP_R_SIZE 16 64 65 /* max length of chap challange */ 66 #define MAX_CHAP_C_LENGTH 2048 67 68 struct iscsi_context { 69 struct iscsi_transport *drv; 70 void *opaque; 71 enum iscsi_transport_type transport; 72 73 char initiator_name[MAX_STRING_SIZE+1]; 74 char target_name[MAX_STRING_SIZE+1]; 75 char target_address[MAX_STRING_SIZE+1]; /* If a redirect */ 76 char connected_portal[MAX_STRING_SIZE+1]; 77 char portal[MAX_STRING_SIZE+1]; 78 char alias[MAX_STRING_SIZE+1]; 79 char bind_interfaces[MAX_STRING_SIZE+1]; 80 81 char user[MAX_STRING_SIZE+1]; 82 char passwd[MAX_STRING_SIZE+1]; 83 char chap_c[MAX_CHAP_C_LENGTH+1]; 84 85 char target_user[MAX_STRING_SIZE+1]; 86 char target_passwd[MAX_STRING_SIZE+1]; 87 uint32_t target_chap_i; 88 unsigned char target_chap_r[CHAP_R_SIZE]; 89 90 char error_string[MAX_STRING_SIZE+1]; 91 92 enum iscsi_session_type session_type; 93 unsigned char isid[6]; 94 uint32_t itt; 95 uint32_t cmdsn; 96 uint32_t min_cmdsn_waiting; 97 uint32_t expcmdsn; 98 uint32_t maxcmdsn; 99 uint32_t statsn; 100 enum iscsi_header_digest want_header_digest; 101 enum iscsi_header_digest header_digest; 102 103 int fd; 104 int is_connected; 105 int is_corked; 106 107 int tcp_user_timeout; 108 int tcp_keepcnt; 109 int tcp_keepintvl; 110 int tcp_keepidle; 111 int tcp_syncnt; 112 int tcp_nonblocking; 113 114 int current_phase; 115 int next_phase; 116 #define ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP 0 117 #define ISCSI_LOGIN_SECNEG_PHASE_SELECT_ALGORITHM 1 118 #define ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE 2 119 int secneg_phase; 120 int login_attempts; 121 int is_loggedin; 122 int bind_interfaces_cnt; 123 int nops_in_flight; 124 125 int chap_a; 126 int chap_i; 127 128 iscsi_command_cb socket_status_cb; 129 void *connect_data; 130 131 struct iscsi_pdu *outqueue; 132 struct iscsi_pdu *outqueue_current; 133 struct iscsi_pdu *waitpdu; 134 135 struct iscsi_in_pdu *incoming; 136 137 uint32_t max_burst_length; 138 uint32_t first_burst_length; 139 uint32_t initiator_max_recv_data_segment_length; 140 uint32_t target_max_recv_data_segment_length; 141 enum iscsi_initial_r2t want_initial_r2t; 142 enum iscsi_initial_r2t use_initial_r2t; 143 enum iscsi_immediate_data want_immediate_data; 144 enum iscsi_immediate_data use_immediate_data; 145 146 int lun; 147 int no_auto_reconnect; 148 int reconnect_deferred; 149 int reconnect_max_retries; 150 int pending_reconnect; 151 152 int log_level; 153 iscsi_log_fn log_fn; 154 155 int mallocs; 156 int reallocs; 157 int frees; 158 int smallocs; 159 void* smalloc_ptrs[SMALL_ALLOC_MAX_FREE]; 160 int smalloc_free; 161 size_t smalloc_size; 162 int cache_allocations; 163 164 time_t next_reconnect; 165 int scsi_timeout; 166 struct iscsi_context *old_iscsi; 167 int retry_cnt; 168 int no_ua_on_reconnect; 169 }; 170 171 #define ISCSI_PDU_IMMEDIATE 0x40 172 173 #define ISCSI_PDU_TEXT_FINAL 0x80 174 #define ISCSI_PDU_TEXT_CONTINUE 0x40 175 176 #define ISCSI_PDU_LOGIN_TRANSIT 0x80 177 #define ISCSI_PDU_LOGIN_CONTINUE 0x40 178 #define ISCSI_PDU_LOGIN_CSG_SECNEG 0x00 179 #define ISCSI_PDU_LOGIN_CSG_OPNEG 0x04 180 #define ISCSI_PDU_LOGIN_CSG_FF 0x0c 181 #define ISCSI_PDU_LOGIN_NSG_SECNEG 0x00 182 #define ISCSI_PDU_LOGIN_NSG_OPNEG 0x01 183 #define ISCSI_PDU_LOGIN_NSG_FF 0x03 184 185 #define ISCSI_PDU_SCSI_FINAL 0x80 186 #define ISCSI_PDU_SCSI_READ 0x40 187 #define ISCSI_PDU_SCSI_WRITE 0x20 188 #define ISCSI_PDU_SCSI_ATTR_UNTAGGED 0x00 189 #define ISCSI_PDU_SCSI_ATTR_SIMPLE 0x01 190 #define ISCSI_PDU_SCSI_ATTR_ORDERED 0x02 191 #define ISCSI_PDU_SCSI_ATTR_HEADOFQUEUE 0x03 192 #define ISCSI_PDU_SCSI_ATTR_ACA 0x04 193 194 #define ISCSI_PDU_DATA_FINAL 0x80 195 #define ISCSI_PDU_DATA_ACK_REQUESTED 0x40 196 #define ISCSI_PDU_DATA_BIDIR_OVERFLOW 0x10 197 #define ISCSI_PDU_DATA_BIDIR_UNDERFLOW 0x08 198 #define ISCSI_PDU_DATA_RESIDUAL_OVERFLOW 0x04 199 #define ISCSI_PDU_DATA_RESIDUAL_UNDERFLOW 0x02 200 #define ISCSI_PDU_DATA_CONTAINS_STATUS 0x01 201 202 enum iscsi_opcode { 203 ISCSI_PDU_NOP_OUT = 0x00, 204 ISCSI_PDU_SCSI_REQUEST = 0x01, 205 ISCSI_PDU_SCSI_TASK_MANAGEMENT_REQUEST = 0x02, 206 ISCSI_PDU_LOGIN_REQUEST = 0x03, 207 ISCSI_PDU_TEXT_REQUEST = 0x04, 208 ISCSI_PDU_DATA_OUT = 0x05, 209 ISCSI_PDU_LOGOUT_REQUEST = 0x06, 210 ISCSI_PDU_NOP_IN = 0x20, 211 ISCSI_PDU_SCSI_RESPONSE = 0x21, 212 ISCSI_PDU_SCSI_TASK_MANAGEMENT_RESPONSE = 0x22, 213 ISCSI_PDU_LOGIN_RESPONSE = 0x23, 214 ISCSI_PDU_TEXT_RESPONSE = 0x24, 215 ISCSI_PDU_DATA_IN = 0x25, 216 ISCSI_PDU_LOGOUT_RESPONSE = 0x26, 217 ISCSI_PDU_R2T = 0x31, 218 ISCSI_PDU_ASYNC_MSG = 0x32, 219 ISCSI_PDU_REJECT = 0x3f, 220 ISCSI_PDU_NO_PDU = 0xff 221 }; 222 223 struct iscsi_scsi_cbdata { 224 iscsi_command_cb callback; 225 void *private_data; 226 struct scsi_task *task; 227 }; 228 229 struct iscsi_pdu { 230 struct iscsi_pdu *next; 231 232 /* There will not be a response to this pdu, so delete it once it is sent on the wire. Don't put it on the wait-queue */ 233 #define ISCSI_PDU_DELETE_WHEN_SENT 0x00000001 234 /* When reconnecting, just drop all these PDUs. Don't re-queue them. 235 * This includes any DATA-OUT PDU as well as all NOPs. 236 */ 237 #define ISCSI_PDU_DROP_ON_RECONNECT 0x00000004 238 /* stop sending after this PDU has been sent */ 239 #define ISCSI_PDU_CORK_WHEN_SENT 0x00000008 240 241 uint32_t flags; 242 243 uint32_t lun; 244 uint32_t itt; 245 uint32_t cmdsn; 246 uint32_t datasn; 247 enum iscsi_opcode response_opcode; 248 249 iscsi_command_cb callback; 250 void *private_data; 251 252 /* Used to track writing the iscsi header to the socket */ 253 struct iscsi_data outdata; /* Header for PDU to send */ 254 size_t outdata_written; /* How much of the header we have written */ 255 256 /* Used to track writing the payload data to the socket */ 257 uint32_t payload_offset; /* Offset of payload data to write */ 258 uint32_t payload_len; /* Amount of payload data to write */ 259 uint32_t payload_written; /* How much of the payload we have written */ 260 261 262 struct iscsi_data indata; 263 264 struct iscsi_scsi_cbdata scsi_cbdata; 265 time_t scsi_timeout; 266 uint32_t expxferlen; 267 }; 268 269 struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi, 270 enum iscsi_opcode opcode, 271 enum iscsi_opcode response_opcode, 272 uint32_t itt, 273 uint32_t flags); 274 void iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); 275 void iscsi_pdu_set_pduflags(struct iscsi_pdu *pdu, unsigned char flags); 276 void iscsi_pdu_set_immediate(struct iscsi_pdu *pdu); 277 void iscsi_pdu_set_ttt(struct iscsi_pdu *pdu, uint32_t ttt); 278 void iscsi_pdu_set_cmdsn(struct iscsi_pdu *pdu, uint32_t cmdsn); 279 void iscsi_pdu_set_rcmdsn(struct iscsi_pdu *pdu, uint32_t rcmdsn); 280 void iscsi_pdu_set_lun(struct iscsi_pdu *pdu, uint32_t lun); 281 void iscsi_pdu_set_expstatsn(struct iscsi_pdu *pdu, uint32_t expstatsnsn); 282 void iscsi_pdu_set_expxferlen(struct iscsi_pdu *pdu, uint32_t expxferlen); 283 void iscsi_pdu_set_itt(struct iscsi_pdu *pdu, uint32_t itt); 284 void iscsi_pdu_set_ritt(struct iscsi_pdu *pdu, uint32_t ritt); 285 void iscsi_pdu_set_datasn(struct iscsi_pdu *pdu, uint32_t datasn); 286 void iscsi_pdu_set_bufferoffset(struct iscsi_pdu *pdu, uint32_t bufferoffset); 287 void iscsi_cancel_pdus(struct iscsi_context *iscsi); 288 int iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, 289 unsigned char *dptr, int dsize); 290 int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); 291 int iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data, 292 unsigned char *dptr, int dsize, int pdualignment); 293 294 struct scsi_task; 295 void iscsi_pdu_set_cdb(struct iscsi_pdu *pdu, struct scsi_task *task); 296 297 int iscsi_get_pdu_data_size(const unsigned char *hdr); 298 int iscsi_get_pdu_padding_size(const unsigned char *hdr); 299 int iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in); 300 301 int iscsi_process_login_reply(struct iscsi_context *iscsi, 302 struct iscsi_pdu *pdu, 303 struct iscsi_in_pdu *in); 304 int iscsi_process_text_reply(struct iscsi_context *iscsi, 305 struct iscsi_pdu *pdu, 306 struct iscsi_in_pdu *in); 307 int iscsi_process_logout_reply(struct iscsi_context *iscsi, 308 struct iscsi_pdu *pdu, 309 struct iscsi_in_pdu *in); 310 int iscsi_process_scsi_reply(struct iscsi_context *iscsi, 311 struct iscsi_pdu *pdu, 312 struct iscsi_in_pdu *in); 313 int iscsi_process_scsi_data_in(struct iscsi_context *iscsi, 314 struct iscsi_pdu *pdu, 315 struct iscsi_in_pdu *in, 316 int *is_finished); 317 int iscsi_process_nop_out_reply(struct iscsi_context *iscsi, 318 struct iscsi_pdu *pdu, 319 struct iscsi_in_pdu *in); 320 int iscsi_process_task_mgmt_reply(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, 321 struct iscsi_in_pdu *in); 322 int iscsi_process_r2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, 323 struct iscsi_in_pdu *in); 324 int iscsi_process_reject(struct iscsi_context *iscsi, 325 struct iscsi_in_pdu *in); 326 int iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt, uint32_t lun); 327 328 #if defined(_WIN32) 329 void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, 330 ...); 331 #else 332 void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, 333 ...) __attribute__((format(printf, 2, 3))); 334 #endif 335 336 struct scsi_iovector *iscsi_get_scsi_task_iovector_in(struct iscsi_context *iscsi, struct iscsi_in_pdu *in); 337 struct scsi_iovector *iscsi_get_scsi_task_iovector_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); 338 void scsi_task_reset_iov(struct scsi_iovector *iovector); 339 340 void* iscsi_malloc(struct iscsi_context *iscsi, size_t size); 341 void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size); 342 void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size); 343 void iscsi_free(struct iscsi_context *iscsi, void* ptr); 344 char* iscsi_strdup(struct iscsi_context *iscsi, const char* str); 345 void* iscsi_smalloc(struct iscsi_context *iscsi, size_t size); 346 void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size); 347 void iscsi_sfree(struct iscsi_context *iscsi, void* ptr); 348 349 uint32_t crc32c(uint8_t *buf, int len); 350 351 struct scsi_task *iscsi_scsi_get_task_from_pdu(struct iscsi_pdu *pdu); 352 353 void iscsi_decrement_iface_rr(void); 354 355 #define ISCSI_LOG(iscsi, level, format, ...) \ 356 do { \ 357 if (level <= iscsi->log_level && iscsi->log_fn) { \ 358 iscsi_log_message(iscsi, level, format, ## __VA_ARGS__); \ 359 } \ 360 } while (0) 361 362 void 363 iscsi_log_message(struct iscsi_context *iscsi, int level, const char *format, ...); 364 365 void 366 iscsi_add_to_outqueue(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); 367 368 int iscsi_serial32_compare(uint32_t s1, uint32_t s2); 369 370 uint32_t iscsi_itt_post_increment(struct iscsi_context *iscsi); 371 372 void iscsi_timeout_scan(struct iscsi_context *iscsi); 373 374 void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status, 375 void *command_data, void *private_data); 376 377 struct iscsi_pdu *iscsi_tcp_new_pdu(struct iscsi_context *iscsi, size_t size); 378 379 void iscsi_init_tcp_transport(struct iscsi_context *iscsi); 380 381 void iscsi_tcp_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); 382 383 int iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi); 384 385 void iscsi_dump_pdu_header(struct iscsi_context *iscsi, unsigned char *data); 386 387 union socket_address; 388 389 typedef struct iscsi_transport { 390 int (*connect)(struct iscsi_context *iscsi, union socket_address *sa, int ai_family); 391 int (*queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); 392 struct iscsi_pdu* (*new_pdu)(struct iscsi_context *iscsi, size_t size); 393 int (*disconnect)(struct iscsi_context *iscsi); 394 void (*free_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu); 395 int (*service)(struct iscsi_context *iscsi, int revents); 396 int (*get_fd)(struct iscsi_context *iscsi); 397 int (*which_events)(struct iscsi_context *iscsi); 398 } iscsi_transport; 399 400 #ifdef __cplusplus 401 } 402 #endif 403 404 #endif /* __iscsi_private_h__ */ 405