]>
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; | |
344 | struct iscsi_session *sess = conn->sess; | |
345 | struct iscsi_login_rsp *login_rsp; | |
346 | ||
347 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
348 | ||
349 | login_rsp->opcode = ISCSI_OP_LOGIN_RSP; | |
350 | hton24(login_rsp->dlength, login->rsp_length); | |
351 | memcpy(login_rsp->isid, login->isid, 6); | |
352 | login_rsp->tsih = cpu_to_be16(login->tsih); | |
66c7db68 | 353 | login_rsp->itt = login->init_task_tag; |
e48354ce NB |
354 | login_rsp->statsn = cpu_to_be32(conn->stat_sn++); |
355 | login_rsp->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); | |
356 | login_rsp->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); | |
357 | ||
358 | pr_debug("Sending Login Response, Flags: 0x%02x, ITT: 0x%08x," | |
359 | " ExpCmdSN; 0x%08x, MaxCmdSN: 0x%08x, StatSN: 0x%08x, Length:" | |
66c7db68 | 360 | " %u\n", login_rsp->flags, (__force u32)login_rsp->itt, |
e48354ce NB |
361 | ntohl(login_rsp->exp_cmdsn), ntohl(login_rsp->max_cmdsn), |
362 | ntohl(login_rsp->statsn), login->rsp_length); | |
363 | ||
364 | padding = ((-login->rsp_length) & 3); | |
e5419865 NB |
365 | /* |
366 | * Before sending the last login response containing the transition | |
367 | * bit for full-feature-phase, go ahead and start up TX/RX threads | |
368 | * now to avoid potential resource allocation failures after the | |
369 | * final login response has been sent. | |
370 | */ | |
371 | if (login->login_complete) { | |
372 | int rc = iscsit_start_kthreads(conn); | |
373 | if (rc) { | |
374 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
375 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | |
376 | return -1; | |
377 | } | |
378 | } | |
e48354ce | 379 | |
baa4d64b NB |
380 | if (conn->conn_transport->iscsit_put_login_tx(conn, login, |
381 | login->rsp_length + padding) < 0) | |
e5419865 | 382 | goto err; |
e48354ce NB |
383 | |
384 | login->rsp_length = 0; | |
e48354ce | 385 | mutex_lock(&sess->cmdsn_mutex); |
50e5c87d CH |
386 | login_rsp->exp_cmdsn = cpu_to_be32(sess->exp_cmd_sn); |
387 | login_rsp->max_cmdsn = cpu_to_be32(sess->max_cmd_sn); | |
e48354ce NB |
388 | mutex_unlock(&sess->cmdsn_mutex); |
389 | ||
390 | return 0; | |
e5419865 NB |
391 | |
392 | err: | |
393 | if (login->login_complete) { | |
394 | if (conn->rx_thread && conn->rx_thread_active) { | |
395 | send_sig(SIGINT, conn->rx_thread, 1); | |
396 | kthread_stop(conn->rx_thread); | |
397 | } | |
398 | if (conn->tx_thread && conn->tx_thread_active) { | |
399 | send_sig(SIGINT, conn->tx_thread, 1); | |
400 | kthread_stop(conn->tx_thread); | |
401 | } | |
402 | spin_lock(&iscsit_global->ts_bitmap_lock); | |
403 | bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, | |
404 | get_order(1)); | |
405 | spin_unlock(&iscsit_global->ts_bitmap_lock); | |
406 | } | |
407 | return -1; | |
e48354ce NB |
408 | } |
409 | ||
676d2369 | 410 | static void iscsi_target_sk_data_ready(struct sock *sk) |
d381a801 NB |
411 | { |
412 | struct iscsi_conn *conn = sk->sk_user_data; | |
413 | bool rc; | |
414 | ||
415 | pr_debug("Entering iscsi_target_sk_data_ready: conn: %p\n", conn); | |
416 | ||
417 | write_lock_bh(&sk->sk_callback_lock); | |
418 | if (!sk->sk_user_data) { | |
419 | write_unlock_bh(&sk->sk_callback_lock); | |
420 | return; | |
421 | } | |
422 | if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) { | |
423 | write_unlock_bh(&sk->sk_callback_lock); | |
424 | pr_debug("Got LOGIN_FLAGS_READY=0, conn: %p >>>>\n", conn); | |
425 | return; | |
426 | } | |
427 | if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { | |
428 | write_unlock_bh(&sk->sk_callback_lock); | |
429 | pr_debug("Got LOGIN_FLAGS_CLOSED=1, conn: %p >>>>\n", conn); | |
430 | return; | |
431 | } | |
432 | if (test_and_set_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { | |
433 | write_unlock_bh(&sk->sk_callback_lock); | |
434 | pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1, conn: %p >>>>\n", conn); | |
435 | return; | |
436 | } | |
437 | ||
438 | rc = schedule_delayed_work(&conn->login_work, 0); | |
0bcc297e | 439 | if (!rc) { |
d381a801 NB |
440 | pr_debug("iscsi_target_sk_data_ready, schedule_delayed_work" |
441 | " got false\n"); | |
442 | } | |
443 | write_unlock_bh(&sk->sk_callback_lock); | |
444 | } | |
445 | ||
bb048357 NB |
446 | static void iscsi_target_sk_state_change(struct sock *); |
447 | ||
d381a801 NB |
448 | static void iscsi_target_set_sock_callbacks(struct iscsi_conn *conn) |
449 | { | |
450 | struct sock *sk; | |
451 | ||
452 | if (!conn->sock) | |
453 | return; | |
454 | ||
455 | sk = conn->sock->sk; | |
456 | pr_debug("Entering iscsi_target_set_sock_callbacks: conn: %p\n", conn); | |
457 | ||
458 | write_lock_bh(&sk->sk_callback_lock); | |
459 | sk->sk_user_data = conn; | |
460 | conn->orig_data_ready = sk->sk_data_ready; | |
bb048357 | 461 | conn->orig_state_change = sk->sk_state_change; |
d381a801 | 462 | sk->sk_data_ready = iscsi_target_sk_data_ready; |
bb048357 | 463 | sk->sk_state_change = iscsi_target_sk_state_change; |
d381a801 | 464 | write_unlock_bh(&sk->sk_callback_lock); |
bb048357 NB |
465 | |
466 | sk->sk_sndtimeo = TA_LOGIN_TIMEOUT * HZ; | |
467 | sk->sk_rcvtimeo = TA_LOGIN_TIMEOUT * HZ; | |
d381a801 NB |
468 | } |
469 | ||
470 | static void iscsi_target_restore_sock_callbacks(struct iscsi_conn *conn) | |
471 | { | |
472 | struct sock *sk; | |
473 | ||
474 | if (!conn->sock) | |
475 | return; | |
476 | ||
477 | sk = conn->sock->sk; | |
478 | pr_debug("Entering iscsi_target_restore_sock_callbacks: conn: %p\n", conn); | |
479 | ||
480 | write_lock_bh(&sk->sk_callback_lock); | |
481 | if (!sk->sk_user_data) { | |
482 | write_unlock_bh(&sk->sk_callback_lock); | |
483 | return; | |
484 | } | |
485 | sk->sk_user_data = NULL; | |
486 | sk->sk_data_ready = conn->orig_data_ready; | |
bb048357 | 487 | sk->sk_state_change = conn->orig_state_change; |
d381a801 | 488 | write_unlock_bh(&sk->sk_callback_lock); |
bb048357 NB |
489 | |
490 | sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; | |
491 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; | |
d381a801 NB |
492 | } |
493 | ||
494 | static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *); | |
495 | ||
496 | static bool iscsi_target_sk_state_check(struct sock *sk) | |
497 | { | |
498 | if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) { | |
499 | pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE," | |
500 | "returning FALSE\n"); | |
501 | return false; | |
502 | } | |
503 | return true; | |
504 | } | |
505 | ||
506 | static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login) | |
507 | { | |
508 | struct iscsi_np *np = login->np; | |
509 | bool zero_tsih = login->zero_tsih; | |
510 | ||
511 | iscsi_remove_failed_auth_entry(conn); | |
512 | iscsi_target_nego_release(conn); | |
513 | iscsi_target_login_sess_out(conn, np, zero_tsih, true); | |
514 | } | |
515 | ||
516 | static void iscsi_target_login_timeout(unsigned long data) | |
517 | { | |
518 | struct iscsi_conn *conn = (struct iscsi_conn *)data; | |
519 | ||
520 | pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n"); | |
521 | ||
522 | if (conn->login_kworker) { | |
523 | pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n", | |
524 | conn->login_kworker->comm, conn->login_kworker->pid); | |
525 | send_sig(SIGINT, conn->login_kworker, 1); | |
526 | } | |
527 | } | |
528 | ||
529 | static void iscsi_target_do_login_rx(struct work_struct *work) | |
530 | { | |
531 | struct iscsi_conn *conn = container_of(work, | |
532 | struct iscsi_conn, login_work.work); | |
533 | struct iscsi_login *login = conn->login; | |
534 | struct iscsi_np *np = login->np; | |
535 | struct iscsi_portal_group *tpg = conn->tpg; | |
536 | struct iscsi_tpg_np *tpg_np = conn->tpg_np; | |
537 | struct timer_list login_timer; | |
538 | int rc, zero_tsih = login->zero_tsih; | |
539 | bool state; | |
540 | ||
541 | pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n", | |
542 | conn, current->comm, current->pid); | |
543 | ||
544 | spin_lock(&tpg->tpg_state_lock); | |
545 | state = (tpg->tpg_state == TPG_STATE_ACTIVE); | |
546 | spin_unlock(&tpg->tpg_state_lock); | |
547 | ||
0bcc297e | 548 | if (!state) { |
d381a801 NB |
549 | pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n"); |
550 | iscsi_target_restore_sock_callbacks(conn); | |
551 | iscsi_target_login_drop(conn, login); | |
552 | iscsit_deaccess_np(np, tpg, tpg_np); | |
553 | return; | |
554 | } | |
555 | ||
556 | if (conn->sock) { | |
557 | struct sock *sk = conn->sock->sk; | |
558 | ||
559 | read_lock_bh(&sk->sk_callback_lock); | |
560 | state = iscsi_target_sk_state_check(sk); | |
561 | read_unlock_bh(&sk->sk_callback_lock); | |
562 | ||
0bcc297e | 563 | if (!state) { |
d381a801 NB |
564 | pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n"); |
565 | iscsi_target_restore_sock_callbacks(conn); | |
566 | iscsi_target_login_drop(conn, login); | |
567 | iscsit_deaccess_np(np, tpg, tpg_np); | |
568 | return; | |
569 | } | |
570 | } | |
571 | ||
572 | conn->login_kworker = current; | |
573 | allow_signal(SIGINT); | |
574 | ||
575 | init_timer(&login_timer); | |
576 | login_timer.expires = (get_jiffies_64() + TA_LOGIN_TIMEOUT * HZ); | |
577 | login_timer.data = (unsigned long)conn; | |
578 | login_timer.function = iscsi_target_login_timeout; | |
579 | add_timer(&login_timer); | |
580 | pr_debug("Starting login_timer for %s/%d\n", current->comm, current->pid); | |
581 | ||
582 | rc = conn->conn_transport->iscsit_get_login_rx(conn, login); | |
583 | del_timer_sync(&login_timer); | |
584 | flush_signals(current); | |
585 | conn->login_kworker = NULL; | |
586 | ||
587 | if (rc < 0) { | |
588 | iscsi_target_restore_sock_callbacks(conn); | |
589 | iscsi_target_login_drop(conn, login); | |
590 | iscsit_deaccess_np(np, tpg, tpg_np); | |
591 | return; | |
592 | } | |
593 | ||
594 | pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n", | |
595 | conn, current->comm, current->pid); | |
596 | ||
597 | rc = iscsi_target_do_login(conn, login); | |
598 | if (rc < 0) { | |
599 | iscsi_target_restore_sock_callbacks(conn); | |
600 | iscsi_target_login_drop(conn, login); | |
601 | iscsit_deaccess_np(np, tpg, tpg_np); | |
602 | } else if (!rc) { | |
603 | if (conn->sock) { | |
604 | struct sock *sk = conn->sock->sk; | |
605 | ||
606 | write_lock_bh(&sk->sk_callback_lock); | |
607 | clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags); | |
608 | write_unlock_bh(&sk->sk_callback_lock); | |
609 | } | |
610 | } else if (rc == 1) { | |
611 | iscsi_target_nego_release(conn); | |
612 | iscsi_post_login_handler(np, conn, zero_tsih); | |
613 | iscsit_deaccess_np(np, tpg, tpg_np); | |
614 | } | |
615 | } | |
616 | ||
bb048357 NB |
617 | static void iscsi_target_do_cleanup(struct work_struct *work) |
618 | { | |
619 | struct iscsi_conn *conn = container_of(work, | |
620 | struct iscsi_conn, login_cleanup_work.work); | |
621 | struct sock *sk = conn->sock->sk; | |
622 | struct iscsi_login *login = conn->login; | |
623 | struct iscsi_np *np = login->np; | |
624 | struct iscsi_portal_group *tpg = conn->tpg; | |
625 | struct iscsi_tpg_np *tpg_np = conn->tpg_np; | |
626 | ||
627 | pr_debug("Entering iscsi_target_do_cleanup\n"); | |
628 | ||
629 | cancel_delayed_work_sync(&conn->login_work); | |
630 | conn->orig_state_change(sk); | |
631 | ||
632 | iscsi_target_restore_sock_callbacks(conn); | |
633 | iscsi_target_login_drop(conn, login); | |
634 | iscsit_deaccess_np(np, tpg, tpg_np); | |
635 | ||
636 | pr_debug("iscsi_target_do_cleanup done()\n"); | |
637 | } | |
638 | ||
639 | static void iscsi_target_sk_state_change(struct sock *sk) | |
640 | { | |
641 | struct iscsi_conn *conn; | |
642 | void (*orig_state_change)(struct sock *); | |
643 | bool state; | |
644 | ||
645 | pr_debug("Entering iscsi_target_sk_state_change\n"); | |
646 | ||
647 | write_lock_bh(&sk->sk_callback_lock); | |
648 | conn = sk->sk_user_data; | |
649 | if (!conn) { | |
650 | write_unlock_bh(&sk->sk_callback_lock); | |
651 | return; | |
652 | } | |
653 | orig_state_change = conn->orig_state_change; | |
654 | ||
655 | if (!test_bit(LOGIN_FLAGS_READY, &conn->login_flags)) { | |
656 | pr_debug("Got LOGIN_FLAGS_READY=0 sk_state_change conn: %p\n", | |
657 | conn); | |
658 | write_unlock_bh(&sk->sk_callback_lock); | |
659 | orig_state_change(sk); | |
660 | return; | |
661 | } | |
662 | if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) { | |
663 | pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change" | |
664 | " conn: %p\n", conn); | |
665 | write_unlock_bh(&sk->sk_callback_lock); | |
666 | orig_state_change(sk); | |
667 | return; | |
668 | } | |
669 | if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) { | |
670 | pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n", | |
671 | conn); | |
672 | write_unlock_bh(&sk->sk_callback_lock); | |
673 | orig_state_change(sk); | |
674 | return; | |
675 | } | |
676 | ||
677 | state = iscsi_target_sk_state_check(sk); | |
678 | write_unlock_bh(&sk->sk_callback_lock); | |
679 | ||
680 | pr_debug("iscsi_target_sk_state_change: state: %d\n", state); | |
681 | ||
682 | if (!state) { | |
683 | pr_debug("iscsi_target_sk_state_change got failed state\n"); | |
684 | schedule_delayed_work(&conn->login_cleanup_work, 0); | |
685 | return; | |
686 | } | |
687 | orig_state_change(sk); | |
688 | } | |
689 | ||
e48354ce NB |
690 | /* |
691 | * NOTE: We check for existing sessions or connections AFTER the initiator | |
692 | * has been successfully authenticated in order to protect against faked | |
693 | * ISID/TSIH combinations. | |
694 | */ | |
695 | static int iscsi_target_check_for_existing_instances( | |
696 | struct iscsi_conn *conn, | |
697 | struct iscsi_login *login) | |
698 | { | |
699 | if (login->checked_for_existing) | |
700 | return 0; | |
701 | ||
702 | login->checked_for_existing = 1; | |
703 | ||
704 | if (!login->tsih) | |
705 | return iscsi_check_for_session_reinstatement(conn); | |
706 | else | |
707 | return iscsi_login_post_auth_non_zero_tsih(conn, login->cid, | |
708 | login->initial_exp_statsn); | |
709 | } | |
710 | ||
711 | static int iscsi_target_do_authentication( | |
712 | struct iscsi_conn *conn, | |
713 | struct iscsi_login *login) | |
714 | { | |
715 | int authret; | |
716 | u32 payload_length; | |
717 | struct iscsi_param *param; | |
718 | struct iscsi_login_req *login_req; | |
719 | struct iscsi_login_rsp *login_rsp; | |
720 | ||
721 | login_req = (struct iscsi_login_req *) login->req; | |
722 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
723 | payload_length = ntoh24(login_req->dlength); | |
724 | ||
725 | param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); | |
726 | if (!param) | |
727 | return -1; | |
728 | ||
729 | authret = iscsi_handle_authentication( | |
730 | conn, | |
731 | login->req_buf, | |
732 | login->rsp_buf, | |
733 | payload_length, | |
734 | &login->rsp_length, | |
735 | param->value); | |
736 | switch (authret) { | |
737 | case 0: | |
738 | pr_debug("Received OK response" | |
739 | " from LIO Authentication, continuing.\n"); | |
740 | break; | |
741 | case 1: | |
742 | pr_debug("iSCSI security negotiation" | |
bfb9035c | 743 | " completed successfully.\n"); |
e48354ce NB |
744 | login->auth_complete = 1; |
745 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) && | |
746 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { | |
747 | login_rsp->flags |= (ISCSI_FLAG_LOGIN_NEXT_STAGE1 | | |
748 | ISCSI_FLAG_LOGIN_TRANSIT); | |
749 | login->current_stage = 1; | |
750 | } | |
751 | return iscsi_target_check_for_existing_instances( | |
752 | conn, login); | |
753 | case 2: | |
754 | pr_err("Security negotiation" | |
755 | " failed.\n"); | |
756 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
757 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
758 | return -1; | |
759 | default: | |
760 | pr_err("Received unknown error %d from LIO" | |
761 | " Authentication\n", authret); | |
762 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
763 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | |
764 | return -1; | |
765 | } | |
766 | ||
767 | return 0; | |
768 | } | |
769 | ||
770 | static int iscsi_target_handle_csg_zero( | |
771 | struct iscsi_conn *conn, | |
772 | struct iscsi_login *login) | |
773 | { | |
774 | int ret; | |
775 | u32 payload_length; | |
776 | struct iscsi_param *param; | |
777 | struct iscsi_login_req *login_req; | |
778 | struct iscsi_login_rsp *login_rsp; | |
779 | ||
780 | login_req = (struct iscsi_login_req *) login->req; | |
781 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
782 | payload_length = ntoh24(login_req->dlength); | |
783 | ||
784 | param = iscsi_find_param_from_key(AUTHMETHOD, conn->param_list); | |
785 | if (!param) | |
786 | return -1; | |
787 | ||
788 | ret = iscsi_decode_text_input( | |
789 | PHASE_SECURITY|PHASE_DECLARATIVE, | |
790 | SENDER_INITIATOR|SENDER_RECEIVER, | |
791 | login->req_buf, | |
792 | payload_length, | |
9977bb18 | 793 | conn); |
e48354ce NB |
794 | if (ret < 0) |
795 | return -1; | |
796 | ||
797 | if (ret > 0) { | |
798 | if (login->auth_complete) { | |
799 | pr_err("Initiator has already been" | |
800 | " successfully authenticated, but is still" | |
801 | " sending %s keys.\n", param->value); | |
802 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
803 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
804 | return -1; | |
805 | } | |
806 | ||
807 | goto do_auth; | |
91f0abfd NB |
808 | } else if (!payload_length) { |
809 | pr_err("Initiator sent zero length security payload," | |
810 | " login failed\n"); | |
811 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
812 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
813 | return -1; | |
e48354ce NB |
814 | } |
815 | ||
816 | if (login->first_request) | |
817 | if (iscsi_target_check_first_request(conn, login) < 0) | |
818 | return -1; | |
819 | ||
820 | ret = iscsi_encode_text_output( | |
821 | PHASE_SECURITY|PHASE_DECLARATIVE, | |
822 | SENDER_TARGET, | |
823 | login->rsp_buf, | |
824 | &login->rsp_length, | |
825 | conn->param_list); | |
826 | if (ret < 0) | |
827 | return -1; | |
828 | ||
829 | if (!iscsi_check_negotiated_keys(conn->param_list)) { | |
60bfcf8e | 830 | if (conn->tpg->tpg_attrib.authentication && |
e48354ce NB |
831 | !strncmp(param->value, NONE, 4)) { |
832 | pr_err("Initiator sent AuthMethod=None but" | |
833 | " Target is enforcing iSCSI Authentication," | |
834 | " login failed.\n"); | |
835 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
836 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
837 | return -1; | |
838 | } | |
839 | ||
60bfcf8e | 840 | if (conn->tpg->tpg_attrib.authentication && |
e48354ce NB |
841 | !login->auth_complete) |
842 | return 0; | |
843 | ||
844 | if (strncmp(param->value, NONE, 4) && !login->auth_complete) | |
845 | return 0; | |
846 | ||
847 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE1) && | |
848 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) { | |
849 | login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE1 | | |
850 | ISCSI_FLAG_LOGIN_TRANSIT; | |
851 | login->current_stage = 1; | |
852 | } | |
853 | } | |
854 | ||
855 | return 0; | |
856 | do_auth: | |
857 | return iscsi_target_do_authentication(conn, login); | |
858 | } | |
859 | ||
860 | static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_login *login) | |
861 | { | |
862 | int ret; | |
863 | u32 payload_length; | |
864 | struct iscsi_login_req *login_req; | |
865 | struct iscsi_login_rsp *login_rsp; | |
866 | ||
867 | login_req = (struct iscsi_login_req *) login->req; | |
868 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
869 | payload_length = ntoh24(login_req->dlength); | |
870 | ||
871 | ret = iscsi_decode_text_input( | |
872 | PHASE_OPERATIONAL|PHASE_DECLARATIVE, | |
873 | SENDER_INITIATOR|SENDER_RECEIVER, | |
874 | login->req_buf, | |
875 | payload_length, | |
9977bb18 | 876 | conn); |
1c5c12c6 RD |
877 | if (ret < 0) { |
878 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
879 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
e48354ce | 880 | return -1; |
1c5c12c6 | 881 | } |
e48354ce NB |
882 | |
883 | if (login->first_request) | |
884 | if (iscsi_target_check_first_request(conn, login) < 0) | |
885 | return -1; | |
886 | ||
887 | if (iscsi_target_check_for_existing_instances(conn, login) < 0) | |
888 | return -1; | |
889 | ||
890 | ret = iscsi_encode_text_output( | |
891 | PHASE_OPERATIONAL|PHASE_DECLARATIVE, | |
892 | SENDER_TARGET, | |
893 | login->rsp_buf, | |
894 | &login->rsp_length, | |
895 | conn->param_list); | |
1c5c12c6 RD |
896 | if (ret < 0) { |
897 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
898 | ISCSI_LOGIN_STATUS_INIT_ERR); | |
e48354ce | 899 | return -1; |
1c5c12c6 | 900 | } |
e48354ce NB |
901 | |
902 | if (!login->auth_complete && | |
60bfcf8e | 903 | conn->tpg->tpg_attrib.authentication) { |
e48354ce NB |
904 | pr_err("Initiator is requesting CSG: 1, has not been" |
905 | " successfully authenticated, and the Target is" | |
906 | " enforcing iSCSI Authentication, login failed.\n"); | |
907 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
908 | ISCSI_LOGIN_STATUS_AUTH_FAILED); | |
909 | return -1; | |
910 | } | |
911 | ||
912 | if (!iscsi_check_negotiated_keys(conn->param_list)) | |
913 | if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE3) && | |
914 | (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT)) | |
915 | login_rsp->flags |= ISCSI_FLAG_LOGIN_NEXT_STAGE3 | | |
916 | ISCSI_FLAG_LOGIN_TRANSIT; | |
917 | ||
918 | return 0; | |
919 | } | |
920 | ||
921 | static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *login) | |
922 | { | |
923 | int pdu_count = 0; | |
924 | struct iscsi_login_req *login_req; | |
925 | struct iscsi_login_rsp *login_rsp; | |
926 | ||
927 | login_req = (struct iscsi_login_req *) login->req; | |
928 | login_rsp = (struct iscsi_login_rsp *) login->rsp; | |
929 | ||
930 | while (1) { | |
931 | if (++pdu_count > MAX_LOGIN_PDUS) { | |
932 | pr_err("MAX_LOGIN_PDUS count reached.\n"); | |
933 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
934 | ISCSI_LOGIN_STATUS_TARGET_ERROR); | |
935 | return -1; | |
936 | } | |
937 | ||
5d358065 | 938 | switch (ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)) { |
e48354ce | 939 | case 0: |
5d358065 | 940 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK; |
e48354ce NB |
941 | if (iscsi_target_handle_csg_zero(conn, login) < 0) |
942 | return -1; | |
943 | break; | |
944 | case 1: | |
945 | login_rsp->flags |= ISCSI_FLAG_LOGIN_CURRENT_STAGE1; | |
946 | if (iscsi_target_handle_csg_one(conn, login) < 0) | |
947 | return -1; | |
948 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { | |
949 | login->tsih = conn->sess->tsih; | |
baa4d64b | 950 | login->login_complete = 1; |
d381a801 | 951 | iscsi_target_restore_sock_callbacks(conn); |
e48354ce NB |
952 | if (iscsi_target_do_tx_login_io(conn, |
953 | login) < 0) | |
954 | return -1; | |
d381a801 | 955 | return 1; |
e48354ce NB |
956 | } |
957 | break; | |
958 | default: | |
959 | pr_err("Illegal CSG: %d received from" | |
960 | " Initiator, protocol error.\n", | |
5d358065 | 961 | ISCSI_LOGIN_CURRENT_STAGE(login_req->flags)); |
e48354ce NB |
962 | break; |
963 | } | |
964 | ||
ea3a179a | 965 | if (iscsi_target_do_tx_login_io(conn, login) < 0) |
e48354ce NB |
966 | return -1; |
967 | ||
968 | if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) { | |
969 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT; | |
970 | login_rsp->flags &= ~ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK; | |
971 | } | |
d381a801 | 972 | break; |
e48354ce NB |
973 | } |
974 | ||
bb048357 NB |
975 | if (conn->sock) { |
976 | struct sock *sk = conn->sock->sk; | |
977 | bool state; | |
978 | ||
979 | read_lock_bh(&sk->sk_callback_lock); | |
980 | state = iscsi_target_sk_state_check(sk); | |
981 | read_unlock_bh(&sk->sk_callback_lock); | |
982 | ||
983 | if (!state) { | |
984 | pr_debug("iscsi_target_do_login() failed state for" | |
985 | " conn: %p\n", conn); | |
986 | return -1; | |
987 | } | |
988 | } | |
989 | ||
e48354ce NB |
990 | return 0; |
991 | } | |
992 | ||
993 | static void iscsi_initiatorname_tolower( | |
994 | char *param_buf) | |
995 | { | |
996 | char *c; | |
997 | u32 iqn_size = strlen(param_buf), i; | |
998 | ||
999 | for (i = 0; i < iqn_size; i++) { | |
8359cf43 | 1000 | c = ¶m_buf[i]; |
e48354ce NB |
1001 | if (!isupper(*c)) |
1002 | continue; | |
1003 | ||
1004 | *c = tolower(*c); | |
1005 | } | |
1006 | } | |
1007 | ||
1008 | /* | |
1009 | * Processes the first Login Request.. | |
1010 | */ | |
baa4d64b | 1011 | int iscsi_target_locate_portal( |
e48354ce NB |
1012 | struct iscsi_np *np, |
1013 | struct iscsi_conn *conn, | |
1014 | struct iscsi_login *login) | |
1015 | { | |
1016 | char *i_buf = NULL, *s_buf = NULL, *t_buf = NULL; | |
1017 | char *tmpbuf, *start = NULL, *end = NULL, *key, *value; | |
1018 | struct iscsi_session *sess = conn->sess; | |
1019 | struct iscsi_tiqn *tiqn; | |
d381a801 | 1020 | struct iscsi_tpg_np *tpg_np = NULL; |
e48354ce | 1021 | struct iscsi_login_req *login_req; |
988e3a85 NB |
1022 | struct se_node_acl *se_nacl; |
1023 | u32 payload_length, queue_depth = 0; | |
1024 | int sessiontype = 0, ret = 0, tag_num, tag_size; | |
e48354ce | 1025 | |
d381a801 | 1026 | INIT_DELAYED_WORK(&conn->login_work, iscsi_target_do_login_rx); |
bb048357 | 1027 | INIT_DELAYED_WORK(&conn->login_cleanup_work, iscsi_target_do_cleanup); |
d381a801 NB |
1028 | iscsi_target_set_sock_callbacks(conn); |
1029 | ||
1030 | login->np = np; | |
1031 | ||
e48354ce | 1032 | login_req = (struct iscsi_login_req *) login->req; |
e48354ce NB |
1033 | payload_length = ntoh24(login_req->dlength); |
1034 | ||
e48354ce NB |
1035 | tmpbuf = kzalloc(payload_length + 1, GFP_KERNEL); |
1036 | if (!tmpbuf) { | |
1037 | pr_err("Unable to allocate memory for tmpbuf.\n"); | |
1038 | return -1; | |
1039 | } | |
1040 | ||
1041 | memcpy(tmpbuf, login->req_buf, payload_length); | |
1042 | tmpbuf[payload_length] = '\0'; | |
1043 | start = tmpbuf; | |
1044 | end = (start + payload_length); | |
1045 | ||
1046 | /* | |
1047 | * Locate the initial keys expected from the Initiator node in | |
1048 | * the first login request in order to progress with the login phase. | |
1049 | */ | |
1050 | while (start < end) { | |
1051 | if (iscsi_extract_key_value(start, &key, &value) < 0) { | |
1052 | ret = -1; | |
1053 | goto out; | |
1054 | } | |
1055 | ||
1056 | if (!strncmp(key, "InitiatorName", 13)) | |
1057 | i_buf = value; | |
1058 | else if (!strncmp(key, "SessionType", 11)) | |
1059 | s_buf = value; | |
1060 | else if (!strncmp(key, "TargetName", 10)) | |
1061 | t_buf = value; | |
1062 | ||
1063 | start += strlen(key) + strlen(value) + 2; | |
1064 | } | |
e48354ce NB |
1065 | /* |
1066 | * See 5.3. Login Phase. | |
1067 | */ | |
1068 | if (!i_buf) { | |
1069 | pr_err("InitiatorName key not received" | |
1070 | " in first login request.\n"); | |
1071 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1072 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
1073 | ret = -1; | |
1074 | goto out; | |
1075 | } | |
1076 | /* | |
1077 | * Convert the incoming InitiatorName to lowercase following | |
1078 | * RFC-3720 3.2.6.1. section c) that says that iSCSI IQNs | |
1079 | * are NOT case sensitive. | |
1080 | */ | |
1081 | iscsi_initiatorname_tolower(i_buf); | |
1082 | ||
1083 | if (!s_buf) { | |
1084 | if (!login->leading_connection) | |
1085 | goto get_target; | |
1086 | ||
1087 | pr_err("SessionType key not received" | |
1088 | " in first login request.\n"); | |
1089 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1090 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
1091 | ret = -1; | |
1092 | goto out; | |
1093 | } | |
1094 | ||
1095 | /* | |
1096 | * Use default portal group for discovery sessions. | |
1097 | */ | |
1098 | sessiontype = strncmp(s_buf, DISCOVERY, 9); | |
1099 | if (!sessiontype) { | |
1100 | conn->tpg = iscsit_global->discovery_tpg; | |
1101 | if (!login->leading_connection) | |
1102 | goto get_target; | |
1103 | ||
1104 | sess->sess_ops->SessionType = 1; | |
1105 | /* | |
1106 | * Setup crc32c modules from libcrypto | |
1107 | */ | |
1108 | if (iscsi_login_setup_crypto(conn) < 0) { | |
1109 | pr_err("iscsi_login_setup_crypto() failed\n"); | |
1110 | ret = -1; | |
1111 | goto out; | |
1112 | } | |
1113 | /* | |
1114 | * Serialize access across the discovery struct iscsi_portal_group to | |
1115 | * process login attempt. | |
1116 | */ | |
1117 | if (iscsit_access_np(np, conn->tpg) < 0) { | |
1118 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1119 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
1120 | ret = -1; | |
1121 | goto out; | |
1122 | } | |
1123 | ret = 0; | |
988e3a85 | 1124 | goto alloc_tags; |
e48354ce NB |
1125 | } |
1126 | ||
1127 | get_target: | |
1128 | if (!t_buf) { | |
1129 | pr_err("TargetName key not received" | |
1130 | " in first login request while" | |
1131 | " SessionType=Normal.\n"); | |
1132 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1133 | ISCSI_LOGIN_STATUS_MISSING_FIELDS); | |
1134 | ret = -1; | |
1135 | goto out; | |
1136 | } | |
1137 | ||
1138 | /* | |
1139 | * Locate Target IQN from Storage Node. | |
1140 | */ | |
1141 | tiqn = iscsit_get_tiqn_for_login(t_buf); | |
1142 | if (!tiqn) { | |
1143 | pr_err("Unable to locate Target IQN: %s in" | |
1144 | " Storage Node\n", t_buf); | |
1145 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1146 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
1147 | ret = -1; | |
1148 | goto out; | |
1149 | } | |
1150 | pr_debug("Located Storage Object: %s\n", tiqn->tiqn); | |
1151 | ||
1152 | /* | |
1153 | * Locate Target Portal Group from Storage Node. | |
1154 | */ | |
d381a801 | 1155 | conn->tpg = iscsit_get_tpg_from_np(tiqn, np, &tpg_np); |
e48354ce NB |
1156 | if (!conn->tpg) { |
1157 | pr_err("Unable to locate Target Portal Group" | |
1158 | " on %s\n", tiqn->tiqn); | |
1159 | iscsit_put_tiqn_for_login(tiqn); | |
1160 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1161 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
1162 | ret = -1; | |
1163 | goto out; | |
1164 | } | |
d381a801 | 1165 | conn->tpg_np = tpg_np; |
e48354ce NB |
1166 | pr_debug("Located Portal Group Object: %hu\n", conn->tpg->tpgt); |
1167 | /* | |
1168 | * Setup crc32c modules from libcrypto | |
1169 | */ | |
1170 | if (iscsi_login_setup_crypto(conn) < 0) { | |
1171 | pr_err("iscsi_login_setup_crypto() failed\n"); | |
d381a801 NB |
1172 | kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); |
1173 | iscsit_put_tiqn_for_login(tiqn); | |
1174 | conn->tpg = NULL; | |
e48354ce NB |
1175 | ret = -1; |
1176 | goto out; | |
1177 | } | |
1178 | /* | |
1179 | * Serialize access across the struct iscsi_portal_group to | |
1180 | * process login attempt. | |
1181 | */ | |
1182 | if (iscsit_access_np(np, conn->tpg) < 0) { | |
d381a801 | 1183 | kref_put(&tpg_np->tpg_np_kref, iscsit_login_kref_put); |
e48354ce NB |
1184 | iscsit_put_tiqn_for_login(tiqn); |
1185 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1186 | ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); | |
e48354ce | 1187 | conn->tpg = NULL; |
d381a801 | 1188 | ret = -1; |
e48354ce NB |
1189 | goto out; |
1190 | } | |
1191 | ||
1192 | /* | |
1193 | * conn->sess->node_acl will be set when the referenced | |
1194 | * struct iscsi_session is located from received ISID+TSIH in | |
1195 | * iscsi_login_non_zero_tsih_s2(). | |
1196 | */ | |
1197 | if (!login->leading_connection) { | |
1198 | ret = 0; | |
1199 | goto out; | |
1200 | } | |
1201 | ||
1202 | /* | |
1203 | * This value is required in iscsi_login_zero_tsih_s2() | |
1204 | */ | |
1205 | sess->sess_ops->SessionType = 0; | |
1206 | ||
1207 | /* | |
1208 | * Locate incoming Initiator IQN reference from Storage Node. | |
1209 | */ | |
1210 | sess->se_sess->se_node_acl = core_tpg_check_initiator_node_acl( | |
1211 | &conn->tpg->tpg_se_tpg, i_buf); | |
1212 | if (!sess->se_sess->se_node_acl) { | |
1213 | pr_err("iSCSI Initiator Node: %s is not authorized to" | |
1214 | " access iSCSI target portal group: %hu.\n", | |
1215 | i_buf, conn->tpg->tpgt); | |
1216 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, | |
1217 | ISCSI_LOGIN_STATUS_TGT_FORBIDDEN); | |
1218 | ret = -1; | |
1219 | goto out; | |
1220 | } | |
988e3a85 NB |
1221 | se_nacl = sess->se_sess->se_node_acl; |
1222 | queue_depth = se_nacl->queue_depth; | |
1223 | /* | |
1224 | * Setup pre-allocated tags based upon allowed per NodeACL CmdSN | |
1225 | * depth for non immediate commands, plus extra tags for immediate | |
1226 | * commands. | |
1227 | * | |
1228 | * Also enforce a ISCSIT_MIN_TAGS to prevent unnecessary contention | |
1229 | * in per-cpu-ida tag allocation logic + small queue_depth. | |
1230 | */ | |
1231 | alloc_tags: | |
1232 | tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth); | |
4a4caa29 | 1233 | tag_num = (tag_num * 2) + ISCSIT_EXTRA_TAGS; |
988e3a85 | 1234 | tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size; |
e48354ce | 1235 | |
988e3a85 NB |
1236 | ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size); |
1237 | if (ret < 0) { | |
1238 | iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, | |
1239 | ISCSI_LOGIN_STATUS_NO_RESOURCES); | |
1240 | ret = -1; | |
1241 | } | |
e48354ce NB |
1242 | out: |
1243 | kfree(tmpbuf); | |
1244 | return ret; | |
1245 | } | |
1246 | ||
e48354ce NB |
1247 | int iscsi_target_start_negotiation( |
1248 | struct iscsi_login *login, | |
1249 | struct iscsi_conn *conn) | |
1250 | { | |
baa4d64b | 1251 | int ret; |
e48354ce NB |
1252 | |
1253 | ret = iscsi_target_do_login(conn, login); | |
d381a801 NB |
1254 | if (!ret) { |
1255 | if (conn->sock) { | |
1256 | struct sock *sk = conn->sock->sk; | |
1257 | ||
1258 | write_lock_bh(&sk->sk_callback_lock); | |
1259 | set_bit(LOGIN_FLAGS_READY, &conn->login_flags); | |
1260 | write_unlock_bh(&sk->sk_callback_lock); | |
1261 | } | |
1262 | } else if (ret < 0) { | |
1263 | cancel_delayed_work_sync(&conn->login_work); | |
bb048357 | 1264 | cancel_delayed_work_sync(&conn->login_cleanup_work); |
d381a801 | 1265 | iscsi_target_restore_sock_callbacks(conn); |
e48354ce | 1266 | iscsi_remove_failed_auth_entry(conn); |
d381a801 NB |
1267 | } |
1268 | if (ret != 0) | |
1269 | iscsi_target_nego_release(conn); | |
e48354ce | 1270 | |
e48354ce NB |
1271 | return ret; |
1272 | } | |
1273 | ||
baa4d64b | 1274 | void iscsi_target_nego_release(struct iscsi_conn *conn) |
e48354ce | 1275 | { |
baa4d64b NB |
1276 | struct iscsi_login *login = conn->conn_login; |
1277 | ||
1278 | if (!login) | |
1279 | return; | |
1280 | ||
e48354ce NB |
1281 | kfree(login->req_buf); |
1282 | kfree(login->rsp_buf); | |
1283 | kfree(login); | |
baa4d64b NB |
1284 | |
1285 | conn->conn_login = NULL; | |
e48354ce | 1286 | } |