xref: /openbsd-src/usr.sbin/iscsid/iscsid.h (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: iscsid.h,v 1.14 2014/05/10 11:30:47 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 #define ISCSID_HOLD_TIME_MAX	128
27 
28 #define PDU_READ_SIZE		(256 * 1024)
29 #define CONTROL_READ_SIZE	8192
30 #define PDU_MAXIOV		5
31 #define PDU_WRIOV		(PDU_MAXIOV * 8)
32 
33 #define PDU_HEADER	0
34 #define PDU_AHS		1
35 #define PDU_HDIGEST	2
36 #define PDU_DATA	3
37 #define PDU_DDIGEST	4
38 
39 #define PDU_LEN(x)	((((x) + 3) / 4) * 4)
40 
41 /*
42  * Common control message header.
43  * A message can consist of up to 3 parts with specified length.
44  */
45 struct ctrlmsghdr {
46 	u_int16_t	type;
47 	u_int16_t	len[3];
48 };
49 
50 struct ctrldata {
51 	void		*buf;
52 	size_t		 len;
53 };
54 
55 #define CTRLARGV(x...)	((struct ctrldata []){ x })
56 
57 /* Control message types */
58 #define CTRL_SUCCESS		1
59 #define CTRL_FAILURE		2
60 #define CTRL_INPROGRESS		3
61 #define CTRL_INITIATOR_CONFIG	4
62 #define CTRL_SESSION_CONFIG	5
63 #define CTRL_LOG_VERBOSE	6
64 #define CTRL_VSCSI_STATS	7
65 #define CTRL_SHOW_SUM		8
66 
67 
68 TAILQ_HEAD(session_head, session);
69 TAILQ_HEAD(connection_head, connection);
70 TAILQ_HEAD(pduq, pdu);
71 TAILQ_HEAD(taskq, task);
72 
73 /* as in tcp_seq.h */
74 #define SEQ_LT(a,b)     ((int)((a)-(b)) < 0)
75 #define SEQ_LEQ(a,b)    ((int)((a)-(b)) <= 0)
76 #define SEQ_GT(a,b)     ((int)((a)-(b)) > 0)
77 #define SEQ_GEQ(a,b)    ((int)((a)-(b)) >= 0)
78 
79 #define SESS_INIT		0x0001
80 #define SESS_FREE		0x0002
81 #define SESS_LOGGED_IN		0x0004
82 #define SESS_FAILED		0x0008
83 #define SESS_ANYSTATE		0xffff
84 #define SESS_RUNNING		(SESS_FREE | SESS_LOGGED_IN | SESS_FAILED)
85 
86 #define CONN_FREE		0x0001	/* S1 = R3 */
87 #define CONN_XPT_WAIT		0x0002	/* S2 */
88 #define CONN_XPT_UP		0x0004	/* S3 */
89 #define CONN_IN_LOGIN		0x0008	/* S4 */
90 #define CONN_LOGGED_IN		0x0010	/* S5 */
91 #define CONN_IN_LOGOUT		0x0020	/* S6 */
92 #define CONN_LOGOUT_REQ		0x0040	/* S7 */
93 #define CONN_CLEANUP_WAIT	0x0080	/* S8 = R1 */
94 #define CONN_IN_CLEANUP		0x0100	/* R2 */
95 #define CONN_ANYSTATE		0xffff
96 #define CONN_RUNNING		(CONN_LOGGED_IN | CONN_LOGOUT_REQ)
97 #define CONN_FAILED		(CONN_CLEANUP_WAIT | CONN_IN_CLEANUP)
98 #define CONN_NEVER_LOGGED_IN	(CONN_FREE | CONN_XPT_WAIT | CONN_XPT_UP | \
99 				    CONN_IN_LOGIN)
100 
101 enum c_event {
102 	CONN_EV_FAIL,
103 	CONN_EV_FREE,
104 	CONN_EV_CONNECT,
105 	CONN_EV_CONNECTED,
106 	CONN_EV_LOGGED_IN,
107 	CONN_EV_REQ_LOGOUT,
108 	CONN_EV_LOGOUT,
109 	CONN_EV_LOGGED_OUT,
110 	CONN_EV_CLOSED,
111 	CONN_EV_CLEANING_UP
112 };
113 
114 enum s_event {
115 	SESS_EV_START,
116 	SESS_EV_STOP,
117 	SESS_EV_CONN_LOGGED_IN,
118 	SESS_EV_CONN_FAIL,
119 	SESS_EV_CONN_CLOSED,
120 	SESS_EV_REINSTATEMENT,
121 	SESS_EV_TIMEOUT,
122 	SESS_EV_CLOSED,
123 	SESS_EV_FAIL,
124 	SESS_EV_FREE
125 };
126 
127 #define SESS_ACT_UP		0
128 #define SESS_ACT_DOWN		1
129 
130 struct pdu {
131 	TAILQ_ENTRY(pdu)	 entry;
132 	struct iovec		 iov[PDU_MAXIOV];
133 	size_t			 resid;
134 };
135 
136 struct pdu_readbuf {
137 	char		*buf;
138 	size_t		 size;
139 	size_t		 rpos;
140 	size_t		 wpos;
141 	struct pdu	*wip;
142 };
143 
144 struct connection_config {
145 	/* values inherited from session_config */
146 	struct sockaddr_storage	 TargetAddr;	/* IP:port of target */
147 	struct sockaddr_storage	 LocalAddr;	/* IP:port of target */
148 };
149 
150 struct initiator_config {
151 	u_int32_t		isid_base;	/* only 24 bits */
152 	u_int16_t		isid_qual;
153 	u_int16_t		pad;
154 };
155 
156 struct session_config {
157 	/* unique session ID */
158 	char			SessionName[32];
159 	/*
160 	 * I = initialize only, L = leading only
161 	 * S = session wide, C = connection only
162 	 */
163 	struct connection_config connection;
164 
165 	char			*TargetName;	/* String: IS */
166 
167 	char			*InitiatorName;	/* String: IS */
168 
169 	u_int16_t		 MaxConnections;
170 				 /* 1, 1-65535 (min()): LS */
171 	u_int8_t		 HeaderDigest;
172 				 /* None , (None|CRC32): IC */
173 	u_int8_t		 DataDigest;
174 				 /* None , (None|CRC32): IC */
175 	u_int8_t		 SessionType;
176 				 /* Normal, (Discovery|Normal): LS */
177 	u_int8_t		 disabled;
178 };
179 
180 #define SESSION_TYPE_NORMAL	0
181 #define SESSION_TYPE_DISCOVERY	1
182 
183 struct session_params {
184 	u_int32_t		 MaxBurstLength;
185 				 /* 262144, 512-to-(2**24-1) (min()): LS */
186 	u_int32_t		 FirstBurstLength;
187 				 /* 65536, 512-to-(2**24-1) (min()): LS */
188 	u_int16_t		 DefaultTime2Wait;
189 				 /* 2, 0-to-3600 (max()): LS */
190 	u_int16_t		 DefaultTime2Retain;
191 				 /* 20, 0-to-3600 (min()): LS */
192 	u_int16_t		 MaxOutstandingR2T;
193 				 /* 1, 1-to-65535 (min()): LS */
194 	u_int16_t		 TargetPortalGroupTag;
195 				 /* 1- 65535: IS */
196 	u_int16_t		 MaxConnections;
197 				 /* 1, 1-65535 (min()): LS */
198 	u_int8_t		 InitialR2T;
199 				 /* yes, bool (||): LS  */
200 	u_int8_t		 ImmediateData;
201 				 /* yes, bool (&&): LS */
202 	u_int8_t		 DataPDUInOrder;
203 				 /* yes, bool (||): LS */
204 	u_int8_t		 DataSequenceInOrder;
205 				 /* yes, bool (||): LS */
206 	u_int8_t		 ErrorRecoveryLevel;
207 				 /* 0, 0 - 2 (min()): LS */
208 };
209 
210 struct connection_params {
211 	u_int32_t		 MaxRecvDataSegmentLength;
212 				 /* 8192, 512-to-(2**24-1): C */
213 				 /* inherited from session_config */
214 	u_int8_t		 HeaderDigest;
215 	u_int8_t		 DataDigest;
216 };
217 
218 struct initiator {
219 	struct session_head	sessions;
220 	struct initiator_config	config;
221 	u_int			target;
222 };
223 
224 struct sessev {
225 	struct session		*sess;
226 	struct connection	*conn;
227 	enum s_event		 event;
228 };
229 
230 struct session {
231 	TAILQ_ENTRY(session)	 entry;
232 	struct connection_head	 connections;
233 	struct taskq		 tasks;
234 	struct session_config	 config;
235 	struct session_params	 mine;
236 	struct session_params	 his;
237 	struct session_params	 active;
238 	struct initiator	*initiator;
239 	u_int32_t		 cmdseqnum;
240 	u_int32_t		 itt;
241 	u_int32_t		 isid_base;	/* only 24 bits */
242 	u_int16_t		 isid_qual;	/* inherited from initiator */
243 	u_int16_t		 tsih;		/* target session id handle */
244 	u_int			 target;
245 	int			 holdTimer;	/* internal hold timer */
246 	int			 state;
247 	int			 action;
248 };
249 
250 struct connection {
251 	struct event		 ev;
252 	struct event		 wev;
253 	TAILQ_ENTRY(connection)	 entry;
254 	struct connection_params mine;
255 	struct connection_params his;
256 	struct connection_params active;
257 	struct connection_config config;
258 	struct pdu_readbuf	 prbuf;
259 	struct pduq		 pdu_w;
260 	struct taskq		 tasks;
261 	struct session		*session;
262 	u_int32_t		 expstatsn;
263 	int			 state;
264 	int			 fd;
265 	u_int16_t		 cid;	/* conection id */
266 };
267 
268 struct task {
269 	TAILQ_ENTRY(task)	 entry;
270 	struct pduq		 sendq;
271 	struct pduq		 recvq;
272 	void			*callarg;
273 	void	(*callback)(struct connection *, void *, struct pdu *);
274 	void	(*failback)(void *);
275 	u_int32_t		 cmdseqnum;
276 	u_int32_t		 itt;
277 	u_int8_t		 pending;
278 };
279 
280 struct kvp {
281 	char	*key;
282 	char	*value;
283 	long	 flags;
284 };
285 #define KVP_KEY_ALLOCED		0x01
286 #define KVP_VALUE_ALLOCED	0x02
287 
288 struct vscsi_stats {
289 	u_int64_t	bytes_rd;
290 	u_int64_t	bytes_wr;
291 	u_int64_t	cnt_read;
292 	u_int64_t	cnt_write;
293 	u_int64_t	cnt_i2t;
294 	u_int64_t	cnt_i2t_dir[3];
295 	u_int64_t	cnt_t2i;
296 	u_int64_t	cnt_t2i_status[3];
297 	u_int32_t	cnt_probe;
298 	u_int32_t	cnt_detach;
299 };
300 
301 extern const struct session_params iscsi_sess_defaults;
302 extern const struct connection_params iscsi_conn_defaults;
303 extern struct session_params initiator_sess_defaults;
304 extern struct connection_params initiator_conn_defaults;
305 
306 void	iscsid_ctrl_dispatch(void *, struct pdu *);
307 void	iscsi_merge_sess_params(struct session_params *,
308 	    struct session_params *, struct session_params *);
309 void	iscsi_merge_conn_params(struct connection_params *,
310 	    struct connection_params *, struct connection_params *);
311 
312 struct initiator *initiator_init(void);
313 void	initiator_cleanup(struct initiator *);
314 void	initiator_shutdown(struct initiator *);
315 int	initiator_isdown(struct initiator *);
316 struct session *initiator_t2s(u_int);
317 void	initiator_login(struct connection *);
318 void	initiator_discovery(struct session *);
319 void	initiator_logout(struct session *, struct connection *, u_int8_t);
320 void	initiator_nop_in_imm(struct connection *, struct pdu *);
321 char	*default_initiator_name(void);
322 
323 int	control_init(char *);
324 void	control_cleanup(char *);
325 void	control_event_init(void);
326 void	control_queue(void *, struct pdu *);
327 int	control_compose(void *, u_int16_t, void *, size_t);
328 int	control_build(void *, u_int16_t, int, struct ctrldata *);
329 
330 struct session	*session_find(struct initiator *, char *);
331 struct session	*session_new(struct initiator *, u_int8_t);
332 void	session_cleanup(struct session *);
333 int	session_shutdown(struct session *);
334 void	session_config(struct session *, struct session_config *);
335 void	session_task_issue(struct session *, struct task *);
336 void	session_logout_issue(struct session *, struct task *);
337 void	session_schedule(struct session *);
338 void	session_task_login(struct connection *);
339 void	session_fsm(struct session *, enum s_event, struct connection *,
340 	    unsigned int);
341 
342 void	conn_new(struct session *, struct connection_config *);
343 void	conn_free(struct connection *);
344 int	conn_task_ready(struct connection *);
345 void	conn_task_issue(struct connection *, struct task *);
346 void	conn_task_schedule(struct connection *);
347 void	conn_task_cleanup(struct connection *, struct task *);
348 int	conn_parse_kvp(struct connection *, struct kvp *);
349 int	conn_gen_kvp(struct connection *, struct kvp *, size_t *);
350 void	conn_pdu_write(struct connection *, struct pdu *);
351 void	conn_fail(struct connection *);
352 void	conn_fsm(struct connection *, enum c_event);
353 
354 void	*pdu_gethdr(struct pdu *);
355 int	text_to_pdu(struct kvp *, struct pdu *);
356 struct kvp *pdu_to_text(char *, size_t);
357 u_int64_t	text_to_num(const char *, u_int64_t, u_int64_t, const char **);
358 int		text_to_bool(const char *, const char **);
359 void	pdu_free_queue(struct pduq *);
360 ssize_t	pdu_read(struct connection *);
361 ssize_t	pdu_write(struct connection *);
362 int	pdu_pending(struct connection *);
363 void	pdu_parse(struct connection *);
364 int	pdu_readbuf_set(struct pdu_readbuf *, size_t);
365 void	pdu_readbuf_free(struct pdu_readbuf *);
366 
367 struct pdu *pdu_new(void);
368 void	*pdu_alloc(size_t);
369 void	*pdu_dup(void *, size_t);
370 int	pdu_addbuf(struct pdu *, void *, size_t, unsigned int);
371 void	*pdu_getbuf(struct pdu *, size_t *, unsigned int);
372 void	pdu_free(struct pdu *);
373 int	socket_setblockmode(int, int);
374 const char *log_sockaddr(void *);
375 
376 void	task_init(struct task *, struct session *, int, void *,
377 	    void (*)(struct connection *, void *, struct pdu *),
378 	    void (*)(void *));
379 void	taskq_cleanup(struct taskq *);
380 void	task_pdu_add(struct task *, struct pdu *);
381 void	task_pdu_cb(struct connection *, struct pdu *);
382 
383 void	vscsi_open(char *);
384 void	vscsi_dispatch(int, short, void *);
385 void	vscsi_data(unsigned long, int, void *, size_t);
386 void	vscsi_status(int, int, void *, size_t);
387 void	vscsi_event(unsigned long, u_int, u_int);
388 struct vscsi_stats *vscsi_stats(void);
389