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
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
|
/*
* 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 <net/if.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 "list.h"
#define ISCSI_CONFIG_ROOT "/etc/iscsi/"
#define CONFIG_FILE ISCSI_CONFIG_ROOT"iscsid.conf"
#define INITIATOR_NAME_FILE ISCSI_CONFIG_ROOT"initiatorname.iscsi"
#define PID_FILE "/var/run/iscsid.pid"
#define LOCK_DIR "/var/lock/iscsi"
#define LOCK_FILE "/var/lock/iscsi/lock"
#define LOCK_WRITE_FILE "/var/lock/iscsi/lock.write"
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,
LOGIN_REDIRECT = 9,
};
typedef enum iscsi_event_e {
EV_UNKNOWN,
EV_CONN_RECV_PDU,
EV_CONN_POLL,
EV_CONN_ERROR,
EV_CONN_LOGOUT_TIMER,
EV_CONN_LOGOUT,
} iscsi_event_e;
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;
struct iscsi_conn_context;
/* daemon's connection structure */
typedef struct iscsi_conn {
uint32_t id;
struct iscsi_session *session;
iscsi_login_context_t login_context;
struct iscsi_conn_context *recv_context;
struct queue_task *logout_qtask;
char data[ISCSI_DEF_MAX_RECV_SEG_LEN];
char host[NI_MAXHOST]; /* scratch */
iscsi_conn_state_e state;
int userspace_nop;
actor_t login_timer;
actor_t nop_out_timer;
#define CONTEXT_POOL_MAX 32
struct iscsi_conn_context *context_pool[CONTEXT_POOL_MAX];
/* login state machine */
int current_stage;
int next_stage;
int partial_response;
conn_login_status_e status;
/* tcp/socket settings */
int socket_fd;
/* address being used for normal session connection */
struct sockaddr_storage saddr;
/* address recieved during login */
struct sockaddr_storage failback_saddr;
int tcp_window_size;
int type_of_service;
/* used for the IPC of bind and for connect/poll/disconnect by
* transports (eg iser) which does these ops from the kernel.
* In the case of TCP, it is just the transport_fd casted to u64. */
uint64_t transport_ep_handle;
/* timeouts */
int login_timeout;
int logout_timeout;
int auth_timeout;
int active_timeout;
int noop_out_interval;
int noop_out_timeout;
/* sequencing */
uint32_t exp_statsn;
/* negotiated parameters */
uint32_t hdrdgst_en;
uint32_t datadgst_en;
uint32_t max_recv_dlength; /* the value we declare */
uint32_t max_xmit_dlength; /* the value declared by the target */
} iscsi_conn_t;
struct iscsi_conn_context {
struct actor actor;
struct iscsi_conn *conn;
int allocated;
void *data;
};
typedef struct queue_task {
iscsi_conn_t *conn;
iscsiadm_req_t req;
iscsiadm_rsp_t rsp;
int mgmt_ipc_fd;
int allocated : 1;
/* Newer request types include a
* variable-length payload */
void *payload;
} queue_task_t;
struct iscsi_transport_template;
struct iscsi_transport;
/* daemon's session structure */
typedef struct iscsi_session {
struct list_head list;
uint32_t id;
uint32_t hostno;
char netdev[IFNAMSIZ];
struct iscsi_transport *t;
node_rec_t nrec; /* copy of original Node record in database */
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;
uint32_t imm_data_en;
uint32_t initial_r2t_en;
uint32_t fast_abort;
uint32_t first_burst;
uint32_t max_burst;
uint32_t pdu_inorder_en;
uint32_t dataseq_inorder_en;
uint32_t def_time2wait;
uint32_t def_time2retain;
int type;
int portal_group_tag;
uint8_t isid[6];
uint16_t tsih;
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_in_length;
iscsi_conn_t conn[ISCSI_CONN_MAX];
int ctrl_fd;
uint32_t param_mask;
/* connection reopens during recovery */
int reopen_cnt;
queue_task_t reopen_qtask;
iscsi_session_r_stage_e r_stage;
uint32_t replacement_timeout;
int host_reset_timeout;
int lu_reset_timeout;
int abort_timeout;
/* sync up fields */
queue_task_t *sync_qtask;
} iscsi_session_t;
/*
* TODO: replace session_info and host_info with
* node_rec and iface_rec
*/
struct session_info {
struct list_head list;
/* local info */
struct iface_rec iface;
int sid;
/* remote info */
char targetname[TARGET_NAME_MAXLEN + 1];
int tpgt;
char address[NI_MAXHOST + 1];
int port;
char persistent_address[NI_MAXHOST + 1];
int persistent_port;
};
struct host_info {
char iname[TARGET_NAME_MAXLEN + 1];
struct iface_rec iface;
int host_no;
};
/* 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);
extern int resolve_address(char *host, char *port, struct sockaddr_storage *ss);
/* 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
/*
* These user/kernel IPC calls are used by transports (eg iSER) that have their
* native connection managed from the kernel. The IPC for having the user space
* code being able to do it, is implemented as an enhancement of the open iscsi
* netlink IPC scheme, currently with the ability to connect/poll-for-establish
* ment/disconnect an opaque transport dependent 64 bit ep (endpoint) handle.
* The exact IPC ABI for that matter is defined in iscsi_if.h
*/
/* netlink.c */
extern int ktransport_ep_connect(iscsi_conn_t *conn, int non_blocking);
extern int ktransport_ep_poll(iscsi_conn_t *conn, int timeout_ms);
extern void ktransport_ep_disconnect(iscsi_conn_t *conn);
/* io.c */
extern int iscsi_io_tcp_poll(iscsi_conn_t *conn, int timeout_ms);
extern int iscsi_io_tcp_connect(iscsi_conn_t *conn, int non_blocking);
extern void iscsi_io_tcp_disconnect(iscsi_conn_t *conn);
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_sid(int sid);
extern iscsi_session_t *session_find_by_rec(node_rec_t *rec);
extern int session_is_running(node_rec_t *rec);
extern struct iscsi_conn_context *iscsi_conn_context_get(iscsi_conn_t *conn,
int ev_size);
extern void iscsi_conn_context_put(struct iscsi_conn_context *conn_context);
extern void iscsi_sched_conn_context(struct iscsi_conn_context *context,
struct iscsi_conn *conn, unsigned long tmo,
int event);
extern mgmt_ipc_err_e iscsi_sync_session(node_rec_t *rec, queue_task_t
*tsk, uint32_t sid);
extern mgmt_ipc_err_e iscsi_host_send_targets(queue_task_t *qtask,
int host_no, int do_login, struct sockaddr_storage *ss);
extern mgmt_ipc_err_e iscsi_host_set_param(int host_no, int param, char *value);
extern void iscsi_async_session_creation(uint32_t host_no, uint32_t sid);
extern void iscsi_async_session_destruction(uint32_t host_no, uint32_t sid);
extern void free_initiator(void);
/* isns.c */
extern int isns_init(void);
extern void isns_handle(int);
extern void isns_exit(void);
extern int isns_dev_attr_query_task(queue_task_t *qtask);
#endif /* INITIATOR_H */
|