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