Commit | Line | Data |
---|---|---|
e48354ce NB |
1 | /******************************************************************************* |
2 | * This file contains main functions related to iSCSI Parameter negotiation. | |
3 | * | |
4c76251e | 4 | * (c) Copyright 2007-2013 Datera, Inc. |
e48354ce NB |
5 | * |
6 | * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | ******************************************************************************/ | |
18 | ||
19 | #include <linux/ctype.h> | |
e5419865 | 20 | #include <linux/kthread.h> |
e48354ce NB |
21 | #include <scsi/iscsi_proto.h> |
22 | #include <target/target_core_base.h> | |
c4795fb2 | 23 | #include <target/target_core_fabric.h> |
baa4d64b | 24 | #include <target/iscsi/iscsi_transport.h> |
e48354ce | 25 | |
67f091f2 | 26 | #include <target/iscsi/iscsi_target_core.h> |
e48354ce NB |
27 | #include "iscsi_target_parameters.h" |
28 | #include "iscsi_target_login.h" | |
29 | #include "iscsi_target_nego.h" | |
30 | #include "iscsi_target_tpg.h" | |
31 | #include "iscsi_target_util.h" | |
32 | #include "iscsi_target.h" | |
33 | #include "iscsi_target_auth.h" | |
34 | ||
35 | #define MAX_LOGIN_PDUS 7 | |
36 | #define TEXT_LEN 4096 | |
37 | ||
38 | void convert_null_to_semi(char *buf, int len) | |
39 | { | |
40 | int i; | |
41 | ||
42 | for (i = 0; i < len; i++) | |
43 | if (buf[i] == '\0') | |
44 | buf[i] = ';'; | |
45 | } | |
46 | ||
fceb5bc7 | 47 | static int strlen_semi(char *buf) |
e48354ce NB |
48 | { |
49 | int i = 0; | |
50 | ||
51 | while (buf[i] != '\0') { | |
52 | if (buf[i] == ';') | |
53 | return i; | |
54 | i++; | |
55 | } | |
56 | ||
57 | return -1; | |
58 | } | |
59 | ||
60 | int extract_param( | |
61 | const char *in_buf, | |
62 | const char *pattern, | |
63 | unsigned int max_length, | |
64 | char *out_buf, | |
65 | unsigned char *type) | |
66 | { | |
67 | char *ptr; | |
68 | int len; | |
69 | ||
70 | if (!in_buf || !pattern || !out_buf || !type) | |
71 | return -1; | |
72 | ||
73 | ptr = strstr(in_buf, pattern); | |
74 | if (!ptr) | |
75 | return -1; | |
76 | ||
77 | ptr = strstr(ptr, "="); | |
78 | if (!ptr) | |
79 | return -1; | |
80 | ||
81 | ptr += 1; | |
82 | if (*ptr == '0' && (*(ptr+1) == 'x' || *(ptr+1) == 'X')) { | |
83 | ptr += 2; /* skip 0x */ | |
84 | *type = HEX; | |
85 | } else | |
86 | *type = DECIMAL; | |
87 | ||
88 | len = strlen_semi(ptr); | |
89 | if (len < 0) | |
90 | return -1; | |
91 | ||
369653e4 | 92 | if (len >= max_length) { |
5e58b029 | 93 | pr_err("Length of input: %d exceeds max_length:" |
e48354ce NB |
94 | " %d\n", len, max_length); |
95 | return -1; | |
96 | } | |
97 | memcpy(out_buf, ptr, len); | |
98 | out_buf[len] = '\0'; | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | static u32 iscsi_handle_authentication( | |
104 | struct iscsi_conn *conn, | |
105 | char *in_buf, | |
106 | char *out_buf, | |
107 | int in_length, | |
108 | int *out_length, | |
109 | unsigned char *authtype) | |
110 | { | |
111 | struct iscsi_session *sess = conn->sess; | |
112 | struct iscsi_node_auth *auth; | |
113 | struct iscsi_node_acl *iscsi_nacl; | |
c3e51442 | 114 | struct iscsi_portal_group *iscsi_tpg; |
e48354ce NB |
115 | struct se_node_acl *se_nacl; |
116 | ||
117 | if (!sess->sess_ops->SessionType) { | |
118 | /* | |
119 | * For SessionType=Normal | |
120 | */ | |
121 | se_nacl = conn->sess->se_sess->se_node_acl; | |
122 | if (!se_nacl) { | |
123 | pr_err("Unable to locate struct se_node_acl for" | |
124 | " CHAP auth\n"); | |
125 | return -1; | |
126 | } | |
127 | iscsi_nacl = container_of(se_nacl, struct iscsi_node_acl, | |
128 | se_node_acl); | |
129 | if (!iscsi_nacl) { | |
130 | pr_err("Unable to locate struct iscsi_node_acl for" | |
131 | " CHAP auth\n"); | |
132 | return -1; | |
133 | } | |
134 | ||
c3e51442 NB |
135 | if (se_nacl->dynamic_node_acl) { |
136 | iscsi_tpg = container_of(se_nacl->se_tpg, | |
137 | struct iscsi_portal_group, tpg_se_tpg); | |
138 | ||
139 | auth = &iscsi_tpg->tpg_demo_auth; | |
140 | } else { | |
141 | iscsi_nacl = container_of(se_nacl, struct iscsi_node_acl, | |
142 | se_node_acl); | |
143 | ||
b7eec2cd | 144 | auth = &iscsi_nacl->node_auth; |
c3e51442 | 145 | } |
e48354ce NB |
146 | } else { |
147 | /* | |
148 | * For SessionType=Discovery | |
149 | */ | |
150 | auth = &iscsit_global->discovery_acl.node_auth; | |
151 | } | |
152 | ||
153 | if (strstr("CHAP", authtype)) | |
154 | strcpy(conn->sess->auth_type, "CHAP"); | |
155 | else | |
156 | strcpy(conn->sess->auth_type, NONE); | |
157 | ||
158 | if (strstr("None", authtype)) | |
159 | return 1; | |
160 | #ifdef CANSRP | |
161 | else if (strstr("SRP", authtype)) | |
162 | return srp_main_loop(conn, auth, in_buf, out_buf, | |
163 | &in_length, out_length); | |
164 | #endif | |
165 | else if (strstr("CHAP", authtype)) | |
166 | return chap_main_loop(conn, auth, in_buf, out_buf, | |
167 | &in_length, out_length); | |
168 | else if (strstr("SPKM1", authtype)) | |
169 | return 2; | |
170 | else if (strstr("SPKM2", authtype)) | |
171 | return 2; | |
172 | else if (strstr("KRB5", authtype)) | |
173 | return 2; | |
174 | else | |
175 | return 2; | |
176 | } | |
177 | ||
178 | static void iscsi_remove_failed_auth_entry(struct iscsi_conn *conn) | |
179 | { | |
180 | kfree(conn->auth_protocol); | |
181 | } | |
182 | ||
baa4d64b | 183 | int iscsi_target_check_login_request( |
e48354ce NB |
184 | struct iscsi_conn *conn, |
185 | struct iscsi_login *login) | |
186 | { | |
28168905 | 187 | int req_csg, req_nsg; |
e48354ce NB |
188 | u32 payload_length; |
189 | struct iscsi_login_req *login_req; | |
e48354ce NB |
190 | |
191 | login_req = (struct iscsi_login_req *) login->req; | |
e48354ce NB |
192 | payload_length = ntoh24(login_req->dlength); |
193 | ||
194 | switch (login_req->opcode & ISCSI_OPCODE_MASK) { | |
195 | case ISCSI_OP_LOGIN: | |
196 | break; | |
197 | default: | |
198 | pr_err("Received unknown opcode 0x%02x.\n", | |
199 | login_req->opcode & ISCSI_OPCODE_MASK); | |
200 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
201 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
202 | return -1; | |
203 | } | |
204 | ||
205 | if ((login_req->flags & ISCSI_FLAG_LOGIN_CONTINUE) && | |
206 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { | |
207 | pr_err("Login request has both ISCSI_FLAG_LOGIN_CONTINUE" | |
208 | " and ISCSI_FLAG_LOGIN_TRANSIT set, protocol error.\n"); | |
209 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
210 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
211 | return -1; | |
212 | } | |
213 | ||
5d358065 AG |
214 | req_csg = ISCSI_LOGIN_CURRENT_STAGE(login_req->flags); |
215 | req_nsg = ISCSI_LOGIN_NEXT_STAGE(login_req->flags); | |
e48354ce NB |
216 | |
217 | if (req_csg != login->current_stage) { | |
218 | pr_err("Initiator unexpectedly changed login stage" | |
219 | " from %d to %d, login failed.\n", login->current_stage, | |
220 | req_csg); | |
221 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
222 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
223 | return -1; | |
224 | } | |
225 | ||
226 | if ((req_nsg == 2) || (req_csg >= 2) || | |
227 | ((login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT) && | |
228 | (req_nsg <= req_csg))) { | |
229 | pr_err("Illegal login_req->flags Combination, CSG: %d," | |
230 | " NSG: %d, ISCSI_FLAG_LOGIN_TRANSIT: %d.\n", req_csg, | |
231 | req_nsg, (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)); | |
232 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
233 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
234 | return -1; | |
235 | } | |
236 | ||
237 | if ((login_req->max_version != login->version_max) || | |
238 | (login_req->min_version != login->version_min)) { | |
239 | pr_err("Login request changed Version Max/Nin" | |
240 | " unexpectedly to 0x%02x/0x%02x, protocol error\n", | |
241 | login_req->max_version, login_req->min_version); | |
242 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
243 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
244 | return -1; | |
245 | } | |
246 | ||
247 | if (memcmp(login_req->isid, login->isid, 6) != 0) { | |
248 | pr_err("Login request changed ISID unexpectedly," | |
249 | " protocol error.\n"); | |
250 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
251 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
252 | return -1; | |
253 | } | |
254 | ||
255 | if (login_req->itt != login->init_task_tag) { | |
256 | pr_err("Login request changed ITT unexpectedly to" | |
257 | " 0x%08x, protocol error.\n", login_req->itt); | |
258 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
259 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
260 | return -1; | |
261 | } | |
262 | ||
263 | if (payload_length > MAX_KEY_VALUE_PAIRS) { | |
264 | pr_err("Login request payload exceeds default" | |
265 | " MaxRecvDataSegmentLength: %u, protocol error.\n", | |
266 | MAX_KEY_VALUE_PAIRS); | |
267 | return -1; | |
268 | } | |
269 | ||
270 | return 0; | |
271 | } | |
272 | ||
273 | static int iscsi_target_check_first_request( | |
274 | struct iscsi_conn *conn, | |
275 | struct iscsi_login *login) | |
276 | { | |
277 | struct iscsi_param *param = NULL; | |
278 | struct se_node_acl *se_nacl; | |
279 | ||
280 | login->first_request = 0; | |
281 | ||
282 | list_for_each_entry(param, &conn->param_list->param_list, p_list) { | |
283 | if (!strncmp(param->name, SESSIONTYPE, 11)) { | |
284 | if (!IS_PSTATE_ACCEPTOR(param)) { | |
285 | pr_err("SessionType key not received" | |
286 | " in first login request.\n"); | |
287 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
288 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
289 | return -1; | |
290 | } | |
291 | if (!strncmp(param->value, DISCOVERY, 9)) | |
292 | return 0; | |
293 | } | |
294 | ||
295 | if (!strncmp(param->name, INITIATORNAME, 13)) { | |
296 | if (!IS_PSTATE_ACCEPTOR(param)) { | |
297 | if (!login->leading_connection) | |
298 | continue; | |
299 | ||
300 | pr_err("InitiatorName key not received" | |
301 | " in first login request.\n"); | |
302 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
303 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
304 | return -1; | |
305 | } | |
306 | ||
307 | /* | |
308 | * For non-leading connections, double check that the | |
309 | * received InitiatorName matches the existing session's | |
310 | * struct iscsi_node_acl. | |
311 | */ | |
312 | if (!login->leading_connection) { | |
313 | se_nacl = conn->sess->se_sess->se_node_acl; | |
314 | if (!se_nacl) { | |
315 | pr_err("Unable to locate" | |
316 | " struct se_node_acl\n"); | |
317 | iscsit_tx_login_rsp(conn, | |
318 | ISCSI_STATUS_CLS_INITIATOR_ERR, | |
319 | ISCSI_LOGIN_STATUS_TGT_NOT_FOUND); | |
320 | return -1; | |
321 | } | |
322 | ||
323 | if (strcmp(param->value, | |
324 | se_nacl->initiatorname)) { | |
325 | pr_err("Incorrect" | |
326 | " InitiatorName: %s for this" | |
327 | " iSCSI Initiator Node.\n", | |
328 | param->value); | |
329 | iscsit_tx_login_rsp(conn, | |
330 | ISCSI_STATUS_CLS_INITIATOR_ERR, | |
331 | ISCSI_LOGIN_STATUS_TGT_NOT_FOUND); | |
332 | return -1; | |
333 | } | |
334 | } | |
335 | } | |
336 | } | |
337 | ||
338 | return 0; | |
339 | } | |
340 | ||
341 | static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_login *login) | |
342 | { | |
343 | u32 padding = 0; | |
e48354ce NB |
344 | struct iscsi_login_rsp *login_rsp; |
345 | ||
346 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
347 | ||
348 | login_rsp->opcode = ISCSI_OP_LOGIN_RSP; | |
349 | hton24(login_rsp->dlength, login->rsp_length); | |
350 | memcpy(login_rsp->isid, login->isid, 6); | |
351 | login_rsp->tsih = cpu_to_be16(login->tsih); | |
66c7db68 | 352 | login_rsp->itt = login->init_task_tag; |
e48354ce NB |
353 | login_rsp->statsn = cpu_to_be32(conn->stat_sn++); |
354 | login_rsp->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | |
109e2381 | 355 | login_rsp->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn)); |
e48354ce NB |
356 | |
357 | pr_debug("Sending Login Response, Flags: 0x%02x, ITT: 0x%08x," | |
358 | " ExpCmdSN; 0x%08x, MaxCmdSN: 0x%08x, StatSN: 0x%08x, Length:" | |
66c7db68 | 359 | " %u\n", login_rsp->flags, (__force u32)login_rsp->itt, |
e48354ce NB |
360 | ntohl(login_rsp->exp_cmdsn), ntohl(login_rsp->max_cmdsn), |
361 | ntohl(login_rsp->statsn), login->rsp_length); | |
362 | ||
363 | padding = ((-login->rsp_length) & 3); | |
e5419865 NB |
364 | /* |
365 | * Before sending the last login response containing the transition | |
366 | * bit for full-feature-phase, go ahead and start up TX/RX threads | |
367 | * now to avoid potential resource allocation failures after the | |
368 | * final login response has been sent. | |
369 | */ | |
370 | if (login->login_complete) { | |
371 | int rc = iscsit_start_kthreads(conn); | |
372 | if (rc) { | |
373 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
374 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | |
375 | return -1; | |
376 | } | |
377 | } | |
e48354ce | 378 | |
baa4d64b NB |
379 | if (conn->conn_transport->iscsit_put_login_tx(conn, login, |
380 | login->rsp_length + padding) < 0) | |
e5419865 | 381 | goto err; |
e48354ce NB |
382 | |
383 | login->rsp_length = 0; | |
e48354ce NB |
384 | |
385 | return 0; | |
e5419865 NB |
386 | |
387 | err: | |
388 | if (login->login_complete) { | |
389 | if (conn->rx_thread && conn->rx_thread_active) { | |
390 | send_sig(SIGINT, conn->rx_thread, 1); | |
ca82c2bd | 391 | complete(&conn->rx_login_comp); |
e5419865 NB |
392 | kthread_stop(conn->rx_thread); |
393 | } | |
394 | if (conn->tx_thread && conn->tx_thread_active) { | |
395 | send_sig(SIGINT, conn->tx_thread, 1); | |
396 | kthread_stop(conn->tx_thread); | |
397 | } | |
398 | spin_lock(&iscsit_global->ts_bitmap_lock); | |
399 | bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, | |
400 | get_order(1)); | |
401 | spin_unlock(&iscsit_global->ts_bitmap_lock); | |
402 | } | |
403 | return -1; | |
e48354ce NB |
404 | } |
405 | ||
676d2369 | 406 | static void iscsi_target_sk_data_ready(struct sock *sk) |
d381a801 NB |
407 | { |
408 | struct iscsi_conn *conn = sk->sk_user_data; | |
409 | bool rc; | |
410 | ||
411 | pr_debug("Entering iscsi_target_sk_data_ready: conn: %p\n", conn); | |
412 | ||
413 | write_lock_bh(&sk->sk_callback_lock); | |
414 | if (!sk->sk_user_data) { | |
415 | write_unlock_bh(&sk->sk_callback_lock); | |
416 | return; | |
417 | } | |
418 | if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) { | |
419 | write_unlock_bh(&sk->sk_callback_lock); | |
420 | pr_debug("Got LOGIN_FLAGS_READY=0, conn: %p >>>>\n", conn); | |
421 | return; | |
422 | } | |
423 | if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { | |
424 | write_unlock_bh(&sk->sk_callback_lock); | |
425 | pr_debug("Got LOGIN_FLAGS_CLOSED=1, conn: %p >>>>\n", conn); | |
426 | return; | |
427 | } | |
428 | if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { | |
429 | write_unlock_bh(&sk->sk_callback_lock); | |
430 | pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p >>>>\n", conn); | |
431 | return; | |
432 | } | |
433 | ||
434 | rc = schedule_delayed_work(&conn->login_work, 0); | |
0bcc297e | 435 | if (!rc) { |
d381a801 NB |
436 | pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work" |
437 | " got false\n"); | |
438 | } | |
439 | write_unlock_bh(&sk->sk_callback_lock); | |
440 | } | |
441 | ||
bb048357 NB |
442 | static void iscsi_target_sk_state_change(struct sock *); |
443 | ||
d381a801 NB |
444 | static void iscsi_target_set_sock_callbacks(struct iscsi_conn *conn) |
445 | { | |
446 | struct sock *sk; | |
447 | ||
448 | if (!conn->sock) | |
449 | return; | |
450 | ||
451 | sk = conn->sock->sk; | |
452 | pr_debug("Entering iscsi_target_set_sock_callbacks: conn: %p\n", conn); | |
453 | ||
454 | write_lock_bh(&sk->sk_callback_lock); | |
455 | sk->sk_user_data = conn; | |
456 | conn->orig_data_ready = sk->sk_data_ready; | |
bb048357 | 457 | conn->orig_state_change = sk->sk_state_change; |
d381a801 | 458 | sk->sk_data_ready = iscsi_target_sk_data_ready; |
bb048357 | 459 | sk->sk_state_change = iscsi_target_sk_state_change; |
d381a801 | 460 | write_unlock_bh(&sk->sk_callback_lock); |
bb048357 NB |
461 | |
462 | sk->sk_sndtimeo = TA_LOGIN_TIMEOUT * HZ; | |
463 | sk->sk_rcvtimeo = TA_LOGIN_TIMEOUT * HZ; | |
d381a801 NB |
464 | } |
465 | ||
466 | static void iscsi_target_restore_sock_callbacks(struct iscsi_conn *conn) | |
467 | { | |
468 | struct sock *sk; | |
469 | ||
470 | if (!conn->sock) | |
471 | return; | |
472 | ||
473 | sk = conn->sock->sk; | |
474 | pr_debug("Entering iscsi_target_restore_sock_callbacks: conn: %p\n", conn); | |
475 | ||
476 | write_lock_bh(&sk->sk_callback_lock); | |
477 | if (!sk->sk_user_data) { | |
478 | write_unlock_bh(&sk->sk_callback_lock); | |
479 | return; | |
480 | } | |
481 | sk->sk_user_data = NULL; | |
482 | sk->sk_data_ready = conn->orig_data_ready; | |
bb048357 | 483 | sk->sk_state_change = conn->orig_state_change; |
d381a801 | 484 | write_unlock_bh(&sk->sk_callback_lock); |
bb048357 NB |
485 | |
486 | sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; | |
487 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; | |
d381a801 NB |
488 | } |
489 | ||
490 | static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *); | |
491 | ||
492 | static bool iscsi_target_sk_state_check(struct sock *sk) | |
493 | { | |
494 | if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { | |
495 | pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE," | |
496 | "returning FALSE\n"); | |
497 | return false; | |
498 | } | |
499 | return true; | |
500 | } | |
501 | ||
502 | static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login) | |
503 | { | |
504 | struct iscsi_np *np = login->np; | |
505 | bool zero_tsih = login->zero_tsih; | |
506 | ||
507 | iscsi_remove_failed_auth_entry(conn); | |
508 | iscsi_target_nego_release(conn); | |
509 | iscsi_target_login_sess_out(conn, np, zero_tsih, true); | |
510 | } | |
511 | ||
512 | static void iscsi_target_login_timeout(unsigned long data) | |
513 | { | |
514 | struct iscsi_conn *conn = (struct iscsi_conn *)data; | |
515 | ||
516 | pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n"); | |
517 | ||
518 | if (conn->login_kworker) { | |
519 | pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n", | |
520 | conn->login_kworker->comm, conn->login_kworker->pid); | |
521 | send_sig(SIGINT, conn->login_kworker, 1); | |
522 | } | |
523 | } | |
524 | ||
525 | static void iscsi_target_do_login_rx(struct work_struct *work) | |
526 | { | |
527 | struct iscsi_conn *conn = container_of(work, | |
528 | struct iscsi_conn, login_work.work); | |
529 | struct iscsi_login *login = conn->login; | |
530 | struct iscsi_np *np = login->np; | |
531 | struct iscsi_portal_group *tpg = conn->tpg; | |
532 | struct iscsi_tpg_np *tpg_np = conn->tpg_np; | |
533 | struct timer_list login_timer; | |
534 | int rc, zero_tsih = login->zero_tsih; | |
535 | bool state; | |
536 | ||
537 | pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n", | |
538 | conn, current->comm, current->pid); | |
539 | ||
540 | spin_lock(&tpg->tpg_state_lock); | |
541 | state = (tpg->tpg_state == TPG_STATE_ACTIVE); | |
542 | spin_unlock(&tpg->tpg_state_lock); | |
543 | ||
0bcc297e | 544 | if (!state) { |
d381a801 NB |
545 | pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n"); |
546 | iscsi_target_restore_sock_callbacks(conn); | |
547 | iscsi_target_login_drop(conn, login); | |
548 | iscsit_deaccess_np(np, tpg, tpg_np); | |
549 | return; | |
550 | } | |
551 | ||
552 | if (conn->sock) { | |
553 | struct sock *sk = conn->sock->sk; | |
554 | ||
555 | read_lock_bh(&sk->sk_callback_lock); | |
556 | state = iscsi_target_sk_state_check(sk); | |
557 | read_unlock_bh(&sk->sk_callback_lock); | |
558 | ||
0bcc297e | 559 | if (!state) { |
d381a801 NB |
560 | pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); |
561 | iscsi_target_restore_sock_callbacks(conn); | |
562 | iscsi_target_login_drop(conn, login); | |
563 | iscsit_deaccess_np(np, tpg, tpg_np); | |
564 | return; | |
565 | } | |
566 | } | |
567 | ||
568 | conn->login_kworker = current; | |
569 | allow_signal(SIGINT); | |
570 | ||
571 | init_timer(&login_timer); | |
572 | login_timer.expires = (get_jiffies_64() + TA_LOGIN_TIMEOUT * HZ); | |
573 | login_timer.data = (unsigned long)conn; | |
574 | login_timer.function = iscsi_target_login_timeout; | |
575 | add_timer(&login_timer); | |
576 | pr_debug("Starting login_timer for %s/%d\n", current->comm, current->pid); | |
577 | ||
578 | rc = conn->conn_transport->iscsit_get_login_rx(conn, login); | |
579 | del_timer_sync(&login_timer); | |
580 | flush_signals(current); | |
581 | conn->login_kworker = NULL; | |
582 | ||
583 | if (rc < 0) { | |
584 | iscsi_target_restore_sock_callbacks(conn); | |
585 | iscsi_target_login_drop(conn, login); | |
586 | iscsit_deaccess_np(np, tpg, tpg_np); | |
587 | return; | |
588 | } | |
589 | ||
590 | pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n", | |
591 | conn, current->comm, current->pid); | |
592 | ||
593 | rc = iscsi_target_do_login(conn, login); | |
594 | if (rc < 0) { | |
595 | iscsi_target_restore_sock_callbacks(conn); | |
596 | iscsi_target_login_drop(conn, login); | |
597 | iscsit_deaccess_np(np, tpg, tpg_np); | |
598 | } else if (!rc) { | |
599 | if (conn->sock) { | |
600 | struct sock *sk = conn->sock->sk; | |
601 | ||
602 | write_lock_bh(&sk->sk_callback_lock); | |
603 | clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags); | |
604 | write_unlock_bh(&sk->sk_callback_lock); | |
605 | } | |
606 | } else if (rc == 1) { | |
607 | iscsi_target_nego_release(conn); | |
608 | iscsi_post_login_handler(np, conn, zero_tsih); | |
609 | iscsit_deaccess_np(np, tpg, tpg_np); | |
610 | } | |
611 | } | |
612 | ||
bb048357 NB |
613 | static void iscsi_target_do_cleanup(struct work_struct *work) |
614 | { | |
615 | struct iscsi_conn *conn = container_of(work, | |
616 | struct iscsi_conn, login_cleanup_work.work); | |
617 | struct sock *sk = conn->sock->sk; | |
618 | struct iscsi_login *login = conn->login; | |
619 | struct iscsi_np *np = login->np; | |
620 | struct iscsi_portal_group *tpg = conn->tpg; | |
621 | struct iscsi_tpg_np *tpg_np = conn->tpg_np; | |
622 | ||
623 | pr_debug("Entering iscsi_target_do_cleanup\n"); | |
624 | ||
625 | cancel_delayed_work_sync(&conn->login_work); | |
626 | conn->orig_state_change(sk); | |
627 | ||
628 | iscsi_target_restore_sock_callbacks(conn); | |
629 | iscsi_target_login_drop(conn, login); | |
630 | iscsit_deaccess_np(np, tpg, tpg_np); | |
631 | ||
632 | pr_debug("iscsi_target_do_cleanup done()\n"); | |
633 | } | |
634 | ||
635 | static void iscsi_target_sk_state_change(struct sock *sk) | |
636 | { | |
637 | struct iscsi_conn *conn; | |
638 | void (*orig_state_change)(struct sock *); | |
639 | bool state; | |
640 | ||
641 | pr_debug("Entering iscsi_target_sk_state_change\n"); | |
642 | ||
643 | write_lock_bh(&sk->sk_callback_lock); | |
644 | conn = sk->sk_user_data; | |
645 | if (!conn) { | |
646 | write_unlock_bh(&sk->sk_callback_lock); | |
647 | return; | |
648 | } | |
649 | orig_state_change = conn->orig_state_change; | |
650 | ||
651 | if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) { | |
652 | pr_debug("Got LOGIN_FLAGS_READY=0 sk_state_change conn: %p\n", | |
653 | conn); | |
654 | write_unlock_bh(&sk->sk_callback_lock); | |
655 | orig_state_change(sk); | |
656 | return; | |
657 | } | |
658 | if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { | |
659 | pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change" | |
660 | " conn: %p\n", conn); | |
661 | write_unlock_bh(&sk->sk_callback_lock); | |
662 | orig_state_change(sk); | |
663 | return; | |
664 | } | |
665 | if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { | |
666 | pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n", | |
667 | conn); | |
668 | write_unlock_bh(&sk->sk_callback_lock); | |
669 | orig_state_change(sk); | |
670 | return; | |
671 | } | |
672 | ||
673 | state = iscsi_target_sk_state_check(sk); | |
674 | write_unlock_bh(&sk->sk_callback_lock); | |
675 | ||
676 | pr_debug("iscsi_target_sk_state_change: state: %d\n", state); | |
677 | ||
678 | if (!state) { | |
679 | pr_debug("iscsi_target_sk_state_change got failed state\n"); | |
680 | schedule_delayed_work(&conn->login_cleanup_work, 0); | |
681 | return; | |
682 | } | |
683 | orig_state_change(sk); | |
684 | } | |
685 | ||
e48354ce NB |
686 | /* |
687 | * NOTE: We check for existing sessions or connections AFTER the initiator | |
688 | * has been successfully authenticated in order to protect against faked | |
689 | * ISID/TSIH combinations. | |
690 | */ | |
691 | static int iscsi_target_check_for_existing_instances( | |
692 | struct iscsi_conn *conn, | |
693 | struct iscsi_login *login) | |
694 | { | |
695 | if (login->checked_for_existing) | |
696 | return 0; | |
697 | ||
698 | login->checked_for_existing = 1; | |
699 | ||
700 | if (!login->tsih) | |
701 | return iscsi_check_for_session_reinstatement(conn); | |
702 | else | |
703 | return iscsi_login_post_auth_non_zero_tsih(conn, login->cid, | |
704 | login->initial_exp_statsn); | |
705 | } | |
706 | ||
707 | static int iscsi_target_do_authentication( | |
708 | struct iscsi_conn *conn, | |
709 | struct iscsi_login *login) | |
710 | { | |
711 | int authret; | |
712 | u32 payload_length; | |
713 | struct iscsi_param *param; | |
714 | struct iscsi_login_req *login_req; | |
715 | struct iscsi_login_rsp *login_rsp; | |
716 | ||
717 | login_req = (struct iscsi_login_req *) login->req; | |
718 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
719 | payload_length = ntoh24(login_req->dlength); | |
720 | ||
721 | param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); | |
722 | if (!param) | |
723 | return -1; | |
724 | ||
725 | authret = iscsi_handle_authentication( | |
726 | conn, | |
727 | login->req_buf, | |
728 | login->rsp_buf, | |
729 | payload_length, | |
730 | &login->rsp_length, | |
731 | param->value); | |
732 | switch (authret) { | |
733 | case 0: | |
734 | pr_debug("Received OK response" | |
735 | " from LIO Authentication, continuing.\n"); | |
736 | break; | |
737 | case 1: | |
738 | pr_debug("iSCSI security negotiation" | |
bfb9035c | 739 | " completed successfully.\n"); |
e48354ce NB |
740 | login->auth_complete = 1; |
741 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) && | |
742 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { | |
743 | login_rsp->flags |= (ISCSI_FLAG_LOGIN_NEXT_STAGE1 | | |
744 | ISCSI_FLAG_LOGIN_TRANSIT); | |
745 | login->current_stage = 1; | |
746 | } | |
747 | return iscsi_target_check_for_existing_instances( | |
748 | conn, login); | |
749 | case 2: | |
750 | pr_err("Security negotiation" | |
751 | " failed.\n"); | |
752 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
753 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
754 | return -1; | |
755 | default: | |
756 | pr_err("Received unknown error %d from LIO" | |
757 | " Authentication\n", authret); | |
758 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
759 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | |
760 | return -1; | |
761 | } | |
762 | ||
763 | return 0; | |
764 | } | |
765 | ||
766 | static int iscsi_target_handle_csg_zero( | |
767 | struct iscsi_conn *conn, | |
768 | struct iscsi_login *login) | |
769 | { | |
770 | int ret; | |
771 | u32 payload_length; | |
772 | struct iscsi_param *param; | |
773 | struct iscsi_login_req *login_req; | |
774 | struct iscsi_login_rsp *login_rsp; | |
775 | ||
776 | login_req = (struct iscsi_login_req *) login->req; | |
777 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
778 | payload_length = ntoh24(login_req->dlength); | |
779 | ||
780 | param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); | |
781 | if (!param) | |
782 | return -1; | |
783 | ||
784 | ret = iscsi_decode_text_input( | |
785 | PHASE_SECURITY|PHASE_DECLARATIVE, | |
786 | SENDER_INITIATOR|SENDER_RECEIVER, | |
787 | login->req_buf, | |
788 | payload_length, | |
9977bb18 | 789 | conn); |
e48354ce NB |
790 | if (ret < 0) |
791 | return -1; | |
792 | ||
793 | if (ret > 0) { | |
794 | if (login->auth_complete) { | |
795 | pr_err("Initiator has already been" | |
796 | " successfully authenticated, but is still" | |
797 | " sending %s keys.\n", param->value); | |
798 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
799 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
800 | return -1; | |
801 | } | |
802 | ||
803 | goto do_auth; | |
91f0abfd NB |
804 | } else if (!payload_length) { |
805 | pr_err("Initiator sent zero length security payload," | |
806 | " login failed\n"); | |
807 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
808 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
809 | return -1; | |
e48354ce NB |
810 | } |
811 | ||
812 | if (login->first_request) | |
813 | if (iscsi_target_check_first_request(conn, login) < 0) | |
814 | return -1; | |
815 | ||
816 | ret = iscsi_encode_text_output( | |
817 | PHASE_SECURITY|PHASE_DECLARATIVE, | |
818 | SENDER_TARGET, | |
819 | login->rsp_buf, | |
820 | &login->rsp_length, | |
c50e87ec NB |
821 | conn->param_list, |
822 | conn->tpg->tpg_attrib.login_keys_workaround); | |
e48354ce NB |
823 | if (ret < 0) |
824 | return -1; | |
825 | ||
826 | if (!iscsi_check_negotiated_keys(conn->param_list)) { | |
60bfcf8e | 827 | if (conn->tpg->tpg_attrib.authentication && |
e48354ce NB |
828 | !strncmp(param->value, NONE, 4)) { |
829 | pr_err("Initiator sent AuthMethod=None but" | |
830 | " Target is enforcing iSCSI Authentication," | |
831 | " login failed.\n"); | |
832 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
833 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
834 | return -1; | |
835 | } | |
836 | ||
60bfcf8e | 837 | if (conn->tpg->tpg_attrib.authentication && |
e48354ce NB |
838 | !login->auth_complete) |
839 | return 0; | |
840 | ||
841 | if (strncmp(param->value, NONE, 4) && !login->auth_complete) | |
842 | return 0; | |
843 | ||
844 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) && | |
845 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { | |
846 | login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE1 | | |
847 | ISCSI_FLAG_LOGIN_TRANSIT; | |
848 | login->current_stage = 1; | |
849 | } | |
850 | } | |
851 | ||
852 | return 0; | |
853 | do_auth: | |
854 | return iscsi_target_do_authentication(conn, login); | |
855 | } | |
856 | ||
857 | static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_login *login) | |
858 | { | |
859 | int ret; | |
860 | u32 payload_length; | |
861 | struct iscsi_login_req *login_req; | |
862 | struct iscsi_login_rsp *login_rsp; | |
863 | ||
864 | login_req = (struct iscsi_login_req *) login->req; | |
865 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
866 | payload_length = ntoh24(login_req->dlength); | |
867 | ||
868 | ret = iscsi_decode_text_input( | |
869 | PHASE_OPERATIONAL|PHASE_DECLARATIVE, | |
870 | SENDER_INITIATOR|SENDER_RECEIVER, | |
871 | login->req_buf, | |
872 | payload_length, | |
9977bb18 | 873 | conn); |
1c5c12c6 RD |
874 | if (ret < 0) { |
875 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
876 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
e48354ce | 877 | return -1; |
1c5c12c6 | 878 | } |
e48354ce NB |
879 | |
880 | if (login->first_request) | |
881 | if (iscsi_target_check_first_request(conn, login) < 0) | |
882 | return -1; | |
883 | ||
884 | if (iscsi_target_check_for_existing_instances(conn, login) < 0) | |
885 | return -1; | |
886 | ||
887 | ret = iscsi_encode_text_output( | |
888 | PHASE_OPERATIONAL|PHASE_DECLARATIVE, | |
889 | SENDER_TARGET, | |
890 | login->rsp_buf, | |
891 | &login->rsp_length, | |
c50e87ec NB |
892 | conn->param_list, |
893 | conn->tpg->tpg_attrib.login_keys_workaround); | |
1c5c12c6 RD |
894 | if (ret < 0) { |
895 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
896 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
e48354ce | 897 | return -1; |
1c5c12c6 | 898 | } |
e48354ce NB |
899 | |
900 | if (!login->auth_complete && | |
60bfcf8e | 901 | conn->tpg->tpg_attrib.authentication) { |
e48354ce NB |
902 | pr_err("Initiator is requesting CSG: 1, has not been" |
903 | " successfully authenticated, and the Target is" | |
904 | " enforcing iSCSI Authentication, login failed.\n"); | |
905 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
906 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
907 | return -1; | |
908 | } | |
909 | ||
910 | if (!iscsi_check_negotiated_keys(conn->param_list)) | |
911 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE3) && | |
912 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) | |
913 | login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE3 | | |
914 | ISCSI_FLAG_LOGIN_TRANSIT; | |
915 | ||
916 | return 0; | |
917 | } | |
918 | ||
919 | static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *login) | |
920 | { | |
921 | int pdu_count = 0; | |
922 | struct iscsi_login_req *login_req; | |
923 | struct iscsi_login_rsp *login_rsp; | |
924 | ||
925 | login_req = (struct iscsi_login_req *) login->req; | |
926 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
927 | ||
928 | while (1) { | |
929 | if (++pdu_count > MAX_LOGIN_PDUS) { | |
930 | pr_err("MAX_LOGIN_PDUS count reached.\n"); | |
931 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
932 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | |
933 | return -1; | |
934 | } | |
935 | ||
5d358065 | 936 | switch (ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)) { |
e48354ce | 937 | case 0: |
5d358065 | 938 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK; |
e48354ce NB |
939 | if (iscsi_target_handle_csg_zero(conn, login) < 0) |
940 | return -1; | |
941 | break; | |
942 | case 1: | |
943 | login_rsp->flags |= ISCSI_FLAG_LOGIN_CURRENT_STAGE1; | |
944 | if (iscsi_target_handle_csg_one(conn, login) < 0) | |
945 | return -1; | |
946 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { | |
947 | login->tsih = conn->sess->tsih; | |
baa4d64b | 948 | login->login_complete = 1; |
d381a801 | 949 | iscsi_target_restore_sock_callbacks(conn); |
e48354ce NB |
950 | if (iscsi_target_do_tx_login_io(conn, |
951 | login) < 0) | |
952 | return -1; | |
d381a801 | 953 | return 1; |
e48354ce NB |
954 | } |
955 | break; | |
956 | default: | |
957 | pr_err("Illegal CSG: %d received from" | |
958 | " Initiator, protocol error.\n", | |
5d358065 | 959 | ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)); |
e48354ce NB |
960 | break; |
961 | } | |
962 | ||
ea3a179a | 963 | if (iscsi_target_do_tx_login_io(conn, login) < 0) |
e48354ce NB |
964 | return -1; |
965 | ||
966 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { | |
967 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT; | |
968 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; | |
969 | } | |
d381a801 | 970 | break; |
e48354ce NB |
971 | } |
972 | ||
bb048357 NB |
973 | if (conn->sock) { |
974 | struct sock *sk = conn->sock->sk; | |
975 | bool state; | |
976 | ||
977 | read_lock_bh(&sk->sk_callback_lock); | |
978 | state = iscsi_target_sk_state_check(sk); | |
979 | read_unlock_bh(&sk->sk_callback_lock); | |
980 | ||
981 | if (!state) { | |
982 | pr_debug("iscsi_target_do_login() failed state for" | |
983 | " conn: %p\n", conn); | |
984 | return -1; | |
985 | } | |
986 | } | |
987 | ||
e48354ce NB |
988 | return 0; |
989 | } | |
990 | ||
991 | static void iscsi_initiatorname_tolower( | |
992 | char *param_buf) | |
993 | { | |
994 | char *c; | |
995 | u32 iqn_size = strlen(param_buf), i; | |
996 | ||
997 | for (i = 0; i < iqn_size; i++) { | |
8359cf43 | 998 | c = ¶m_buf[i]; |
e48354ce NB |
999 | if (!isupper(*c)) |
1000 | continue; | |
1001 | ||
1002 | *c = tolower(*c); | |
1003 | } | |
1004 | } | |
1005 | ||
1006 | /* | |
1007 | * Processes the first Login Request.. | |
1008 | */ | |
baa4d64b | 1009 | int iscsi_target_locate_portal( |
e48354ce NB |
1010 | struct iscsi_np *np, |
1011 | struct iscsi_conn *conn, | |
1012 | struct iscsi_login *login) | |
1013 | { | |
1014 | char *i_buf = NULL, *s_buf = NULL, *t_buf = NULL; | |
1015 | char *tmpbuf, *start = NULL, *end = NULL, *key, *value; | |
1016 | struct iscsi_session *sess = conn->sess; | |
1017 | struct iscsi_tiqn *tiqn; | |
d381a801 | 1018 | struct iscsi_tpg_np *tpg_np = NULL; |
e48354ce | 1019 | struct iscsi_login_req *login_req; |
988e3a85 NB |
1020 | struct se_node_acl *se_nacl; |
1021 | u32 payload_length, queue_depth = 0; | |
1022 | int sessiontype = 0, ret = 0, tag_num, tag_size; | |
e48354ce | 1023 | |
d381a801 | 1024 | INIT_DELAYED_WORK(&conn->login_work, iscsi_target_do_login_rx); |
bb048357 | 1025 | INIT_DELAYED_WORK(&conn->login_cleanup_work, iscsi_target_do_cleanup); |
d381a801 NB |
1026 | iscsi_target_set_sock_callbacks(conn); |
1027 | ||
1028 | login->np = np; | |
1029 | ||
e48354ce | 1030 | login_req = (struct iscsi_login_req *) login->req; |
e48354ce NB |
1031 | payload_length = ntoh24(login_req->dlength); |
1032 | ||
e48354ce NB |
1033 | tmpbuf = kzalloc(payload_length + 1, GFP_KERNEL); |
1034 | if (!tmpbuf) { | |
1035 | pr_err("Unable to allocate memory for tmpbuf.\n"); | |
1036 | return -1; | |
1037 | } | |
1038 | ||
1039 | memcpy(tmpbuf, login->req_buf, payload_length); | |
1040 | tmpbuf[payload_length] = '\0'; | |
1041 | start = tmpbuf; | |
1042 | end = (start + payload_length); | |
1043 | ||
1044 | /* | |
1045 | * Locate the initial keys expected from the Initiator node in | |
1046 | * the first login request in order to progress with the login phase. | |
1047 | */ | |
1048 | while (start < end) { | |
1049 | if (iscsi_extract_key_value(start, &key, &value) < 0) { | |
1050 | ret = -1; | |
1051 | goto out; | |
1052 | } | |
1053 | ||
1054 | if (!strncmp(key, "InitiatorName", 13)) | |
1055 | i_buf = value; | |
1056 | else if (!strncmp(key, "SessionType", 11)) | |
1057 | s_buf = value; | |
1058 | else if (!strncmp(key, "TargetName", 10)) | |
1059 | t_buf = value; | |
1060 | ||
1061 | start += strlen(key) + strlen(value) + 2; | |
1062 | } | |
e48354ce NB |
1063 | /* |
1064 | * See 5.3. Login Phase. | |
1065 | */ | |
1066 | if (!i_buf) { | |
1067 | pr_err("InitiatorName key not received" | |
1068 | " in first login request.\n"); | |
1069 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1070 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
1071 | ret = -1; | |
1072 | goto out; | |
1073 | } | |
1074 | /* | |
1075 | * Convert the incoming InitiatorName to lowercase following | |
1076 | * RFC-3720 3.2.6.1. section c) that says that iSCSI IQNs | |
1077 | * are NOT case sensitive. | |
1078 | */ | |
1079 | iscsi_initiatorname_tolower(i_buf); | |
1080 | ||
1081 | if (!s_buf) { | |
1082 | if (!login->leading_connection) | |
1083 | goto get_target; | |
1084 | ||
1085 | pr_err("SessionType key not received" | |
1086 | " in first login request.\n"); | |
1087 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1088 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
1089 | ret = -1; | |
1090 | goto out; | |
1091 | } | |
1092 | ||
1093 | /* | |
1094 | * Use default portal group for discovery sessions. | |
1095 | */ | |
1096 | sessiontype = strncmp(s_buf, DISCOVERY, 9); | |
1097 | if (!sessiontype) { | |
1098 | conn->tpg = iscsit_global->discovery_tpg; | |
1099 | if (!login->leading_connection) | |
1100 | goto get_target; | |
1101 | ||
1102 | sess->sess_ops->SessionType = 1; | |
1103 | /* | |
1104 | * Setup crc32c modules from libcrypto | |
1105 | */ | |
1106 | if (iscsi_login_setup_crypto(conn) < 0) { | |
1107 | pr_err("iscsi_login_setup_crypto() failed\n"); | |
1108 | ret = -1; | |
1109 | goto out; | |
1110 | } | |
1111 | /* | |
1112 | * Serialize access across the discovery struct iscsi_portal_group to | |
1113 | * process login attempt. | |
1114 | */ | |
1115 | if (iscsit_access_np(np, conn->tpg) < 0) { | |
1116 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1117 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
1118 | ret = -1; | |
1119 | goto out; | |
1120 | } | |
1121 | ret = 0; | |
988e3a85 | 1122 | goto alloc_tags; |
e48354ce NB |
1123 | } |
1124 | ||
1125 | get_target: | |
1126 | if (!t_buf) { | |
1127 | pr_err("TargetName key not received" | |
1128 | " in first login request while" | |
1129 | " SessionType=Normal.\n"); | |
1130 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1131 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
1132 | ret = -1; | |
1133 | goto out; | |
1134 | } | |
1135 | ||
1136 | /* | |
1137 | * Locate Target IQN from Storage Node. | |
1138 | */ | |
1139 | tiqn = iscsit_get_tiqn_for_login(t_buf); | |
1140 | if (!tiqn) { | |
1141 | pr_err("Unable to locate Target IQN: %s in" | |
1142 | " Storage Node\n", t_buf); | |
1143 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1144 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
1145 | ret = -1; | |
1146 | goto out; | |
1147 | } | |
1148 | pr_debug("Located Storage Object: %s\n", tiqn->tiqn); | |
1149 | ||
1150 | /* | |
1151 | * Locate Target Portal Group from Storage Node. | |
1152 | */ | |
d381a801 | 1153 | conn->tpg = iscsit_get_tpg_from_np(tiqn, np, &tpg_np); |
e48354ce NB |
1154 | if (!conn->tpg) { |
1155 | pr_err("Unable to locate Target Portal Group" | |
1156 | " on %s\n", tiqn->tiqn); | |
1157 | iscsit_put_tiqn_for_login(tiqn); | |
1158 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1159 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
1160 | ret = -1; | |
1161 | goto out; | |
1162 | } | |
d381a801 | 1163 | conn->tpg_np = tpg_np; |
e48354ce NB |
1164 | pr_debug("Located Portal Group Object: %hu\n", conn->tpg->tpgt); |
1165 | /* | |
1166 | * Setup crc32c modules from libcrypto | |
1167 | */ | |
1168 | if (iscsi_login_setup_crypto(conn) < 0) { | |
1169 | pr_err("iscsi_login_setup_crypto() failed\n"); | |
d381a801 NB |
1170 | kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); |
1171 | iscsit_put_tiqn_for_login(tiqn); | |
1172 | conn->tpg = NULL; | |
e48354ce NB |
1173 | ret = -1; |
1174 | goto out; | |
1175 | } | |
1176 | /* | |
1177 | * Serialize access across the struct iscsi_portal_group to | |
1178 | * process login attempt. | |
1179 | */ | |
1180 | if (iscsit_access_np(np, conn->tpg) < 0) { | |
d381a801 | 1181 | kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); |
e48354ce NB |
1182 | iscsit_put_tiqn_for_login(tiqn); |
1183 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1184 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
e48354ce | 1185 | conn->tpg = NULL; |
d381a801 | 1186 | ret = -1; |
e48354ce NB |
1187 | goto out; |
1188 | } | |
1189 | ||
1190 | /* | |
1191 | * conn->sess->node_acl will be set when the referenced | |
1192 | * struct iscsi_session is located from received ISID+TSIH in | |
1193 | * iscsi_login_non_zero_tsih_s2(). | |
1194 | */ | |
1195 | if (!login->leading_connection) { | |
1196 | ret = 0; | |
1197 | goto out; | |
1198 | } | |
1199 | ||
1200 | /* | |
1201 | * This value is required in iscsi_login_zero_tsih_s2() | |
1202 | */ | |
1203 | sess->sess_ops->SessionType = 0; | |
1204 | ||
1205 | /* | |
1206 | * Locate incoming Initiator IQN reference from Storage Node. | |
1207 | */ | |
1208 | sess->se_sess->se_node_acl = core_tpg_check_initiator_node_acl( | |
1209 | &conn->tpg->tpg_se_tpg, i_buf); | |
1210 | if (!sess->se_sess->se_node_acl) { | |
1211 | pr_err("iSCSI Initiator Node: %s is not authorized to" | |
1212 | " access iSCSI target portal group: %hu.\n", | |
1213 | i_buf, conn->tpg->tpgt); | |
1214 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1215 | ISCSI_LOGIN_STATUS_TGT_FORBIDDEN); | |
1216 | ret = -1; | |
1217 | goto out; | |
1218 | } | |
988e3a85 NB |
1219 | se_nacl = sess->se_sess->se_node_acl; |
1220 | queue_depth = se_nacl->queue_depth; | |
1221 | /* | |
1222 | * Setup pre-allocated tags based upon allowed per NodeACL CmdSN | |
1223 | * depth for non immediate commands, plus extra tags for immediate | |
1224 | * commands. | |
1225 | * | |
1226 | * Also enforce a ISCSIT_MIN_TAGS to prevent unnecessary contention | |
1227 | * in per-cpu-ida tag allocation logic + small queue_depth. | |
1228 | */ | |
1229 | alloc_tags: | |
1230 | tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth); | |
4a4caa29 | 1231 | tag_num = (tag_num * 2) + ISCSIT_EXTRA_TAGS; |
988e3a85 | 1232 | tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; |
e48354ce | 1233 | |
988e3a85 NB |
1234 | ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size); |
1235 | if (ret < 0) { | |
1236 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1237 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | |
1238 | ret = -1; | |
1239 | } | |
e48354ce NB |
1240 | out: |
1241 | kfree(tmpbuf); | |
1242 | return ret; | |
1243 | } | |
1244 | ||
e48354ce NB |
1245 | int iscsi_target_start_negotiation( |
1246 | struct iscsi_login *login, | |
1247 | struct iscsi_conn *conn) | |
1248 | { | |
baa4d64b | 1249 | int ret; |
e48354ce | 1250 | |
cf4ab9d5 NB |
1251 | if (conn->sock) { |
1252 | struct sock *sk = conn->sock->sk; | |
d381a801 | 1253 | |
cf4ab9d5 NB |
1254 | write_lock_bh(&sk->sk_callback_lock); |
1255 | set_bit(LOGIN_FLAGS_READY, &conn->login_flags); | |
1256 | write_unlock_bh(&sk->sk_callback_lock); | |
1257 | } | |
1258 | ||
1259 | ret = iscsi_target_do_login(conn, login); | |
1260 | if (ret < 0) { | |
d381a801 | 1261 | cancel_delayed_work_sync(&conn->login_work); |
bb048357 | 1262 | cancel_delayed_work_sync(&conn->login_cleanup_work); |
d381a801 | 1263 | iscsi_target_restore_sock_callbacks(conn); |
e48354ce | 1264 | iscsi_remove_failed_auth_entry(conn); |
d381a801 NB |
1265 | } |
1266 | if (ret != 0) | |
1267 | iscsi_target_nego_release(conn); | |
e48354ce | 1268 | |
e48354ce NB |
1269 | return ret; |
1270 | } | |
1271 | ||
baa4d64b | 1272 | void iscsi_target_nego_release(struct iscsi_conn *conn) |
e48354ce | 1273 | { |
baa4d64b NB |
1274 | struct iscsi_login *login = conn->conn_login; |
1275 | ||
1276 | if (!login) | |
1277 | return; | |
1278 | ||
e48354ce NB |
1279 | kfree(login->req_buf); |
1280 | kfree(login->rsp_buf); | |
1281 | kfree(login); | |
baa4d64b NB |
1282 | |
1283 | conn->conn_login = NULL; | |
e48354ce | 1284 | } |