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