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