summaryrefslogtreecommitdiff
path: root/usr/initiator.h
blob: 2799b168c5739b33500b1271c87b8ef010ad70c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/*
 * iSCSI Initiator
 *
 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
 * maintained by open-iscsi@googlegroups.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * See the file COPYING included with this distribution for more details.
 */

#ifndef INITIATOR_H
#define INITIATOR_H

#include <stdint.h>

#include "types.h"
#include "iscsi_proto.h"
#include "iscsi_if.h"
#include "auth.h"
#include "mgmt_ipc.h"
#include "config.h"
#include "actor.h"
#include "queue.h"

#define CONFIG_FILE		"/etc/iscsid.conf"
#define PID_FILE		"/var/run/iscsid.pid"
#define INITIATOR_NAME_FILE	"/etc/initiatorname.iscsi"
#define DISCOVERY_FILE		"/var/db/iscsi/discovery"
#define NODE_FILE		"/var/db/iscsi/node"

#define DEF_ISCSI_PORT		3260

typedef enum conn_login_status_e {
	CONN_LOGIN_SUCCESS		= 0,
	CONN_LOGIN_FAILED		= 1,
	CONN_LOGIN_IO_ERR		= 2,
	CONN_LOGIN_RETRY		= 3,
	CONN_LOGIN_IMM_RETRY		= 4,
	CONN_LOGIN_IMM_REDIRECT_RETRY	= 5,
} conn_login_status_e;

enum iscsi_login_status {
	LOGIN_OK			= 0,
	LOGIN_IO_ERROR			= 1,
	LOGIN_FAILED			= 2,
	LOGIN_VERSION_MISMATCH		= 3,
	LOGIN_NEGOTIATION_FAILED	= 4,
	LOGIN_AUTHENTICATION_FAILED	= 5,
	LOGIN_WRONG_PORTAL_GROUP	= 6,
	LOGIN_REDIRECTION_FAILED	= 7,
	LOGIN_INVALID_PDU		= 8,
};

typedef enum iscsi_conn_state_e {
	STATE_FREE			= 0,
	STATE_XPT_WAIT			= 1,
	STATE_IN_LOGIN			= 2,
	STATE_LOGGED_IN			= 3,
	STATE_IN_LOGOUT			= 4,
	STATE_LOGOUT_REQUESTED		= 5,
	STATE_CLEANUP_WAIT		= 6,
} iscsi_conn_state_e;

typedef enum iscsi_session_r_stage_e {
	R_STAGE_NO_CHANGE		= 0,
	R_STAGE_SESSION_CLEANUP		= 1,
	R_STAGE_SESSION_REOPEN		= 2,
} iscsi_session_r_stage_e;

typedef enum iscsi_event_e {
	EV_UNKNOWN			= 0,
	EV_CONN_RECV_PDU		= 1,
	EV_CONN_POLL			= 2,
	EV_CONN_TIMER			= 3,
	EV_CONN_ERROR			= 4,
} iscsi_event_e;

typedef struct iscsi_event {
	queue_item_t item;
	char payload[EVENT_PAYLOAD_MAX];
} iscsi_event_t;

struct queue_task;

typedef struct iscsi_login_context {
	int cid;
	char *buffer;
	size_t bufsize;
	uint8_t status_class;
	uint8_t status_detail;
	struct iscsi_acl *auth_client;
	struct iscsi_hdr pdu;
	struct iscsi_login_rsp *login_rsp;
	char *data;
	int received_pdu;
	int max_data_length;
	int timeout;
	int final;
	enum iscsi_login_status ret;
	struct queue_task *qtask;
} iscsi_login_context_t;

struct iscsi_session;
struct iscsi_conn;

typedef void (*send_pdu_begin_f) (uint64_t transport_handle, uint64_t connh,
                                int hdr_size, int data_size);
typedef int (*send_pdu_end_f) (uint64_t transport_handle, uint64_t connh,
                             int *retcode);
typedef int (*recv_pdu_begin_f) (uint64_t transport_handle, uint64_t connh,
                                uintptr_t recv_handle, uintptr_t *pdu_handle,
                                int *pdu_size);
