1/*-
2 * Copyright (c) 2012 The FreeBSD Foundation
3 * All rights reserved.
4 *
5 * This software was developed by Edward Tomasz Napierala under sponsorship
6 * from the FreeBSD Foundation.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31
32#ifndef ISCSI_PROTO_H
33#define	ISCSI_PROTO_H
34
35#ifndef CTASSERT
36#define CTASSERT(x)		_CTASSERT(x, __LINE__)
37#define _CTASSERT(x, y)		__CTASSERT(x, y)
38#define __CTASSERT(x, y)	typedef char __assert_ ## y [(x) ? 1 : -1]
39#endif
40
41#define	ISCSI_SNGT(x, y)	((int32_t)(x) - (int32_t)(y) > 0)
42#define	ISCSI_SNLT(x, y)	((int32_t)(x) - (int32_t)(y) < 0)
43
44#define	ISCSI_BHS_SIZE			48
45#define	ISCSI_HEADER_DIGEST_SIZE	4
46#define	ISCSI_DATA_DIGEST_SIZE		4
47
48#define	ISCSI_BHS_OPCODE_IMMEDIATE	0x40
49
50#define	ISCSI_BHS_OPCODE_NOP_OUT	0x00
51#define	ISCSI_BHS_OPCODE_SCSI_COMMAND	0x01
52#define	ISCSI_BHS_OPCODE_TASK_REQUEST	0x02
53#define	ISCSI_BHS_OPCODE_LOGIN_REQUEST	0x03
54#define	ISCSI_BHS_OPCODE_TEXT_REQUEST	0x04
55#define	ISCSI_BHS_OPCODE_SCSI_DATA_OUT	0x05
56#define	ISCSI_BHS_OPCODE_LOGOUT_REQUEST	0x06
57
58#define	ISCSI_BHS_OPCODE_NOP_IN		0x20
59#define	ISCSI_BHS_OPCODE_SCSI_RESPONSE	0x21
60#define	ISCSI_BHS_OPCODE_TASK_RESPONSE	0x22
61#define	ISCSI_BHS_OPCODE_LOGIN_RESPONSE	0x23
62#define	ISCSI_BHS_OPCODE_TEXT_RESPONSE	0x24
63#define	ISCSI_BHS_OPCODE_SCSI_DATA_IN	0x25
64#define	ISCSI_BHS_OPCODE_LOGOUT_RESPONSE	0x26
65#define	ISCSI_BHS_OPCODE_R2T		0x31
66#define	ISCSI_BHS_OPCODE_ASYNC_MESSAGE	0x32
67#define	ISCSI_BHS_OPCODE_REJECT		0x3f
68
69struct iscsi_bhs {
70	uint8_t		bhs_opcode;
71	uint8_t		bhs_opcode_specific1[3];
72	uint8_t		bhs_total_ahs_len;
73	uint8_t		bhs_data_segment_len[3];
74	uint64_t	bhs_lun;
75	uint8_t		bhs_inititator_task_tag[4];
76	uint8_t		bhs_opcode_specific4[28];
77};
78CTASSERT(sizeof(struct iscsi_bhs) == ISCSI_BHS_SIZE);
79
80#define	BHSSC_FLAGS_F		0x80
81#define	BHSSC_FLAGS_R		0x40
82#define	BHSSC_FLAGS_W		0x20
83#define	BHSSC_FLAGS_ATTR	0x07
84
85#define	BHSSC_FLAGS_ATTR_UNTAGGED	0
86#define	BHSSC_FLAGS_ATTR_SIMPLE		1
87#define	BHSSC_FLAGS_ATTR_ORDERED	2
88#define	BHSSC_FLAGS_ATTR_HOQ		3
89#define	BHSSC_FLAGS_ATTR_ACA		4
90
91struct iscsi_bhs_scsi_command {
92	uint8_t		bhssc_opcode;
93	uint8_t		bhssc_flags;
94	uint8_t		bhssc_reserved[2];
95	uint8_t		bhssc_total_ahs_len;
96	uint8_t		bhssc_data_segment_len[3];
97	uint64_t	bhssc_lun;
98	uint32_t	bhssc_initiator_task_tag;
99	uint32_t	bhssc_expected_data_transfer_length;
100	uint32_t	bhssc_cmdsn;
101	uint32_t	bhssc_expstatsn;
102	uint8_t		bhssc_cdb[16];
103};
104CTASSERT(sizeof(struct iscsi_bhs_scsi_command) == ISCSI_BHS_SIZE);
105
106#define	BHSSR_FLAGS_RESIDUAL_UNDERFLOW		0x02
107#define	BHSSR_FLAGS_RESIDUAL_OVERFLOW		0x04
108
109#define	BHSSR_RESPONSE_COMMAND_COMPLETED	0x00
110
111struct iscsi_bhs_scsi_response {
112	uint8_t		bhssr_opcode;
113	uint8_t		bhssr_flags;
114	uint8_t		bhssr_response;
115	uint8_t		bhssr_status;
116	uint8_t		bhssr_total_ahs_len;
117	uint8_t		bhssr_data_segment_len[3];
118	uint16_t	bhssr_status_qualifier;
119	uint16_t	bhssr_reserved;
120	uint32_t	bhssr_reserved2;
121	uint32_t	bhssr_initiator_task_tag;
122	uint32_t	bhssr_snack_tag;
123	uint32_t	bhssr_statsn;
124	uint32_t	bhssr_expcmdsn;
125	uint32_t	bhssr_maxcmdsn;
126	uint32_t	bhssr_expdatasn;
127	uint32_t	bhssr_bidirectional_read_residual_count;
128	uint32_t	bhssr_residual_count;
129};
130CTASSERT(sizeof(struct iscsi_bhs_scsi_response) == ISCSI_BHS_SIZE);
131
132#define	BHSTMR_FUNCTION_ABORT_TASK		1
133#define	BHSTMR_FUNCTION_ABORT_TASK_SET		2
134#define	BHSTMR_FUNCTION_CLEAR_ACA		3
135#define	BHSTMR_FUNCTION_CLEAR_TASK_SET		4
136#define	BHSTMR_FUNCTION_LOGICAL_UNIT_RESET	5
137#define	BHSTMR_FUNCTION_TARGET_WARM_RESET	6
138#define	BHSTMR_FUNCTION_TARGET_COLD_RESET	7
139#define	BHSTMR_FUNCTION_TASK_REASSIGN		8
140#define	BHSTMR_FUNCTION_QUERY_TASK		9
141#define	BHSTMR_FUNCTION_QUERY_TASK_SET		10
142#define	BHSTMR_FUNCTION_I_T_NEXUS_RESET		11
143#define	BHSTMR_FUNCTION_QUERY_ASYNC_EVENT	12
144
145struct iscsi_bhs_task_management_request {
146	uint8_t		bhstmr_opcode;
147	uint8_t		bhstmr_function;
148	uint8_t		bhstmr_reserved[2];
149	uint8_t		bhstmr_total_ahs_len;
150	uint8_t		bhstmr_data_segment_len[3];
151	uint64_t	bhstmr_lun;
152	uint32_t	bhstmr_initiator_task_tag;
153	uint32_t	bhstmr_referenced_task_tag;
154	uint32_t	bhstmr_cmdsn;
155	uint32_t	bhstmr_expstatsn;
156	uint32_t	bhstmr_refcmdsn;
157	uint32_t	bhstmr_expdatasn;
158	uint64_t	bhstmr_reserved2;
159};
160CTASSERT(sizeof(struct iscsi_bhs_task_management_request) == ISCSI_BHS_SIZE);
161
162#define	BHSTMR_RESPONSE_FUNCTION_COMPLETE	0
163#define	BHSTMR_RESPONSE_TASK_DOES_NOT_EXIST	1
164#define	BHSTMR_RESPONSE_LUN_DOES_NOT_EXIST	2
165#define	BHSTMR_RESPONSE_TASK_STILL_ALLEGIANT	3
166#define	BHSTMR_RESPONSE_TASK_ALL_REASS_NOT_SUPP	4
167#define	BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED	5
168#define	BHSTMR_RESPONSE_FUNCTION_AUTH_FAIL	6
169#define	BHSTMR_RESPONSE_FUNCTION_SUCCEEDED	7
170#define	BHSTMR_RESPONSE_FUNCTION_REJECTED	255
171
172struct iscsi_bhs_task_management_response {
173	uint8_t		bhstmr_opcode;
174	uint8_t		bhstmr_flags;
175	uint8_t		bhstmr_response;
176	uint8_t		bhstmr_reserved;
177	uint8_t		bhstmr_total_ahs_len;
178	uint8_t		bhstmr_data_segment_len[3];
179	uint8_t		bhstmr_additional_reponse_information[3];
180	uint8_t		bhstmr_reserved2[5];
181	uint32_t	bhstmr_initiator_task_tag;
182	uint32_t	bhstmr_reserved3;
183	uint32_t	bhstmr_statsn;
184	uint32_t	bhstmr_expcmdsn;
185	uint32_t	bhstmr_maxcmdsn;
186	uint8_t		bhstmr_reserved4[12];
187};
188CTASSERT(sizeof(struct iscsi_bhs_task_management_response) == ISCSI_BHS_SIZE);
189
190#define	BHSLR_FLAGS_TRANSIT		0x80
191#define	BHSLR_FLAGS_CONTINUE		0x40
192
193#define	BHSLR_STAGE_SECURITY_NEGOTIATION	0
194#define	BHSLR_STAGE_OPERATIONAL_NEGOTIATION	1
195#define	BHSLR_STAGE_FULL_FEATURE_PHASE		3 /* Yes, 3. */
196
197struct iscsi_bhs_login_request {
198	uint8_t		bhslr_opcode;
199	uint8_t		bhslr_flags;
200	uint8_t		bhslr_version_max;
201	uint8_t		bhslr_version_min;
202	uint8_t		bhslr_total_ahs_len;
203	uint8_t		bhslr_data_segment_len[3];
204	uint8_t		bhslr_isid[6];
205	uint16_t	bhslr_tsih;
206	uint32_t	bhslr_initiator_task_tag;
207	uint16_t	bhslr_cid;
208	uint16_t	bhslr_reserved;
209	uint32_t	bhslr_cmdsn;
210	uint32_t	bhslr_expstatsn;
211	uint8_t		bhslr_reserved2[16];
212};
213CTASSERT(sizeof(struct iscsi_bhs_login_request) == ISCSI_BHS_SIZE);
214
215struct iscsi_bhs_login_response {
216	uint8_t		bhslr_opcode;
217	uint8_t		bhslr_flags;
218	uint8_t		bhslr_version_max;
219	uint8_t		bhslr_version_active;
220	uint8_t		bhslr_total_ahs_len;
221	uint8_t		bhslr_data_segment_len[3];
222	uint8_t		bhslr_isid[6];
223	uint16_t	bhslr_tsih;
224	uint32_t	bhslr_initiator_task_tag;
225	uint32_t	bhslr_reserved;
226	uint32_t	bhslr_statsn;
227	uint32_t	bhslr_expcmdsn;
228	uint32_t	bhslr_maxcmdsn;
229	uint8_t		bhslr_status_class;
230	uint8_t		bhslr_status_detail;
231	uint16_t	bhslr_reserved2;
232	uint8_t		bhslr_reserved3[8];
233};
234CTASSERT(sizeof(struct iscsi_bhs_login_response) == ISCSI_BHS_SIZE);
235
236#define	BHSTR_FLAGS_FINAL		0x80
237#define	BHSTR_FLAGS_CONTINUE		0x40
238
239struct iscsi_bhs_text_request {
240	uint8_t		bhstr_opcode;
241	uint8_t		bhstr_flags;
242	uint16_t	bhstr_reserved;
243	uint8_t		bhstr_total_ahs_len;
244	uint8_t		bhstr_data_segment_len[3];
245	uint64_t	bhstr_lun;
246	uint32_t	bhstr_initiator_task_tag;
247	uint32_t	bhstr_target_transfer_tag;
248	uint32_t	bhstr_cmdsn;
249	uint32_t	bhstr_expstatsn;
250	uint8_t		bhstr_reserved2[16];
251};
252CTASSERT(sizeof(struct iscsi_bhs_text_request) == ISCSI_BHS_SIZE);
253
254struct iscsi_bhs_text_response {
255	uint8_t		bhstr_opcode;
256	uint8_t		bhstr_flags;
257	uint16_t	bhstr_reserved;
258	uint8_t		bhstr_total_ahs_len;
259	uint8_t		bhstr_data_segment_len[3];
260	uint64_t	bhstr_lun;
261	uint32_t	bhstr_initiator_task_tag;
262	uint32_t	bhstr_target_transfer_tag;
263	uint32_t	bhstr_statsn;
264	uint32_t	bhstr_expcmdsn;
265	uint32_t	bhstr_maxcmdsn;
266	uint8_t		bhstr_reserved2[12];
267};
268CTASSERT(sizeof(struct iscsi_bhs_text_response) == ISCSI_BHS_SIZE);
269
270#define	BHSDO_FLAGS_F	0x80
271
272struct iscsi_bhs_data_out {
273	uint8_t		bhsdo_opcode;
274	uint8_t		bhsdo_flags;
275	uint8_t		bhsdo_reserved[2];
276	uint8_t		bhsdo_total_ahs_len;
277	uint8_t		bhsdo_data_segment_len[3];
278	uint64_t	bhsdo_lun;
279	uint32_t	bhsdo_initiator_task_tag;
280	uint32_t	bhsdo_target_transfer_tag;
281	uint32_t	bhsdo_reserved2;
282	uint32_t	bhsdo_expstatsn;
283	uint32_t	bhsdo_reserved3;
284	uint32_t	bhsdo_datasn;
285	uint32_t	bhsdo_buffer_offset;
286	uint32_t	bhsdo_reserved4;
287};
288CTASSERT(sizeof(struct iscsi_bhs_data_out) == ISCSI_BHS_SIZE);
289
290#define	BHSDI_FLAGS_F	0x80
291#define	BHSDI_FLAGS_A	0x40
292#define	BHSDI_FLAGS_O	0x04
293#define	BHSDI_FLAGS_U	0x02
294#define	BHSDI_FLAGS_S	0x01
295
296struct iscsi_bhs_data_in {
297	uint8_t		bhsdi_opcode;
298	uint8_t		bhsdi_flags;
299	uint8_t		bhsdi_reserved;
300	uint8_t		bhsdi_status;
301	uint8_t		bhsdi_total_ahs_len;
302	uint8_t		bhsdi_data_segment_len[3];
303	uint64_t	bhsdi_lun;
304	uint32_t	bhsdi_initiator_task_tag;
305	uint32_t	bhsdi_target_transfer_tag;
306	uint32_t	bhsdi_statsn;
307	uint32_t	bhsdi_expcmdsn;
308	uint32_t	bhsdi_maxcmdsn;
309	uint32_t	bhsdi_datasn;
310	uint32_t	bhsdi_buffer_offset;
311	uint32_t	bhsdi_residual_count;
312};
313CTASSERT(sizeof(struct iscsi_bhs_data_in) == ISCSI_BHS_SIZE);
314
315struct iscsi_bhs_r2t {
316	uint8_t		bhsr2t_opcode;
317	uint8_t		bhsr2t_flags;
318	uint16_t	bhsr2t_reserved;
319	uint8_t		bhsr2t_total_ahs_len;
320	uint8_t		bhsr2t_data_segment_len[3];
321	uint64_t	bhsr2t_lun;
322	uint32_t	bhsr2t_initiator_task_tag;
323	uint32_t	bhsr2t_target_transfer_tag;
324	uint32_t	bhsr2t_statsn;
325	uint32_t	bhsr2t_expcmdsn;
326	uint32_t	bhsr2t_maxcmdsn;
327	uint32_t	bhsr2t_r2tsn;
328	uint32_t	bhsr2t_buffer_offset;
329	uint32_t	bhsr2t_desired_data_transfer_length;
330};
331CTASSERT(sizeof(struct iscsi_bhs_r2t) == ISCSI_BHS_SIZE);
332
333struct iscsi_bhs_nop_out {
334	uint8_t		bhsno_opcode;
335	uint8_t		bhsno_flags;
336	uint16_t	bhsno_reserved;
337	uint8_t		bhsno_total_ahs_len;
338	uint8_t		bhsno_data_segment_len[3];
339	uint64_t	bhsno_lun;
340	uint32_t	bhsno_initiator_task_tag;
341	uint32_t	bhsno_target_transfer_tag;
342	uint32_t	bhsno_cmdsn;
343	uint32_t	bhsno_expstatsn;
344	uint8_t		bhsno_reserved2[16];
345};
346CTASSERT(sizeof(struct iscsi_bhs_nop_out) == ISCSI_BHS_SIZE);
347
348struct iscsi_bhs_nop_in {
349	uint8_t		bhsni_opcode;
350	uint8_t		bhsni_flags;
351	uint16_t	bhsni_reserved;
352	uint8_t		bhsni_total_ahs_len;
353	uint8_t		bhsni_data_segment_len[3];
354	uint64_t	bhsni_lun;
355	uint32_t	bhsni_initiator_task_tag;
356	uint32_t	bhsni_target_transfer_tag;
357	uint32_t	bhsni_statsn;
358	uint32_t	bhsni_expcmdsn;
359	uint32_t	bhsni_maxcmdsn;
360	uint8_t		bhsno_reserved2[12];
361};
362CTASSERT(sizeof(struct iscsi_bhs_nop_in) == ISCSI_BHS_SIZE);
363
364#define	BHSLR_REASON_CLOSE_SESSION		0
365#define	BHSLR_REASON_CLOSE_CONNECTION		1
366#define	BHSLR_REASON_REMOVE_FOR_RECOVERY	2
367
368struct iscsi_bhs_logout_request {
369	uint8_t		bhslr_opcode;
370	uint8_t		bhslr_reason;
371	uint16_t	bhslr_reserved;
372	uint8_t		bhslr_total_ahs_len;
373	uint8_t		bhslr_data_segment_len[3];
374	uint64_t	bhslr_reserved2;
375	uint32_t	bhslr_initiator_task_tag;
376	uint16_t	bhslr_cid;
377	uint16_t	bhslr_reserved3;
378	uint32_t	bhslr_cmdsn;
379	uint32_t	bhslr_expstatsn;
380	uint8_t		bhslr_reserved4[16];
381};
382CTASSERT(sizeof(struct iscsi_bhs_logout_request) == ISCSI_BHS_SIZE);
383
384#define	BHSLR_RESPONSE_CLOSED_SUCCESSFULLY	0
385#define	BHSLR_RESPONSE_RECOVERY_NOT_SUPPORTED	2
386
387struct iscsi_bhs_logout_response {
388	uint8_t		bhslr_opcode;
389	uint8_t		bhslr_flags;
390	uint8_t		bhslr_response;
391	uint8_t		bhslr_reserved;
392	uint8_t		bhslr_total_ahs_len;
393	uint8_t		bhslr_data_segment_len[3];
394	uint64_t	bhslr_reserved2;
395	uint32_t	bhslr_initiator_task_tag;
396	uint32_t	bhslr_reserved3;
397	uint32_t	bhslr_statsn;
398	uint32_t	bhslr_expcmdsn;
399	uint32_t	bhslr_maxcmdsn;
400	uint32_t	bhslr_reserved4;
401	uint16_t	bhslr_time2wait;
402	uint16_t	bhslr_time2retain;
403	uint32_t	bhslr_reserved5;
404};
405CTASSERT(sizeof(struct iscsi_bhs_logout_response) == ISCSI_BHS_SIZE);
406
407#define	BHSAM_EVENT_TARGET_REQUESTS_LOGOUT		1
408#define	BHSAM_EVENT_TARGET_TERMINATES_CONNECTION	2
409#define	BHSAM_EVENT_TARGET_TERMINATES_SESSION		3
410
411struct iscsi_bhs_asynchronous_message {
412	uint8_t		bhsam_opcode;
413	uint8_t		bhsam_flags;
414	uint16_t	bhsam_reserved;
415	uint8_t		bhsam_total_ahs_len;
416	uint8_t		bhsam_data_segment_len[3];
417	uint64_t	bhsam_lun;
418	uint32_t	bhsam_0xffffffff;
419	uint32_t	bhsam_reserved2;
420	uint32_t	bhsam_statsn;
421	uint32_t	bhsam_expcmdsn;
422	uint32_t	bhsam_maxcmdsn;
423	uint8_t		bhsam_async_event;
424	uint8_t		bhsam_async_vcode;
425	uint16_t	bhsam_parameter1;
426	uint16_t	bhsam_parameter2;
427	uint16_t	bhsam_parameter3;
428	uint32_t	bhsam_reserved3;
429};
430CTASSERT(sizeof(struct iscsi_bhs_asynchronous_message) == ISCSI_BHS_SIZE);
431
432#define BHSSR_REASON_DATA_DIGEST_ERROR	0x02
433#define BHSSR_PROTOCOL_ERROR		0x04
434#define BHSSR_COMMAND_NOT_SUPPORTED	0x05
435#define BHSSR_INVALID_PDU_FIELD		0x09
436
437struct iscsi_bhs_reject {
438	uint8_t		bhsr_opcode;
439	uint8_t		bhsr_flags;
440	uint8_t		bhsr_reason;
441	uint8_t		bhsr_reserved;
442	uint8_t		bhsr_total_ahs_len;
443	uint8_t		bhsr_data_segment_len[3];
444	uint64_t	bhsr_reserved2;
445	uint32_t	bhsr_0xffffffff;
446	uint32_t	bhsr_reserved3;
447	uint32_t	bhsr_statsn;
448	uint32_t	bhsr_expcmdsn;
449	uint32_t	bhsr_maxcmdsn;
450	uint32_t	bhsr_datasn_r2tsn;
451	uint32_t	bhsr_reserved4;
452	uint32_t	bhsr_reserved5;
453};
454CTASSERT(sizeof(struct iscsi_bhs_reject) == ISCSI_BHS_SIZE);
455
456#endif /* !ISCSI_PROTO_H */
457