xref: /openbsd-src/usr.sbin/iscsid/iscsid.h (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: iscsid.h,v 1.9 2011/05/04 21:00:04 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #define ISCSID_DEVICE	"/dev/vscsi0"
20 #define ISCSID_CONTROL	"/var/run/iscsid.sock"
21 #define ISCSID_CONFIG	"/etc/iscsi.conf"
22 #define ISCSID_USER	"_iscsid"
23 
24 #define ISCSID_BASE_NAME	"iqn.1995-11.org.openbsd.iscsid"
25 #define ISCSID_DEF_CONNS	8
26 
27 #define PDU_READ_SIZE		(256 * 1024)
28 #define CONTROL_READ_SIZE	8192
29 #define PDU_MAXIOV		5
30 #define PDU_WRIOV		(PDU_MAXIOV * 8)
31 
32 #define PDU_HEADER	0
33 #define PDU_AHS		1
34 #define PDU_HDIGEST	2
35 #define PDU_DATA	3
36 #define PDU_DDIGEST	4
37 
38 #define PDU_LEN(x)	((((x) + 3) / 4) * 4)
39 
40 /*
41  * Common control message header.
42  * A message can consist of up to 3 parts with specified length.
43  */
44 struct ctrlmsghdr {
45 	u_int16_t	type;
46 	u_int16_t	len[3];
47 };
48 
49 /* Control message types */
50 #define CTRL_SUCCESS		1
51 #define CTRL_FAILURE		2
52 #define CTRL_INPROGRESS		3
53 #define CTRL_INITIATOR_CONFIG	4
54 #define CTRL_SESSION_CONFIG	5
55 #define CTRL_LOG_VERBOSE	6
56 
57 
58 TAILQ_HEAD(session_head, session);
59 TAILQ_HEAD(connection_head, connection);
60 TAILQ_HEAD(pduq, pdu);
61 TAILQ_HEAD(taskq, task);
62 
63 /* as in tcp_seq.h */
64 #define SEQ_LT(a,b)     ((int)((a)-(b)) < 0)
65 #define SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
66 #define SEQ_GT(a,b)     ((int)((a)-(b)) > 0)
67 #define SEQ_GEQ(a,b)    ((int)((a)-(b)) >= 0)
68 
69 #define SESS_INIT		0x0001
70 #define SESS_FREE		0x0002
71 #define SESS_LOGGED_IN		0x0004
72 #define SESS_FAILED		0x0008
73 #define SESS_DOWN		0x0010
74 #define SESS_ANYSTATE		0xffff
75 #define SESS_RUNNING		(SESS_FREE | SESS_LOGGED_IN | SESS_FAILED)
76 
77 #define CONN_FREE		0x0001
78 #define CONN_XPT_WAIT		0x0002
79 #define CONN_XPT_UP		0x0004
80 #define CONN_IN_LOGIN		0x0008
81 #define CONN_LOGGED_IN		0x0010
82 #define CONN_IN_LOGOUT		0x0020
83 #define CONN_LOGOUT_REQ		0x0040
84 #define CONN_CLEANUP_WAIT	0x0080
85 #define CONN_IN_CLEANUP		0x0100
86 #define CONN_ANYSTATE		0xffff
87 #define CONN_RUNNING		(CONN_LOGGED_IN | CONN_LOGOUT_REQ)
88 #define CONN_FAILED		(CONN_CLEANUP_WAIT | CONN_IN_CLEANUP)
89 #define CONN_NEVER_LOGGED_IN	(CONN_FREE | CONN_XPT_WAIT | CONN_XPT_UP | \
90 				    CONN_IN_LOGIN)
91 
92 enum c_event {
93 	CONN_EV_FAIL,
94 	CONN_EV_FREE,
95 	CONN_EV_CONNECT,
96 	CONN_EV_CONNECTED,
97 	CONN_EV_LOGGED_IN,
98 	CONN_EV_LOGOUT,
99 	CONN_EV_LOGGED_OUT,
100 	CONN_EV_CLOSED
101 };
102 
103 enum s_event {
104 	SESS_EV_START,
105 	SESS_EV_CONN_LOGGED_IN,
106 	SESS_EV_CONN_FAIL,
107 	SESS_EV_CONN_CLOSED,
108 	SESS_EV_CLOSED,
109 	SESS_EV_FAIL
110 };
111 
112 #define SESS_ACT_UP		0
113 #define SESS_ACT_DOWN		1
114 
115 struct pdu {
116 	TAILQ_ENTRY(pdu)	 entry;
117 	struct iovec		 iov[PDU_MAXIOV];
118 	size_t			 resid;
119 };
120 
121 struct pdu_readbuf {
122 	char		*buf;
123 	size_t		 size;
124 	size_t		 rpos;
125 	size_t		 wpos;
126 	struct pdu	*wip;
127 };
128 
129 struct connection_config {
130 	/* values inherited from session_config */
131 	struct sockaddr_storage	 TargetAddr;	/* IP:port of target */
132 	struct sockaddr_storage	 LocalAddr;	/* IP:port of target */
133 };
134 
135 struct initiator_config {
136 	u_int32_t		isid_base;	/* only 24 bits */
137 	u_int16_t		isid_qual;
138 	u_int16_t		pad;
139 };
140 
141 struct session_config {
142 	/* unique session ID */
143 	char			SessionName[32];
144 	/*
145 	 * I = initialize only, L = leading only
146 	 * S = session wide, C = connection only
147 	 */
148 	struct connection_config connection;
149 
150 	char			*TargetName;	/* String: IS */
151 
152 	char			*InitiatorName;	/* String: IS */
153 
154 	u_int16_t		 MaxConnections;
155 				 /* 1, 1-65535 (min()): LS */
156 	u_int8_t		 HeaderDigest;
157 				 /* None , (None|CRC32): IC */
158 	u_int8_t		 DataDigest;
159 				 /* None , (None|CRC32): IC */
160 	u_int8_t		 SessionType;
161 				 /* Normal, (Discovery|Normal): LS */
162 	u_int8_t		 disabled;
163 };
164 
165 #define SESSION_TYPE_NORMAL	0
166 #define SESSION_TYPE_DISCOVERY	1
167 
168 struct session_params {
169 	u_int32_t		 MaxBurstLength;
170 				 /* 262144, 512-to-(2**24-1) (min()): LS */
171 	u_int32_t		 FirstBurstLength;
172 				 /* 65536, 512-to-(2**24-1) (min()): LS */
173 	u_int16_t		 DefaultTime2Wait;
174 				 /* 2, 0-to-3600 (max()): LS */
175 	u_int16_t		 DefaultTime2Retain;
176 				 /* 20, 0-to-3600 (min()): LS */
177 	u_int16_t		 MaxOutstandingR2T;
178 				 /* 1, 1-to-65535 (min()): LS */
179 	u_int16_t		 TargetPortalGroupTag;
180 				 /* 1- 65535: IS */
181 	u_int16_t		 MaxConnections;
182 				 /* 1, 1-65535 (min()): LS */
183 	u_int8_t		 InitialR2T;
184 				 /* yes, bool (||): LS  */
185 	u_int8_t		 ImmediateData;
186 				 /* yes, bool (&&): LS */
187 	u_int8_t		 DataPDUInOrder;
188 				 /* yes, bool (||): LS */
189 	u_int8_t		 DataSequenceInOrder;
190 				 /* yes, bool (||): LS */
191 	u_int8_t		 ErrorRecoveryLevel;
192 				 /* 0, 0 - 2 (min()): LS */
193 };
194 
195 struct connection_params {
196 	u_int32_t		 MaxRecvDataSegmentLength;
197 				 /* 8192, 512-to-(2**24-1): C */
198 				 /* inherited from session_config */
199 	u_int8_t		 HeaderDigest;
200 	u_int8_t		 DataDigest;
201 };
202 
203 struct initiator {
204 	struct session_head	sessions;
205 	struct initiator_config	config;
206 	u_int			target;
207 };
208 
209 struct sessev {
210 	SIMPLEQ_ENTRY(sessev)	 entry;
211 	struct connection	*conn;
212 	enum s_event		 event;
213 };
214 
215 struct session {
216 	TAILQ_ENTRY(session)	 entry;
217 	struct connection_head	 connections;
218 	struct taskq		 tasks;
219 	struct session_config	 config;
220 	struct session_params	 mine;
221 	struct session_params	 his;
222 	struct session_params	 active;
223 	struct initiator	*initiator;
224 	struct event		 fsm_ev;
225 	SIMPLEQ_HEAD(, sessev)	 fsmq;
226 	u_int32_t		 cmdseqnum;
227 	u_int32_t		 itt;
228 	u_int32_t		 isid_base;	/* only 24 bits */
229 	u_int16_t		 isid_qual;	/* inherited from initiator */
230 	u_int16_t		 tsih;		/* target session id handle */
231 	u_int			 target;
232 	int			 state;
233 	int			 action;
234 };
235 
236 struct connection {
237 	struct event		 ev;
238 	struct event		 wev;
239 	TAILQ_ENTRY(connection)	 entry;
240 	struct connection_params mine;
241 	struct connection_params his;
242 	struct connection_params active;
243 	struct connection_config config;
244 	struct pdu_readbuf	 prbuf;
245 	struct pduq		 pdu_w;
246 	struct taskq		 tasks;
247 	struct session		*session;
248 	u_int32_t		 expstatsn;
249 	int			 state;
250 	int			 fd;
251 	u_int16_t		 cid;	/* conection id */
252 };
253 
254 struct task {
255 	TAILQ_ENTRY(task)	 entry;
256 	struct pduq		 sendq;
257 	struct pduq		 recvq;
258 	void			*callarg;
259 	void	(*callback)(struct connection *, void *, struct pdu *);
260 	void	(*failback)(void *);
261 	u_int32_t		 cmdseqnum;
262 	u_int32_t		 itt;
263 	u_int8_t		 pending;
264 };
265 
266 struct kvp {
267 	char	*key;
268 	char	*value;
269 	long	 flags;
270 };
271 #define KVP_KEY_ALLOCED		0x01
272 #define KVP_VALUE_ALLOCED	0x02
273 
274 extern const struct session_params iscsi_sess_defaults;
275 extern const struct connection_params iscsi_conn_defaults;
276 extern struct session_params initiator_sess_defaults;
277 extern struct connection_params initiator_conn_defaults;
278 
279 void	iscsid_ctrl_dispatch(void *, struct pdu *);
280 void	iscsi_merge_sess_params(struct session_params *,
281 	    struct session_params *, struct session_params *);
282 void	iscsi_merge_conn_params(struct connection_params *,
283 	    struct connection_params *, struct connection_params *);
284 
285 struct initiator *initiator_init(void);
286 void	initiator_cleanup(struct initiator *);
287 void	initiator_shutdown(struct initiator *);
288 int	initiator_isdown(struct initiator *);
289 struct session *initiator_t2s(u_int);
290 void	initiator_login(struct connection *);
291 void	initiator_discovery(struct session *);
292 void	initiator_logout(struct session *, struct connection *, u_int8_t);
293 void	initiator_nop_in_imm(struct connection *, struct pdu *);
294 char	*default_initiator_name(void);
295 
296 int	control_init(char *);
297 void	control_cleanup(char *);
298 int	control_listen(void);
299 int	control_queue(void *, struct pdu *);
300 int	control_compose(void *, u_int16_t, void *, size_t);
301 
302 struct session	*session_find(struct initiator *, char *);
303 struct session	*session_new(struct initiator *, u_int8_t);
304 void	session_cleanup(struct session *);
305 int	session_shutdown(struct session *);
306 void	session_config(struct session *, struct session_config *);
307 void	session_task_issue(struct session *, struct task *);
308 void	session_logout_issue(struct session *, struct task *);
309 void	session_schedule(struct session *);
310 void	session_task_login(struct connection *);
311 void	session_fsm(struct session *, enum s_event, struct connection *);
312 
313 void	conn_new(struct session *, struct connection_config *);
314 void	conn_free(struct connection *);
315 int	conn_task_ready(struct connection *);
316 void	conn_task_issue(struct connection *, struct task *);
317 void	conn_task_schedule(struct connection *);
318 void	conn_task_cleanup(struct connection *, struct task *);
319 int	conn_parse_kvp(struct connection *, struct kvp *);
320 int	conn_gen_kvp(struct connection *, struct kvp *, size_t *);
321 void	conn_pdu_write(struct connection *, struct pdu *);
322 void	conn_fail(struct connection *);
323 void	conn_fsm(struct connection *, enum c_event);
324 
325 void	*pdu_gethdr(struct pdu *);
326 int	text_to_pdu(struct kvp *, struct pdu *);
327 struct kvp *pdu_to_text(char *, size_t);
328 u_int64_t	text_to_num(const char *, u_int64_t, u_int64_t, const char **);
329 int		text_to_bool(const char *, const char **);
330 void	pdu_free_queue(struct pduq *);
331 ssize_t	pdu_read(struct connection *);
332 ssize_t	pdu_write(struct connection *);
333 int	pdu_pending(struct connection *);
334 void	pdu_parse(struct connection *);
335 int	pdu_readbuf_set(struct pdu_readbuf *, size_t);
336 void	pdu_readbuf_free(struct pdu_readbuf *);
337 
338 struct pdu *pdu_new(void);
339 void	*pdu_alloc(size_t);
340 void	*pdu_dup(void *, size_t);
341 int	pdu_addbuf(struct pdu *, void *, size_t, unsigned int);
342 void	*pdu_getbuf(struct pdu *, size_t *, unsigned int);
343 void	pdu_free(struct pdu *);
344 int	socket_setblockmode(int, int);
345 const char *log_sockaddr(void *);
346 
347 void	task_init(struct task *, struct session *, int, void *,
348 	    void (*)(struct connection *, void *, struct pdu *),
349 	    void (*)(void *));
350 void	taskq_cleanup(struct taskq *);
351 void	task_pdu_add(struct task *, struct pdu *);
352 void	task_pdu_cb(struct connection *, struct pdu *);
353 
354 void	vscsi_open(char *);
355 void	vscsi_dispatch(int, short, void *);
356 void	vscsi_data(unsigned long, int, void *, size_t);
357 void	vscsi_status(int, int, void *, size_t);
358 void	vscsi_event(unsigned long, u_int, u_int);
359