xref: /openbsd/usr.sbin/iscsid/iscsid.h (revision 2224f3a1)
1 /*	$OpenBSD: iscsid.h,v 1.24 2025/01/28 20:41:44 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 #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 DIGEST_NONE		0x1
185 #define DIGEST_CRC32C		0x2
186 
187 #define SESSION_TYPE_NORMAL	0
188 #define SESSION_TYPE_DISCOVERY	1
189 
190 struct session_params {
191 	u_int32_t		 MaxBurstLength;
192 				 /* 262144, 512-to-(2**24-1) (min()): LS */
193 	u_int32_t		 FirstBurstLength;
194 				 /* 65536, 512-to-(2**24-1) (min()): LS */
195 	u_int16_t		 DefaultTime2Wait;
196 				 /* 2, 0-to-3600 (max()): LS */
197 	u_int16_t		 DefaultTime2Retain;
198 				 /* 20, 0-to-3600 (min()): LS */
199 	u_int16_t		 MaxOutstandingR2T;
200 				 /* 1, 1-to-65535 (min()): LS */
201 	u_int16_t		 TargetPortalGroupTag;
202 				 /* 1- 65535: IS */
203 	u_int16_t		 MaxConnections;
204 				 /* 1, 1-65535 (min()): LS */
205 	u_int8_t		 InitialR2T;
206 				 /* yes, bool (||): LS  */
207 	u_int8_t		 ImmediateData;
208 				 /* yes, bool (&&): LS */
209 	u_int8_t		 DataPDUInOrder;
210 				 /* yes, bool (||): LS */
211 	u_int8_t		 DataSequenceInOrder;
212 				 /* yes, bool (||): LS */
213 	u_int8_t		 ErrorRecoveryLevel;
214 				 /* 0, 0 - 2 (min()): LS */
215 };
216 
217 struct connection_params {
218 	u_int32_t		 MaxRecvDataSegmentLength;
219 				 /* 8192, 512-to-(2**24-1): C */
220 				 /* inherited from session_config */
221 	u_int8_t		 HeaderDigest;
222 	u_int8_t		 DataDigest;
223 };
224 
225 struct initiator {
226 	struct session_head	sessions;
227 	struct initiator_config	config;
228 	u_int			target;
229 };
230 
231 struct sessev {
232 	struct event		 ev;
233 	struct session		*sess;
234 	struct connection	*conn;
235 	enum s_event		 event;
236 };
237 
238 struct session {
239 	TAILQ_ENTRY(session)	 entry;
240 	struct sessev		 sev;
241 	struct connection_head	 connections;
242 	struct taskq		 tasks;
243 	struct session_config	 config;
244 	struct session_params	 mine;
245 	struct session_params	 his;
246 	struct session_params	 active;
247 	u_int32_t		 cmdseqnum;
248 	u_int32_t		 itt;
249 	u_int32_t		 isid_base;	/* only 24 bits */
250 	u_int16_t		 isid_qual;	/* inherited from initiator */
251 	u_int16_t		 tsih;		/* target session id handle */
252 	u_int			 target;
253 	int			 holdTimer;	/* internal hold timer */
254 	int			 state;
255 	int			 action;
256 };
257 
258 struct session_poll {
259 	int session_count;
260 	int session_init_count;
261 	int session_running_count;
262 	int conn_logged_in_count;
263 	int conn_failed_count;
264 	int conn_waiting_count;
265 	int sess_conn_status;
266 };
267 
268 struct connection {
269 	struct event		 ev;
270 	struct event		 wev;
271 	struct sessev		 sev;
272 	TAILQ_ENTRY(connection)	 entry;
273 	struct connection_params mine;
274 	struct connection_params his;
275 	struct connection_params active;
276 	struct connection_config config;
277 	struct pdu_readbuf	 prbuf;
278 	struct pduq		 pdu_w;
279 	struct taskq		 tasks;
280 	struct session		*session;
281 	u_int32_t		 expstatsn;
282 	int			 state;
283 	int			 fd;
284 	u_int16_t		 cid;	/* connection id */
285 };
286 
287 struct task {
288 	TAILQ_ENTRY(task)	 entry;
289 	struct pduq		 sendq;
290 	struct pduq		 recvq;
291 	void			*callarg;
292 	void	(*callback)(struct connection *, void *, struct pdu *);
293 	void	(*failback)(void *);
294 	u_int32_t		 cmdseqnum;
295 	u_int32_t		 itt;
296 	u_int8_t		 pending;
297 };
298 
299 struct kvp {
300 	char	*key;
301 	char	*value;
302 	long	 flags;
303 };
304 #define KVP_KEY_ALLOCED		0x01
305 #define KVP_VALUE_ALLOCED	0x02
306 
307 struct vscsi_stats {
308 	u_int64_t	bytes_rd;
309 	u_int64_t	bytes_wr;
310 	u_int64_t	cnt_read;
311 	u_int64_t	cnt_write;
312 	u_int64_t	cnt_i2t;
313 	u_int64_t	cnt_i2t_dir[3];
314 	u_int64_t	cnt_t2i;
315 	u_int64_t	cnt_t2i_status[3];
316 	u_int32_t	cnt_probe;
317 	u_int32_t	cnt_detach;
318 };
319 
320 extern const struct session_params iscsi_sess_defaults;
321 extern const struct connection_params iscsi_conn_defaults;
322 extern struct session_params initiator_sess_defaults;
323 extern struct connection_params initiator_conn_defaults;
324 
325 void	iscsid_ctrl_dispatch(void *, struct pdu *);
326 void	iscsi_merge_sess_params(struct session_params *,
327 	    struct session_params *, struct session_params *);
328 void	iscsi_merge_conn_params(struct connection_params *,
329 	    struct connection_params *, struct connection_params *);
330 
331 void	initiator_init(void);
332 void	initiator_cleanup(void);
333 void	initiator_set_config(struct initiator_config *);
334 struct initiator_config *initiator_get_config(void);
335 void	initiator_shutdown(void);
336 int	initiator_isdown(void);
337 struct session	*initiator_new_session(u_int8_t);
338 struct session	*initiator_find_session(char *);
339 struct session	*initiator_t2s(u_int);
340 struct session_head	*initiator_get_sessions(void);
341 void	initiator_login(struct connection *);
342 void	initiator_discovery(struct session *);
343 void	initiator_logout(struct session *, struct connection *, u_int8_t);
344 void	initiator_nop_in_imm(struct connection *, struct pdu *);
345 char	*default_initiator_name(void);
346 
347 int	control_init(char *);
348 void	control_cleanup(char *);
349 void	control_event_init(void);
350 void	control_queue(void *, struct pdu *);
351 int	control_compose(void *, u_int16_t, void *, size_t);
352 int	control_build(void *, u_int16_t, int, struct ctrldata *);
353 
354 void	session_cleanup(struct session *);
355 int	session_shutdown(struct session *);
356 void	session_config(struct session *, struct session_config *);
357 void	session_task_issue(struct session *, struct task *);
358 void	session_logout_issue(struct session *, struct task *);
359 void	session_schedule(struct session *);
360 void	session_fsm(struct sessev *, enum s_event, unsigned int);
361 void	session_fsm_callback(int, short, void *);
362 
363 void	conn_new(struct session *, struct connection_config *);
364 void	conn_free(struct connection *);
365 int	conn_task_ready(struct connection *);
366 void	conn_task_issue(struct connection *, struct task *);
367 void	conn_task_schedule(struct connection *);
368 void	conn_task_cleanup(struct connection *, struct task *);
369 int	conn_parse_kvp(struct connection *, struct kvp *);
370 int	kvp_set_from_mine(struct kvp *, const char *, struct connection *);
371 void	conn_pdu_write(struct connection *, struct pdu *);
372 void	conn_fail(struct connection *);
373 void	conn_fsm(struct connection *, enum c_event);
374 
375 void	*pdu_gethdr(struct pdu *);
376 int	text_to_pdu(struct kvp *, struct pdu *);
377 struct kvp *pdu_to_text(char *, size_t);
378 u_int64_t	text_to_num(const char *, u_int64_t, u_int64_t, const char **);
379 int		text_to_bool(const char *, const char **);
380 int		text_to_digest(const char *, const char **);
381 void	pdu_free_queue(struct pduq *);
382 ssize_t	pdu_read(struct connection *);
383 ssize_t	pdu_write(struct connection *);
384 int	pdu_pending(struct connection *);
385 void	pdu_parse(struct connection *);
386 int	pdu_readbuf_set(struct pdu_readbuf *, size_t);
387 void	pdu_readbuf_free(struct pdu_readbuf *);
388 
389 struct pdu *pdu_new(void);
390 void	*pdu_alloc(size_t);
391 void	*pdu_dup(void *, size_t);
392 int	pdu_addbuf(struct pdu *, void *, size_t, unsigned int);
393 void	*pdu_getbuf(struct pdu *, size_t *, unsigned int);
394 void	pdu_free(struct pdu *);
395 int	socket_setblockmode(int, int);
396 const char *log_sockaddr(void *);
397 void	kvp_free(struct kvp *);
398 
399 void	task_init(struct task *, struct session *, int, void *,
400 	    void (*)(struct connection *, void *, struct pdu *),
401 	    void (*)(void *));
402 void	taskq_cleanup(struct taskq *);
403 void	task_pdu_add(struct task *, struct pdu *);
404 void	task_pdu_cb(struct connection *, struct pdu *);
405 
406 void	vscsi_open(char *);
407 void	vscsi_dispatch(int, short, void *);
408 void	vscsi_data(unsigned long, int, void *, size_t);
409 void	vscsi_status(int, int, void *, size_t);
410 void	vscsi_event(unsigned long, u_int, u_int);
411 struct vscsi_stats *vscsi_stats(void);
412 
413 /* Session polling */
414 void    poll_session(struct session_poll *, struct session *);
415 void    poll_finalize(struct session_poll *);
416 
417 /* logmsg.c */
418 void	log_hexdump(void *, size_t);
419 void	log_pdu(struct pdu *, int);
420