typedef int (*recv_pdu_end_f) (uint64_t transport_handle, uintptr_t conn_handle,
                             uintptr_t pdu_handle);
typedef void (*send_pdu_timer_add_f)(struct iscsi_conn *conn, int timeout);
typedef void (*send_pdu_timer_remove_f)(struct iscsi_conn *conn);

/* daemon's connection structure */
typedef struct iscsi_conn {
	struct qelem item; /* must stay at the top */
	int id;
	uint64_t handle;
	uintptr_t recv_handle;
	struct iscsi_session *session;
	iscsi_login_context_t login_context;
	char data[DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH];
	iscsi_conn_state_e state;
	actor_t connect_timer;
	actor_t send_pdu_timer;
	int send_pdu_in_progress;

	int kernel_io;
	send_pdu_begin_f send_pdu_begin;
	send_pdu_end_f send_pdu_end;
	recv_pdu_begin_f recv_pdu_begin;
	recv_pdu_end_f recv_pdu_end;
	send_pdu_timer_add_f send_pdu_timer_add;
	send_pdu_timer_remove_f send_pdu_timer_remove;

#define RECVPOOL_MAX	32
	void* recvpool[RECVPOOL_MAX];

	/* login state machine */
	int current_stage;
	int next_stage;
	int partial_response;
	conn_login_status_e status;

	/* tcp/socket settings */
	int socket_fd;
	struct sockaddr_in addr;
	uint8_t ip_address[16];
	int ip_length;
	int port;
	int tcp_window_size;
	int type_of_service;

	/* timeouts */
	int login_timeout;
	int auth_timeout;
	int active_timeout;
	int idle_timeout;
	int ping_timeout;

	/* sequencing */
	uint32_t exp_statsn;

	/* negotiated parameters */
	int hdrdgst_en;
	int datadgst_en;
	int max_recv_dlength;	/* the value we declare */
	int max_xmit_dlength;	/* the value declared by the target */
} iscsi_conn_t;

typedef struct queue_task {
	iscsi_conn_t *conn;
	union {
		/* iSCSI requests originated via IPC */
		struct ipcreq_login {
			iscsiadm_req_t req;
			iscsiadm_rsp_t rsp;
			int mgmt_ipc_fd;
		} login;
		struct ipcreq_logout {
			iscsiadm_req_t req;
			iscsiadm_rsp_t rsp;
			int mgmt_ipc_fd;
		} logout;
		/* iSCSI requests originated via CTL */
		struct ctlreq_recv_pdu {
		} recv_pdu;
	} u;
} queue_task_t;

/* daemon's session structure */
typedef struct iscsi_session {
	struct qelem item; /* must stay at the top */
	int id;
	uint64_t transport_handle;
	uint64_t handle;
	node_rec_t nrec; /* copy of original Node record in database */
	int vendor_specific_keys;
	unsigned int irrelevant_keys_bitmap;
	int send_async_text;
	uint32_t itt;
	uint32_t cmdsn;
	uint32_t exp_cmdsn;
	uint32_t max_cmdsn;
	int erl;
	int imm_data_en;
	int initial_r2t_en;
	int first_burst;
	int max_burst;
	int pdu_inorder_en;
	int dataseq_inorder_en;
	int def_time2wait;
	int def_time2retain;
	int type;
	int portal_group_tag;
	uint8_t isid[6];
	uint16_t tsih;
	int channel;
	int target_id;
	char target_name[TARGET_NAME_MAXLEN + 1];
	char *target_alias;
	char *initiator_name;
	char *initiator_alias;
	struct auth_str_block auth_recv_string_block;
	struct auth_str_block auth_send_string_block;
	struct auth_large_binary auth_recv_binary_block;
	struct auth_large_binary auth_send_binary_block;
	struct iscsi_acl auth_client_block;
	struct iscsi_acl *auth_client;
	int num_auth_buffers;
	struct auth_buffer_desc auth_buffers[5];
	int bidirectional_auth;
	char username[AUTH_STR_MAX_LEN];
	uint8_t password[AUTH_STR_MAX_LEN];
	int password_length;
	char username_in[AUTH_STR_MAX_LEN];
	uint8_t password_in[AUTH_STR_MAX_LEN];
	int password_length_in;
	iscsi_conn_t conn[ISCSI_CONN_MAX];
	int ctrl_fd;

	/* connection reopens during recovery */
	int reopen_cnt;
	queue_task_t reopen_qtask;
	iscsi_session_r_stage_e r_stage;

	/* session's processing */
	actor_t mainloop;
	queue_t *queue;
} iscsi_session_t;

