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_BHS_SIZE			48
42#define	ISCSI_HEADER_DIGEST_SIZE	4
43#define	ISCSI_DATA_DIGEST_SIZE		4
44
45#define	ISCSI_BHS_OPCODE_IMMEDIATE	0x40
46
47#define	ISCSI_BHS_OPCODE_NOP_OUT	0x00
48#define	ISCSI_BHS_OPCODE_SCSI_COMMAND	0x01
49#define	ISCSI_BHS_OPCODE_TASK_REQUEST	0x02
50#define	ISCSI_BHS_OPCODE_LOGIN_REQUEST	0x03
51#define	ISCSI_BHS_OPCODE_TEXT_REQUEST	0x04
52#define	ISCSI_BHS_OPCODE_SCSI_DATA_OUT	0x05
53#define	ISCSI_BHS_OPCODE_LOGOUT_REQUEST	0x06
54
55#define	ISCSI_BHS_OPCODE_NOP_IN		0x20
56#define	ISCSI_BHS_OPCODE_SCSI_RESPONSE	0x21
57#define	ISCSI_BHS_OPCODE_TASK_RESPONSE	0x22
58#define	ISCSI_BHS_OPCODE_LOGIN_RESPONSE	0x23
59#define	ISCSI_BHS_OPCODE_TEXT_RESPONSE	0x24
60#define	ISCSI_BHS_OPCODE_SCSI_DATA_IN	0x25
61#define	ISCSI_BHS_OPCODE_LOGOUT_RESPONSE	0x26
62#define	ISCSI_BHS_OPCODE_R2T		0x31
63#define	ISCSI_BHS_OPCODE_ASYNC_MESSAGE	0x32
64#define	ISCSI_BHS_OPCODE_REJECT		0x3f
65
66struct iscsi_bhs {
67	uint8_t		bhs_opcode;
68	uint8_t		bhs_opcode_specific1[3];
69	uint8_t		bhs_total_ahs_len;
70	uint8_t		bhs_data_segment_len[3];
71	uint64_t	bhs_lun;
72	uint8_t		bhs_inititator_task_tag[4];
73	uint8_t		bhs_opcode_specific4[28];
74};
75CTASSERT(sizeof(struct iscsi_bhs) == ISCSI_BHS_SIZE);
76
77#define	BHSSC_FLAGS_F		0x80
78#define	BHSSC_FLAGS_R		0x40
79#define	BHSSC_FLAGS_W		0x20
80#define	BHSSC_FLAGS_ATTR	0x07
81
82#define	BHSSC_FLAGS_ATTR_UNTAGGED	0
83#define	BHSSC_FLAGS_ATTR_SIMPLE		1
84#define	BHSSC_FLAGS_ATTR_ORDERED	2
85#define	BHSSC_FLAGS_ATTR_HOQ		3
86#define	BHSSC_FLAGS_ATTR_ACA		4
87
88struct iscsi_bhs_scsi_command {
89	uint8_t		bhssc_opcode;
90	uint8_t		bhssc_flags;
91	uint8_t		bhssc_reserved[2];
92	uint8_t		bhssc_total_ahs_len;
93	uint8_t		bhssc_data_segment_len[3];
94	uint64_t	bhssc_lun;
95	uint32_t	bhssc_initiator_task_tag;
96	uint32_t	bhssc_expected_data_transfer_length;
97	uint32_t	bhssc_cmdsn;
98	uint32_t	bhssc_expstatsn;
99	uint8_t		bhssc_cdb[16];
100};
101CTASSERT(sizeof(struct iscsi_bhs_scsi_command) == ISCSI_BHS_SIZE);
102
103#define	BHSSR_FLAGS_RESIDUAL_UNDERFLOW		0x02
104#define	BHSSR_FLAGS_RESIDUAL_OVERFLOW		0x04
105
106#define	BHSSR_RESPONSE_COMMAND_COMPLETED	0x00
107
108struct iscsi_bhs_scsi_response {
109	uint8_t		bhssr_opcode;
110	uint8_t		bhssr_flags;
111	uint8_t		bhssr_response;
112	uint8_t		bhssr_status;
113	uint8_t		bhssr_total_ahs_len;
114	uint8_t		bhssr_data_segment_len[3];
115	uint64_t	bhssr_reserved;
116	uint32_t	bhssr_initiator_task_tag;
117	uint32_t	bhssr_snack_tag;
118	uint32_t	bhssr_statsn;
119	uint32_t	bhssr_expcmdsn;
120	uint32_t	bhssr_maxcmdsn;
121	uint32_t	bhssr_expdatasn;
122	uint32_t	bhssr_bidirectional_read_residual_count;
123	uint32_t	bhssr_residual_count;
124};
125CTASSERT(sizeof(struct iscsi_bhs_scsi_response) == ISCSI_BHS_SIZE);
126
127#define	BHSTMR_FUNCTION_ABORT_TASK		1
128#define	BHSTMR_FUNCTION_ABORT_TASK_SET		2
129#define	BHSTMR_FUNCTION_CLEAR_ACA		3
130#define	BHSTMR_FUNCTION_CLEAR_TASK_SET		4
131#define	BHSTMR_FUNCTION_LOGICAL_UNIT_RESET	5
132#define	BHSTMR_FUNCTION_TARGET_WARM_RESET	6
133#define	BHSTMR_FUNCTION_TARGET_COLD_RESET	7
134#define	BHSTMR_FUNCTION_TASK_REASSIGN		8
135
136struct iscsi_bhs_task_management_request {
137	uint8_t		bhstmr_opcode;
138	uint8_t		bhstmr_function;
139	uint8_t		bhstmr_reserved[2];
140	uint8_t		bhstmr_total_ahs_len;
141	uint8_t		bhstmr_data_segment_len[3];
142	uint64_t	bhstmr_lun;
143	uint32_t	bhstmr_initiator_task_tag;
144	uint32_t	bhstmr_referenced_task_tag;
145	uint32_t	bhstmr_cmdsn;
146	uint32_t	bhstmr_expstatsn;
147	uint32_t	bhstmr_refcmdsn;
148	uint32_t	bhstmr_expdatasn;
149	uint64_t	bhstmr_reserved2;
150};
151CTASSERT(sizeof(struct iscsi_bhs_task_management_request) == ISCSI_BHS_SIZE);
152
153#define	BHSTMR_RESPONSE_FUNCTION_COMPLETE	0
154#define	BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED	5
155
156struct iscsi_bhs_task_management_response {
157	uint8_t		bhstmr_opcode;
158	uint8_t		bhstmr_flags;
159	uint8_t		bhstmr_response;
160	uint8_t		bhstmr_reserved;
161	uint8_t		bhstmr_total_ahs_len;
162	uint8_t		bhstmr_data_segment_len[3];
163	uint64_t	bhstmr_reserved2;
164	uint32_t	bhstmr_initiator_task_tag;
165	uint32_t	bhstmr_reserved3;
166	uint32_t	bhstmr_statsn;
167	uint32_t	bhstmr_expcmdsn;
168	uint32_t	bhstmr_maxcmdsn;
169	uint8_t		bhstmr_reserved4[12];
170};
171CTASSERT(sizeof(struct iscsi_bhs_task_management_response) == ISCSI_BHS_SIZE);
172
173#define	BHSLR_FLAGS_TRANSIT		0x80
174#define	BHSLR_FLAGS_CONTINUE		0x40
175
176#define	BHSLR_STAGE_SECURITY_NEGOTIATION	0
177#define	BHSLR_STAGE_OPERATIONAL_NEGOTIATION	1
178#define	BHSLR_STAGE_FULL_FEATURE_PHASE		3 /* Yes, 3. */
179
180struct iscsi_bhs_login_request {
181	uint8_t		bhslr_opcode;
182	uint8_t		bhslr_flags;
183	uint8_t		bhslr_version_max;
184	uint8_t		bhslr_version_min;
185	uint8_t		bhslr_total_ahs_len;
186	uint8_t		bhslr_data_segment_len[3];
187	uint8_t		bhslr_isid[6];
188	uint16_t	bhslr_tsih;
189	uint32_t	bhslr_initiator_task_tag;
190	uint16_t	bhslr_cid;
191	uint16_t	bhslr_reserved;
192	uint32_t	bhslr_cmdsn;
193	uint32_t	bhslr_expstatsn;
194	uint8_t		bhslr_reserved2[16];
195};
196CTASSERT(sizeof(struct iscsi_bhs_login_request) == ISCSI_BHS_SIZE);
197
198struct iscsi_bhs_login_response {
199	uint8_t		bhslr_opcode;
200	uint8_t		bhslr_flags;
201	uint8_t		bhslr_version_max;
202	uint8_t		bhslr_version_active;
203	uint8_t		bhslr_total_ahs_len;
204	uint8_t		bhslr_data_segment_len[3];
205	uint8_t		bhslr_isid[6];
206	uint16_t	bhslr_tsih;
207	uint32_t	bhslr_initiator_task_tag;
208	uint32_t	bhslr_reserved;
209	uint32_t	bhslr_statsn;
210	uint32_t	bhslr_expcmdsn;
211	uint32_t	bhslr_maxcmdsn;
212	uint8_t		bhslr_status_class;
213	uint8_t		bhslr_status_detail;
214	uint16_t	bhslr_reserved2;
215	uint8_t		bhslr_reserved3[8];
216};
217CTASSERT(sizeof(struct iscsi_bhs_login_response) == ISCSI_BHS_SIZE);
218
219#define	BHSTR_FLAGS_FINAL		0x80
220#define	BHSTR_FLAGS_CONTINUE		0x40
221
222struct iscsi_bhs_text_request {
223	uint8_t		bhstr_opcode;
224	uint8_t		bhstr_flags;
225	uint16_t	bhstr_reserved;
226	uint8_t		bhstr_total_ahs_len;
227	uint8_t		bhstr_data_segment_len[3];
228	uint64_t	bhstr_lun;
229	uint32_t	bhstr_initiator_task_tag;
230	uint32_t	bhstr_target_transfer_tag;
231	uint32_t	bhstr_cmdsn;
232	uint32_t	bhstr_expstatsn;
233	uint8_t		bhstr_reserved2[16];
234};
235CTASSERT(sizeof(struct iscsi_bhs_text_request) == ISCSI_BHS_SIZE);
236
237struct iscsi_bhs_text_response {
238	uint8_t		bhstr_opcode;
239	uint8_t		bhstr_flags;
240	uint16_t	bhstr_reserved;
241	uint8_t		bhstr_total_ahs_len;
242	uint8_t		bhstr_data_segment_len[3];
243	uint64_t	bhstr_lun;
244	uint32_t	bhstr_initiator_task_tag;
245	uint32_t	bhstr_target_transfer_tag;
246	uint32_t	bhstr_statsn;
247	uint32_t	bhstr_expcmdsn;
248	uint32_t	bhstr_maxcmdsn;
249	uint8_t		bhstr_reserved2[12];
250};
251CTASSERT(sizeof(struct iscsi_bhs_text_response) == ISCSI_BHS_SIZE);
252
253#define	BHSDO_FLAGS_F	0x80
254
255struct iscsi_bhs_data_out {
256	uint8_t		bhsdo_opcode;
257	uint8_t		bhsdo_flags;
258	uint8_t		bhsdo_reserved[2];
259	uint8_t		bhsdo_total_ahs_len;
260	uint8_t		bhsdo_data_segment_len[3];
261	uint64_t	bhsdo_lun;
262	uint32_t	bhsdo_initiator_task_tag;
263	uint32_t	bhsdo_target_transfer_tag;
264	uint32_t	bhsdo_reserved2;
265	uint32_t	bhsdo_expstatsn;
266	uint32_t	bhsdo_reserved3;
267	uint32_t	bhsdo_datasn;
268	uint32_t	bhsdo_buffer_offset;
269	uint32_t	bhsdo_reserved4;
270};
271CTASSERT(sizeof(struct iscsi_bhs_data_out) == ISCSI_BHS_SIZE);
272
273#define	BHSDI_FLAGS_F	0x80
274#define	BHSDI_FLAGS_A	0x40
275#define	BHSDI_FLAGS_O	0x04
276#define	BHSDI_FLAGS_U	0x02
277#define	BHSDI_FLAGS_S	0x01
278
279struct iscsi_bhs_data_in {
280	uint8_t		bhsdi_opcode;
281	uint8_t		bhsdi_flags;
282	uint8_t		bhsdi_reserved;
283	uint8_t		bhsdi_status;
284	uint8_t		bhsdi_total_ahs_len;
285	uint8_t		bhsdi_data_segment_len[3];
286	uint64_t	bhsdi_lun;
287	uint32_t	bhsdi_initiator_task_tag;
288	uint32_t	bhsdi_target_transfer_tag;
289	uint32_t	bhsdi_statsn;
290	uint32_t	bhsdi_expcmdsn;
291	uint32_t	bhsdi_maxcmdsn;
292	uint32_t	bhsdi_datasn;
293	uint32_t	bhsdi_buffer_offset;
294	uint32_t	bhsdi_residual_count;
295};
296CTASSERT(sizeof(struct iscsi_bhs_data_in) == ISCSI_BHS_SIZE);
297
298struct iscsi_bhs_r2t {
299	uint8_t		bhsr2t_opcode;
300	uint8_t		bhsr2t_flags;
301	uint16_t	bhsr2t_reserved;
302	uint8_t		bhsr2t_total_ahs_len;
303	uint8_t		bhsr2t_data_segment_len[3];
304	uint64_t	bhsr2t_lun;
305	uint32_t	bhsr2t_initiator_task_tag;
306	uint32_t	bhsr2t_target_transfer_tag;
307	uint32_t	bhsr2t_statsn;
308	uint32_t	bhsr2t_expcmdsn;
309	uint32_t	bhsr2t_maxcmdsn;
310	uint32_t	bhsr2t_r2tsn;
311	uint32_t	bhsr2t_buffer_offset;
312	uint32_t	bhsr2t_desired_data_transfer_length;
313};
314CTASSERT(sizeof(struct iscsi_bhs_r2t) == ISCSI_BHS_SIZE);
315
316struct iscsi_bhs_nop_out {
317	uint8_t		bhsno_opcode;
318	uint8_t		bhsno_flags;
319	uint16_t	bhsno_reserved;
320	uint8_t		bhsno_total_ahs_len;
321	uint8_t		bhsno_data_segment_len[3];
322	uint64_t	bhsno_lun;
323	uint32_t	bhsno_initiator_task_tag;
324	uint32_t	bhsno_target_transfer_tag;
325	uint32_t	bhsno_cmdsn;
326	uint32_t	bhsno_expstatsn;
327	uint8_t		bhsno_reserved2[16];
328};
329CTASSERT(sizeof(struct iscsi_bhs_nop_out) == ISCSI_BHS_SIZE);
330
331struct iscsi_bhs_nop_in {
332	uint8_t		bhsni_opcode;
333	uint8_t		bhsni_flags;
334	uint16_t	bhsni_reserved;
335	uint8_t		bhsni_total_ahs_len;
336	uint8_t		bhsni_data_segment_len[3];
337	uint64_t	bhsni_lun;
338	uint32_t	bhsni_initiator_task_tag;
339	uint32_t	bhsni_target_transfer_tag;
340	uint32_t	bhsni_statsn;
341	uint32_t	bhsni_expcmdsn;
342	uint32_t	bhsni_maxcmdsn;
343	uint8_t		bhsno_reserved2[12];
344};
345CTASSERT(sizeof(struct iscsi_bhs_nop_in) == ISCSI_BHS_SIZE);
346
347#define	BHSLR_REASON_CLOSE_SESSION		0
348#define	BHSLR_REASON_CLOSE_CONNECTION		1
349#define	BHSLR_REASON_REMOVE_FOR_RECOVERY	2
350
351struct iscsi_bhs_logout_request {
352	uint8_t		bhslr_opcode;
353	uint8_t		bhslr_reason;
354	uint16_t	bhslr_reserved;
355	uint8_t		bhslr_total_ahs_len;
356	uint8_t		bhslr_data_segment_len[3];
357	uint64_t	bhslr_reserved2;
358	uint32_t	bhslr_initiator_task_tag;
359	uint16_t	bhslr_cid;
360	uint16_t	bhslr_reserved3;
361	uint32_t	bhslr_cmdsn;
362	uint32_t	bhslr_expstatsn;
363	uint8_t		bhslr_reserved4[16];
364};
365CTASSERT(sizeof(struct iscsi_bhs_logout_request) == ISCSI_BHS_SIZE);
366
367#define	BHSLR_RESPONSE_CLOSED_SUCCESSFULLY	0
368#define	BHSLR_RESPONSE_RECOVERY_NOT_SUPPORTED	2
369
370struct iscsi_bhs_logout_response {
371	uint8_t		bhslr_opcode;
372	uint8_t		bhslr_flags;
373	uint8_t		bhslr_response;
374	uint8_t		bhslr_reserved;
375	uint8_t		bhslr_total_ahs_len;
376	uint8_t		bhslr_data_segment_len[3];
377	uint64_t	bhslr_reserved2;
378	uint32_t	bhslr_initiator_task_tag;
379	uint32_t	bhslr_reserved3;
380	uint32_t	bhslr_statsn;
381	uint32_t	bhslr_expcmdsn;
382	uint32_t	bhslr_maxcmdsn;
383	uint32_t	bhslr_reserved4;
384	uint16_t	bhslr_time2wait;
385	uint16_t	bhslr_time2retain;
386	uint32_t	bhslr_reserved5;
387};
388CTASSERT(sizeof(struct iscsi_bhs_logout_response) == ISCSI_BHS_SIZE);
389
390#define	BHSAM_EVENT_TARGET_REQUESTS_LOGOUT		1
391#define	BHSAM_EVENT_TARGET_TERMINATES_CONNECTION	2
392#define	BHSAM_EVENT_TARGET_TERMINATES_SESSION		3
393
394struct iscsi_bhs_asynchronous_message {
395	uint8_t		bhsam_opcode;
396	uint8_t		bhsam_flags;
397	uint16_t	bhsam_reserved;
398	uint8_t		bhsam_total_ahs_len;
399	uint8_t		bhsam_data_segment_len[3];
400	uint64_t	bhsam_lun;
401	uint32_t	bhsam_0xffffffff;
402	uint32_t	bhsam_reserved2;
403	uint32_t	bhsam_statsn;
404	uint32_t	bhsam_expcmdsn;
405	uint32_t	bhsam_maxcmdsn;
406	uint8_t		bhsam_async_event;
407	uint8_t		bhsam_async_vcode;
408	uint16_t	bhsam_parameter1;
409	uint16_t	bhsam_parameter2;
410	uint16_t	bhsam_parameter3;
411	uint32_t	bhsam_reserved3;
412};
413CTASSERT(sizeof(struct iscsi_bhs_asynchronous_message) == ISCSI_BHS_SIZE);
414
415#define BHSSR_REASON_DATA_DIGEST_ERROR	0x02
416#define BHSSR_PROTOCOL_ERROR		0x04
417#define BHSSR_COMMAND_NOT_SUPPORTED	0x05
418#define BHSSR_INVALID_PDU_FIELD		0x09
419
420struct iscsi_bhs_reject {
421	uint8_t		bhsr_opcode;
422	uint8_t		bhsr_flags;
423	uint8_t		bhsr_reason;
424	uint8_t		bhsr_reserved;
425	uint8_t		bhsr_total_ahs_len;
426	uint8_t		bhsr_data_segment_len[3];
427	uint64_t	bhsr_reserved2;
428	uint32_t	bhsr_0xffffffff;
429	uint32_t	bhsr_reserved3;
430	uint32_t	bhsr_statsn;
431	uint32_t	bhsr_expcmdsn;
432	uint32_t	bhsr_maxcmdsn;
433	uint32_t	bhsr_datasn_r2tsn;
434	uint32_t	bhsr_reserved4;
435	uint32_t	bhsr_reserved5;
436};
437CTASSERT(sizeof(struct iscsi_bhs_reject) == ISCSI_BHS_SIZE);
438
439#endif /* !ISCSI_PROTO_H */
440