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