typedef enum iscsi_provider_status_e {
	PROVIDER_STATUS_UNKNOWN		= 0,
	PROVIDER_STATUS_OPERATIONAL	= 1,
	PROVIDER_STATUS_FAILED		= 2,
} iscsi_provider_status_e;

/* represents data path provider */
typedef struct iscsi_provider_t {
	uint64_t handle;
	iscsi_provider_status_e status;
	char name[ISCSI_TRANSPORT_NAME_MAXLEN];
	struct qelem sessions;
} iscsi_provider_t;

/* iscsid.c */
extern iscsi_provider_t provider[ISCSI_TRANSPORT_MAX];

/* login.c */

#define ISCSI_SESSION_TYPE_NORMAL 0
#define ISCSI_SESSION_TYPE_DISCOVERY 1

/* not defined by iSCSI, but used in the login code to determine
 * when to send the initial Login PDU
 */
#define ISCSI_INITIAL_LOGIN_STAGE -1

#define ISCSI_TEXT_SEPARATOR     '='

/* implemented in iscsi-login.c for use on all platforms */
extern int iscsi_add_text(struct iscsi_hdr *hdr, char *data, int max_data_length,
			char *param, char *value);
extern enum iscsi_login_status iscsi_login(iscsi_session_t *session, int cid,
		   char *buffer, size_t bufsize, uint8_t * status_class,
		   uint8_t * status_detail);
extern int iscsi_update_address(iscsi_conn_t *conn, char *address);
extern int iscsi_login_begin(iscsi_session_t *session,
			     iscsi_login_context_t *c);
extern int iscsi_login_req(iscsi_session_t *session, iscsi_login_context_t *c);
extern int iscsi_login_rsp(iscsi_session_t *session, iscsi_login_context_t *c);

/* Digest types */
#define ISCSI_DIGEST_NONE  0
#define ISCSI_DIGEST_CRC32C 1
#define ISCSI_DIGEST_CRC32C_NONE 2	/* offer both, prefer CRC32C */
#define ISCSI_DIGEST_NONE_CRC32C 3	/* offer both, prefer None */

#define IRRELEVANT_MAXCONNECTIONS	0x01
#define IRRELEVANT_INITIALR2T		0x02
#define IRRELEVANT_IMMEDIATEDATA	0x04
#define IRRELEVANT_MAXBURSTLENGTH	0x08
#define IRRELEVANT_FIRSTBURSTLENGTH	0x10
#define IRRELEVANT_MAXOUTSTANDINGR2T	0x20
#define IRRELEVANT_DATAPDUINORDER	0x40
#define IRRELEVANT_DATASEQUENCEINORDER	0x80

/* io.c */
extern int iscsi_io_tcp_poll(iscsi_conn_t *conn);
extern int iscsi_io_tcp_connect(iscsi_conn_t *conn, int non_blocking);
extern int iscsi_io_connect(iscsi_conn_t *conn);
extern void iscsi_io_disconnect(iscsi_conn_t *conn);
extern int iscsi_io_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr,
	       int hdr_digest, char *data, int data_digest, int timeout);
extern int iscsi_io_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr,
	int hdr_digest, char *data, int max_data_length, int data_digest,
	int timeout);

/* initiator.c */
extern int session_login_task(node_rec_t *rec, queue_task_t *qtask);
extern int session_logout_task(iscsi_session_t *session, queue_task_t *qtask);
extern iscsi_session_t* session_find_by_rec(node_rec_t *rec);
extern void* recvpool_get(iscsi_conn_t *conn, int ev_size);
extern void recvpool_put(iscsi_conn_t *conn, void *handle);

#endif /* INITIATOR_H */