1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2016 Nexenta Systems, Inc.
25 */
26
27 #include <sys/cpuvar.h>
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/file.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/modctl.h>
34 #include <sys/scsi/generic/persist.h>
35 #include <sys/scsi/scsi_names.h>
36
37 #include <sys/socket.h>
38 #include <sys/strsubr.h>
39 #include <sys/sysmacros.h>
40 #include <sys/note.h>
41 #include <sys/sdt.h>
42 #include <sys/errno.h>
43
44 #include <sys/stmf.h>
45 #include <sys/stmf_ioctl.h>
46 #include <sys/portif.h>
47 #include <sys/idm/idm.h>
48 #include <sys/idm/idm_text.h>
49 #include <sys/idm/idm_so.h>
50
51 #define ISCSIT_LOGIN_SM_STRINGS
52 #include "iscsit.h"
53 #include "iscsit_auth.h"
54
55 typedef struct {
56 list_node_t le_ctx_node;
57 iscsit_login_event_t le_ctx_event;
58 idm_pdu_t *le_pdu;
59 } login_event_ctx_t;
60
61 #ifndef TRUE
62 #define TRUE B_TRUE
63 #endif
64
65 #ifndef FALSE
66 #define FALSE B_FALSE
67 #endif
68
69 #define DEFAULT_RADIUS_PORT 1812
70
71 static void
72 login_sm_complete(void *ict_void);
73
74 static void
75 login_sm_event_dispatch(iscsit_conn_login_t *lsm, iscsit_conn_t *ict,
76 login_event_ctx_t *ctx);
77
78 static void
79 login_sm_init(iscsit_conn_t *ict, login_event_ctx_t *ctx);
80
81 static void
82 login_sm_waiting(iscsit_conn_t *ict, login_event_ctx_t *ctx);
83
84 static void
85 login_sm_processing(iscsit_conn_t *ict, login_event_ctx_t *ctx);
86
87 static void
88 login_sm_responding(iscsit_conn_t *ict, login_event_ctx_t *ctx);
89
90 static void
91 login_sm_responded(iscsit_conn_t *ict, login_event_ctx_t *ctx);
92
93 static void
94 login_sm_ffp(iscsit_conn_t *ict, login_event_ctx_t *ctx);
95
96 static void
97 login_sm_done(iscsit_conn_t *ict, login_event_ctx_t *ctx);
98
99 static void
100 login_sm_error(iscsit_conn_t *ict, login_event_ctx_t *ctx);
101
102 static void
103 login_sm_new_state(iscsit_conn_t *ict, login_event_ctx_t *ctx,
104 iscsit_login_state_t new_state);
105
106 static void
107 login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu);
108
109 static idm_status_t
110 login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu);
111
112 static boolean_t
113 login_sm_is_last_response(idm_pdu_t *pdu);
114
115 static void
116 login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu);
117
118 static void
119 login_sm_send_next_response(iscsit_conn_t *ict, idm_pdu_t *pdu);
120
121 static void
122 login_sm_process_request(iscsit_conn_t *ict);
123
124 static idm_status_t
125 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu);
126
127 static idm_status_t
128 login_sm_process_nvlist(iscsit_conn_t *ict);
129
130 static idm_status_t
131 login_sm_check_security(iscsit_conn_t *ict);
132
133 static idm_pdu_t *
134 login_sm_build_login_response(iscsit_conn_t *ict);
135
136 static void
137 login_sm_ffp_actions(iscsit_conn_t *ict);
138
139 static idm_status_t
140 login_sm_validate_initial_parameters(iscsit_conn_t *ict);
141
142 static idm_status_t
143 login_sm_session_bind(iscsit_conn_t *ict);
144
145 static idm_status_t
146 login_sm_set_auth(iscsit_conn_t *ict);
147
148 static idm_status_t
149 login_sm_session_register(iscsit_conn_t *ict);
150
151 static kv_status_t
152 iscsit_handle_key(iscsit_conn_t *ict, nvpair_t *nvp, char *nvp_name);
153
154 static kv_status_t
155 iscsit_handle_common_key(iscsit_conn_t *ict, nvpair_t *nvp,
156 const idm_kv_xlate_t *ikvx);
157
158 static kv_status_t
159 iscsit_handle_security_key(iscsit_conn_t *ict, nvpair_t *nvp,
160 const idm_kv_xlate_t *ikvx);
161
162 static kv_status_t
163 iscsit_reply_security_key(iscsit_conn_t *ict);
164
165 static kv_status_t
166 iscsit_handle_operational_key(iscsit_conn_t *ict, nvpair_t *nvp,
167 const idm_kv_xlate_t *ikvx);
168
169 static kv_status_t
170 iscsit_reply_numerical(iscsit_conn_t *ict,
171 const char *nvp_name, const uint64_t value);
172
173 static kv_status_t
174 iscsit_reply_string(iscsit_conn_t *ict,
175 const char *nvp_name, const char *text);
176
177 static kv_status_t
178 iscsit_handle_digest(iscsit_conn_t *ict, nvpair_t *choices,
179 const idm_kv_xlate_t *ikvx);
180
181 static kv_status_t
182 iscsit_handle_boolean(iscsit_conn_t *ict, nvpair_t *nvp, boolean_t value,
183 const idm_kv_xlate_t *ikvx, boolean_t iscsit_value);
184
185 static kv_status_t
186 iscsit_handle_numerical(iscsit_conn_t *ict, nvpair_t *nvp, uint64_t value,
187 const idm_kv_xlate_t *ikvx,
188 uint64_t iscsi_min_value, uint64_t iscsi_max_value,
189 uint64_t iscsit_max_value);
190
191 static void
192 iscsit_process_negotiated_values(iscsit_conn_t *ict);
193
194 static void
195 login_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status);
196
197 static idm_status_t
198 iscsit_add_declarative_keys(iscsit_conn_t *ict);
199
200 static char *
201 iscsit_fold_name(char *name, size_t *buflen);
202
203 uint64_t max_dataseglen_target = ISCSIT_MAX_RECV_DATA_SEGMENT_LENGTH;
204
205 /*
206 * global mutex defined in iscsit.c to enforce
207 * login_sm_session_bind as a critical section
208 */
209 extern kmutex_t login_sm_session_mutex;
210
211 idm_status_t
iscsit_login_sm_init(iscsit_conn_t * ict)212 iscsit_login_sm_init(iscsit_conn_t *ict)
213 {
214 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
215
216 bzero(lsm, sizeof (iscsit_conn_login_t));
217
218 (void) nvlist_alloc(&lsm->icl_negotiated_values, NV_UNIQUE_NAME,
219 KM_SLEEP);
220
221 /*
222 * Hold connection until the login state machine completes
223 */
224 iscsit_conn_hold(ict);
225
226 /*
227 * Pre-allocating a login response PDU means we will always be
228 * able to respond to a login request -- even if we can't allocate
229 * a data buffer to hold the text responses we can at least send
230 * a login failure.
231 */
232 lsm->icl_login_resp_tmpl = kmem_zalloc(sizeof (iscsi_login_rsp_hdr_t),
233 KM_SLEEP);
234
235 idm_sm_audit_init(&lsm->icl_state_audit);
236 mutex_init(&lsm->icl_mutex, NULL, MUTEX_DEFAULT, NULL);
237 list_create(&lsm->icl_login_events, sizeof (login_event_ctx_t),
238 offsetof(login_event_ctx_t, le_ctx_node));
239 list_create(&lsm->icl_pdu_list, sizeof (idm_pdu_t),
240 offsetof(idm_pdu_t, isp_client_lnd));
241
242 lsm->icl_login_state = ILS_LOGIN_INIT;
243 lsm->icl_login_last_state = ILS_LOGIN_INIT;
244
245 /*
246 * Initialize operational parameters to default values. Anything
247 * we don't specifically negotiate stays at the default.
248 */
249 ict->ict_op.op_discovery_session = B_FALSE;
250 ict->ict_op.op_initial_r2t = ISCSI_DEFAULT_INITIALR2T;
251 ict->ict_op.op_immed_data = ISCSI_DEFAULT_IMMEDIATE_DATA;
252 ict->ict_op.op_data_pdu_in_order = ISCSI_DEFAULT_DATA_PDU_IN_ORDER;
253 ict->ict_op.op_data_sequence_in_order =
254 ISCSI_DEFAULT_DATA_SEQUENCE_IN_ORDER;
255 ict->ict_op.op_max_connections = ISCSI_DEFAULT_MAX_CONNECTIONS;
256 ict->ict_op.op_max_recv_data_segment_length =
257 ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
258 ict->ict_op.op_max_burst_length = ISCSI_DEFAULT_MAX_BURST_LENGTH;
259 ict->ict_op.op_first_burst_length = ISCSI_DEFAULT_FIRST_BURST_LENGTH;
260 ict->ict_op.op_default_time_2_wait = ISCSI_DEFAULT_TIME_TO_WAIT;
261 ict->ict_op.op_default_time_2_retain = ISCSI_DEFAULT_TIME_TO_RETAIN;
262 ict->ict_op.op_max_outstanding_r2t = ISCSI_DEFAULT_MAX_OUT_R2T;
263 ict->ict_op.op_error_recovery_level =
264 ISCSI_DEFAULT_ERROR_RECOVERY_LEVEL;
265
266 return (IDM_STATUS_SUCCESS);
267 }
268
269 static void
login_resp_complete_cb(idm_pdu_t * pdu,idm_status_t status)270 login_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status)
271 {
272 iscsit_conn_t *ict = pdu->isp_private;
273
274 /*
275 * Check that this is a login pdu
276 */
277 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0);
278 idm_pdu_free(pdu);
279
280 if ((status != IDM_STATUS_SUCCESS) ||
281 (ict->ict_login_sm.icl_login_resp_err_class != 0)) {
282 /*
283 * Transport or login error occurred.
284 */
285 iscsit_login_sm_event(ict, ILE_LOGIN_ERROR, NULL);
286 }
287 iscsit_conn_rele(ict);
288 }
289
290 void
iscsit_login_sm_fini(iscsit_conn_t * ict)291 iscsit_login_sm_fini(iscsit_conn_t *ict)
292 {
293 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
294
295 mutex_enter(&lsm->icl_mutex);
296 list_destroy(&lsm->icl_pdu_list);
297 list_destroy(&lsm->icl_login_events);
298
299 kmem_free(lsm->icl_login_resp_tmpl, sizeof (iscsi_login_rsp_hdr_t));
300
301 /* clean up the login response idm text buffer */
302 if (lsm->icl_login_resp_itb != NULL) {
303 idm_itextbuf_free(lsm->icl_login_resp_itb);
304 lsm->icl_login_resp_itb = NULL;
305 }
306
307 nvlist_free(lsm->icl_negotiated_values);
308 mutex_destroy(&lsm->icl_mutex);
309 }
310
311 void
iscsit_login_sm_event(iscsit_conn_t * ict,iscsit_login_event_t event,idm_pdu_t * pdu)312 iscsit_login_sm_event(iscsit_conn_t *ict, iscsit_login_event_t event,
313 idm_pdu_t *pdu)
314 {
315 /*
316 * This is a bit ugly but if we're already in ILS_LOGIN_ERROR
317 * or ILS_LOGIN_DONE then just drop any additional events. They
318 * won't change the state and it's possible we've already called
319 * iscsit_login_sm_fini in which case the mutex is destroyed.
320 */
321 if ((ict->ict_login_sm.icl_login_state == ILS_LOGIN_ERROR) ||
322 (ict->ict_login_sm.icl_login_state == ILS_LOGIN_DONE))
323 return;
324
325 mutex_enter(&ict->ict_login_sm.icl_mutex);
326 iscsit_login_sm_event_locked(ict, event, pdu);
327 mutex_exit(&ict->ict_login_sm.icl_mutex);
328 }
329 void
iscsit_login_sm_event_locked(iscsit_conn_t * ict,iscsit_login_event_t event,idm_pdu_t * pdu)330 iscsit_login_sm_event_locked(iscsit_conn_t *ict, iscsit_login_event_t event,
331 idm_pdu_t *pdu)
332 {
333 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
334 login_event_ctx_t *ctx;
335
336 ASSERT(mutex_owned(&lsm->icl_mutex));
337 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
338
339 ctx->le_ctx_event = event;
340 ctx->le_pdu = pdu;
341
342 list_insert_tail(&lsm->icl_login_events, ctx);
343
344 /*
345 * Use the icl_busy flag to keep the state machine single threaded.
346 * This also serves as recursion avoidance since this flag will
347 * always be set if we call login_sm_event from within the
348 * state machine code.
349 */
350 if (!lsm->icl_busy) {
351 lsm->icl_busy = B_TRUE;
352 while (!list_is_empty(&lsm->icl_login_events)) {
353 ctx = list_head(&lsm->icl_login_events);
354 list_remove(&lsm->icl_login_events, ctx);
355 idm_sm_audit_event(&lsm->icl_state_audit,
356 SAS_ISCSIT_LOGIN, (int)lsm->icl_login_state,
357 (int)ctx->le_ctx_event, (uintptr_t)pdu);
358
359 /*
360 * If the lsm is in a terminal state, just drain
361 * any remaining events.
362 */
363 if ((lsm->icl_login_state == ILS_LOGIN_ERROR) ||
364 (lsm->icl_login_state == ILS_LOGIN_DONE)) {
365 kmem_free(ctx, sizeof (*ctx));
366 continue;
367 }
368 mutex_exit(&lsm->icl_mutex);
369 login_sm_event_dispatch(lsm, ict, ctx);
370 mutex_enter(&lsm->icl_mutex);
371 }
372 lsm->icl_busy = B_FALSE;
373
374 /*
375 * When the state machine reaches ILS_LOGIN_DONE or
376 * ILS_LOGIN_ERROR state the login process has completed
377 * and it's time to cleanup. The state machine code will
378 * mark itself "complete" when this happens.
379 *
380 * To protect against spurious events (which shouldn't
381 * happen) set icl_busy again.
382 */
383 if (lsm->icl_login_complete) {
384 lsm->icl_busy = B_TRUE;
385 if (taskq_dispatch(iscsit_global.global_dispatch_taskq,
386 login_sm_complete, ict, DDI_SLEEP) ==
387 TASKQID_INVALID) {
388 cmn_err(CE_WARN, "iscsit_login_sm_event_locked:"
389 " Failed to dispatch task");
390 }
391 }
392 }
393 }
394
395 static void
login_sm_complete(void * ict_void)396 login_sm_complete(void *ict_void)
397 {
398 iscsit_conn_t *ict = ict_void;
399
400 /*
401 * State machine has run to completion, resources
402 * will be cleaned up when connection is destroyed.
403 */
404 iscsit_conn_rele(ict);
405 }
406
407 static void
login_sm_event_dispatch(iscsit_conn_login_t * lsm,iscsit_conn_t * ict,login_event_ctx_t * ctx)408 login_sm_event_dispatch(iscsit_conn_login_t *lsm, iscsit_conn_t *ict,
409 login_event_ctx_t *ctx)
410 {
411 idm_pdu_t *pdu = ctx->le_pdu; /* Only valid for some events */
412
413 DTRACE_PROBE2(login__event, iscsit_conn_t *, ict,
414 login_event_ctx_t *, ctx);
415
416 IDM_SM_LOG(CE_NOTE, "login_sm_event_dispatch: ict %p event %s(%d)",
417 (void *)ict,
418 iscsit_ile_name[ctx->le_ctx_event], ctx->le_ctx_event);
419
420 /* State independent actions */
421 switch (ctx->le_ctx_event) {
422 case ILE_LOGIN_RCV:
423 /* Perform basic sanity checks on the header */
424 if (login_sm_req_pdu_check(ict, pdu) != IDM_STATUS_SUCCESS) {
425 idm_pdu_t *rpdu;
426
427 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
428 ISCSI_LOGIN_STATUS_INVALID_REQUEST);
429 /*
430 * If we haven't processed any PDU's yet then use
431 * this one as a template for the response
432 */
433 if (ict->ict_login_sm.icl_login_resp_tmpl->opcode == 0)
434 login_sm_handle_initial_login(ict, pdu);
435 rpdu = login_sm_build_login_response(ict);
436 login_sm_send_next_response(ict, rpdu);
437 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
438 kmem_free(ctx, sizeof (*ctx));
439 return;
440 }
441 break;
442 default:
443 break;
444 }
445
446 /* State dependent actions */
447 switch (lsm->icl_login_state) {
448 case ILS_LOGIN_INIT:
449 login_sm_init(ict, ctx);
450 break;
451 case ILS_LOGIN_WAITING:
452 login_sm_waiting(ict, ctx);
453 break;
454 case ILS_LOGIN_PROCESSING:
455 login_sm_processing(ict, ctx);
456 break;
457 case ILS_LOGIN_RESPONDING:
458 login_sm_responding(ict, ctx);
459 break;
460 case ILS_LOGIN_RESPONDED:
461 login_sm_responded(ict, ctx);
462 break;
463 case ILS_LOGIN_FFP:
464 login_sm_ffp(ict, ctx);
465 break;
466 case ILS_LOGIN_DONE:
467 login_sm_done(ict, ctx);
468 break;
469 case ILS_LOGIN_ERROR:
470 login_sm_error(ict, ctx);
471 break;
472 }
473
474 kmem_free(ctx, sizeof (*ctx));
475 }
476
477 static void
login_sm_init(iscsit_conn_t * ict,login_event_ctx_t * ctx)478 login_sm_init(iscsit_conn_t *ict, login_event_ctx_t *ctx)
479 {
480 idm_pdu_t *pdu;
481
482 switch (ctx->le_ctx_event) {
483 case ILE_LOGIN_RCV:
484 pdu = ctx->le_pdu;
485
486 /*
487 * This is the first login PDU we've received so use
488 * it to build the login response template and set our CSG.
489 */
490 login_sm_handle_initial_login(ict, pdu);
491
492 /*
493 * Accumulate all the login PDU's that make up this
494 * request on a queue.
495 */
496 mutex_enter(&ict->ict_login_sm.icl_mutex);
497 list_insert_tail(&ict->ict_login_sm.icl_pdu_list, pdu);
498 mutex_exit(&ict->ict_login_sm.icl_mutex);
499
500 if (pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) {
501 login_sm_send_ack(ict, pdu);
502 login_sm_new_state(ict, ctx, ILS_LOGIN_WAITING);
503 } else {
504 login_sm_new_state(ict, ctx, ILS_LOGIN_PROCESSING);
505 }
506 break;
507 case ILE_LOGIN_CONN_ERROR:
508 case ILE_LOGIN_ERROR:
509 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
510 break;
511 default:
512 ASSERT(0);
513 }
514 }
515
516 static void
login_sm_waiting(iscsit_conn_t * ict,login_event_ctx_t * ctx)517 login_sm_waiting(iscsit_conn_t *ict, login_event_ctx_t *ctx)
518 {
519 idm_pdu_t *pdu;
520
521 switch (ctx->le_ctx_event) {
522 case ILE_LOGIN_RCV:
523 pdu = ctx->le_pdu;
524 mutex_enter(&ict->ict_login_sm.icl_mutex);
525 list_insert_tail(&ict->ict_login_sm.icl_pdu_list, pdu);
526 mutex_exit(&ict->ict_login_sm.icl_mutex);
527 if (!(pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE)) {
528 login_sm_new_state(ict, ctx, ILS_LOGIN_PROCESSING);
529 } else {
530 login_sm_send_ack(ict, pdu);
531 }
532 break;
533 case ILE_LOGIN_ERROR:
534 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
535 break;
536 case ILE_LOGIN_RESP_COMPLETE:
537 break;
538 default:
539 ASSERT(0);
540 }
541 }
542
543 static void
login_sm_processing(iscsit_conn_t * ict,login_event_ctx_t * ctx)544 login_sm_processing(iscsit_conn_t *ict, login_event_ctx_t *ctx)
545 {
546 switch (ctx->le_ctx_event) {
547 case ILE_LOGIN_RESP_READY:
548 login_sm_new_state(ict, ctx, ILS_LOGIN_RESPONDING);
549 break;
550 case ILE_LOGIN_RCV:
551 idm_pdu_complete(ctx->le_pdu, IDM_STATUS_SUCCESS);
552 /*FALLTHROUGH*/
553 case ILE_LOGIN_CONN_ERROR:
554 case ILE_LOGIN_ERROR:
555 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
556 break;
557 default:
558 ASSERT(0);
559 }
560 }
561
562 static void
login_sm_responding(iscsit_conn_t * ict,login_event_ctx_t * ctx)563 login_sm_responding(iscsit_conn_t *ict, login_event_ctx_t *ctx)
564 {
565 idm_pdu_t *pdu, *rpdu;
566
567 switch (ctx->le_ctx_event) {
568 case ILE_LOGIN_RCV:
569 pdu = ctx->le_pdu;
570 /*
571 * We should only be in "responding" state if we have not
572 * sent the last PDU of a multi-PDU login response sequence.
573 * In that case we expect this received PDU to be an
574 * acknowledgement from the initiator (login PDU with C
575 * bit cleared and no data). If it's the acknowledgement
576 * we are expecting then we send the next PDU in the login
577 * response sequence. Otherwise it's a protocol error and
578 * the login fails.
579 */
580 if (login_sm_validate_ack(ict, pdu) == IDM_STATUS_SUCCESS) {
581 rpdu = login_sm_build_login_response(ict);
582 login_sm_send_next_response(ict, rpdu);
583 } else {
584 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
585 }
586 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
587 break;
588 case ILE_LOGIN_FFP:
589 login_sm_new_state(ict, ctx, ILS_LOGIN_FFP);
590 break;
591 case ILE_LOGIN_RESP_COMPLETE:
592 login_sm_new_state(ict, ctx, ILS_LOGIN_RESPONDED);
593 break;
594 case ILE_LOGIN_CONN_ERROR:
595 case ILE_LOGIN_ERROR:
596 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
597 break;
598 default:
599 ASSERT(0);
600 }
601 }
602
603 static void
login_sm_responded(iscsit_conn_t * ict,login_event_ctx_t * ctx)604 login_sm_responded(iscsit_conn_t *ict, login_event_ctx_t *ctx)
605 {
606 idm_pdu_t *pdu;
607 iscsi_login_hdr_t *lh;
608
609 switch (ctx->le_ctx_event) {
610 case ILE_LOGIN_RCV:
611 pdu = ctx->le_pdu;
612 lh = (iscsi_login_hdr_t *)pdu->isp_hdr;
613 /*
614 * Set the CSG, NSG and Transit bits based on the this PDU.
615 * The CSG already validated in login_sm_req_pdu_check().
616 * We'll clear the transit bit if we encounter any login
617 * parameters in the request that required an additional
618 * login transfer (i.e. no acceptable
619 * choices in range or we needed to change a boolean
620 * value from "Yes" to "No").
621 */
622 ict->ict_login_sm.icl_login_csg =
623 ISCSI_LOGIN_CURRENT_STAGE(lh->flags);
624 ict->ict_login_sm.icl_login_nsg =
625 ISCSI_LOGIN_NEXT_STAGE(lh->flags);
626 ict->ict_login_sm.icl_login_transit =
627 lh->flags & ISCSI_FLAG_LOGIN_TRANSIT;
628 mutex_enter(&ict->ict_login_sm.icl_mutex);
629 list_insert_tail(&ict->ict_login_sm.icl_pdu_list, pdu);
630 mutex_exit(&ict->ict_login_sm.icl_mutex);
631 if (pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) {
632 login_sm_send_ack(ict, pdu);
633 login_sm_new_state(ict, ctx, ILS_LOGIN_WAITING);
634 } else {
635 login_sm_new_state(ict, ctx, ILS_LOGIN_PROCESSING);
636 }
637 break;
638 case ILE_LOGIN_CONN_ERROR:
639 case ILE_LOGIN_ERROR:
640 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
641 break;
642 default:
643 ASSERT(0);
644 }
645 }
646
647 static void
login_sm_ffp(iscsit_conn_t * ict,login_event_ctx_t * ctx)648 login_sm_ffp(iscsit_conn_t *ict, login_event_ctx_t *ctx)
649 {
650 switch (ctx->le_ctx_event) {
651 case ILE_LOGIN_RESP_COMPLETE:
652 login_sm_new_state(ict, ctx, ILS_LOGIN_DONE);
653 break;
654 case ILE_LOGIN_CONN_ERROR:
655 case ILE_LOGIN_ERROR:
656 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
657 break;
658 default:
659 ASSERT(0);
660 }
661
662 }
663
664 /*ARGSUSED*/
665 static void
login_sm_done(iscsit_conn_t * ict,login_event_ctx_t * ctx)666 login_sm_done(iscsit_conn_t *ict, login_event_ctx_t *ctx)
667 {
668 /* Terminal state, we should get no events */
669 switch (ctx->le_ctx_event) {
670 case ILE_LOGIN_RCV:
671 /*
672 * We've already processed everything we're going to
673 * process. Drop any additional login PDU's.
674 */
675 idm_pdu_complete(ctx->le_pdu, IDM_STATUS_SUCCESS);
676 break;
677 case ILE_LOGIN_CONN_ERROR:
678 /* Don't care */
679 break;
680 default:
681 ASSERT(0);
682 }
683 }
684
685 /*ARGSUSED*/
686 static void
login_sm_error(iscsit_conn_t * ict,login_event_ctx_t * ctx)687 login_sm_error(iscsit_conn_t *ict, login_event_ctx_t *ctx)
688 {
689 switch (ctx->le_ctx_event) {
690 case ILE_LOGIN_RCV:
691 /*
692 * We've already processed everything we're going to
693 * process. Drop any additional login PDU's.
694 */
695 idm_pdu_complete(ctx->le_pdu, IDM_STATUS_SUCCESS);
696 break;
697 case ILE_LOGIN_CONN_ERROR:
698 /* Don't care */
699 break;
700 default:
701 ASSERT(0);
702 }
703 }
704
705 static void
login_sm_new_state(iscsit_conn_t * ict,login_event_ctx_t * ctx,iscsit_login_state_t new_state)706 login_sm_new_state(iscsit_conn_t *ict, login_event_ctx_t *ctx,
707 iscsit_login_state_t new_state)
708 {
709 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
710 idm_pdu_t *rpdu;
711
712 /*
713 * Validate new state
714 */
715 ASSERT(new_state != ILS_UNDEFINED);
716 ASSERT3U(new_state, <, ILS_MAX_STATE);
717
718 new_state = (new_state < ILS_MAX_STATE) ?
719 new_state : ILS_UNDEFINED;
720
721 IDM_SM_LOG(CE_NOTE, "login_sm_new_state: conn %p "
722 "%s (%d) --> %s (%d)\n", (void *)ict->ict_ic,
723 iscsit_ils_name[lsm->icl_login_state], lsm->icl_login_state,
724 iscsit_ils_name[new_state], new_state);
725
726 DTRACE_PROBE3(login__state__change,
727 iscsit_conn_t *, ict, login_event_ctx_t *, ctx,
728 iscsit_login_state_t, new_state);
729
730 mutex_enter(&lsm->icl_mutex);
731 idm_sm_audit_state_change(&lsm->icl_state_audit, SAS_ISCSIT_LOGIN,
732 (int)lsm->icl_login_state, (int)new_state);
733 lsm->icl_login_last_state = lsm->icl_login_state;
734 lsm->icl_login_state = new_state;
735 mutex_exit(&lsm->icl_mutex);
736
737 /*
738 * Tale of caution here. The use of new_state instead of using
739 * lsm->icl_login_state is deliberate (which had been used originally).
740 * Since the icl_mutex is dropped under the right circumstances
741 * the login state changes between setting the state and examining
742 * the state to proceed. No big surprise since the lock was being
743 * used in the first place to prevent just that type of change.
744 *
745 * There has been a case where network errors occurred while a client
746 * was attempting to reinstate the connection causing multiple
747 * login packets to arrive into the state machine. Those multiple
748 * packets which were processed incorrectly caused the reference
749 * count on the connection to be one higher than it should be and
750 * from then on the connection can't close correctly causing a hang.
751 *
752 * Upon examination of the core it was found that the connection
753 * audit data had calls looking like:
754 * login_sm_event_dispatch
755 * login_sm_processing
756 * login_sm_new_state
757 * That call sequence means the new state was/is ILS_LOGIN_ERROR
758 * yet the audit trail continues with a call to
759 * login_sm_send_next_response
760 * which could only occur if icl_login_state had changed. Had the
761 * design of COMSTAR taken this into account the code would
762 * originally have held the icl_mutex across the processing of the
763 * state processing. Lock order and calls which sleep prevent that
764 * from being possible. The next best solution is to use the local
765 * variable which holds the state.
766 */
767 switch (new_state) {
768 case ILS_LOGIN_WAITING:
769 /* Do nothing, waiting for more login PDU's */
770 break;
771 case ILS_LOGIN_PROCESSING:
772 /* All login PDU's received, process login request */
773 login_sm_process_request(ict);
774 break;
775 case ILS_LOGIN_RESPONDING:
776 rpdu = login_sm_build_login_response(ict);
777 login_sm_send_next_response(ict, rpdu);
778 break;
779 case ILS_LOGIN_RESPONDED:
780 /* clean up the login response idm text buffer */
781 if (lsm->icl_login_resp_itb != NULL) {
782 idm_itextbuf_free(lsm->icl_login_resp_itb);
783 lsm->icl_login_resp_itb = NULL;
784 }
785 break;
786 case ILS_LOGIN_FFP:
787 login_sm_ffp_actions(ict);
788 break;
789 case ILS_LOGIN_DONE:
790 case ILS_LOGIN_ERROR:
791 /*
792 * Flag the terminal state for the dispatcher
793 */
794 lsm->icl_login_complete = B_TRUE;
795 break;
796 case ILS_LOGIN_INIT: /* Initial state, can't return */
797 default:
798 ASSERT(0);
799 /*NOTREACHED*/
800 }
801 }
802
803 /*ARGSUSED*/
804 static void
login_sm_send_ack(iscsit_conn_t * ict,idm_pdu_t * pdu)805 login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu)
806 {
807 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
808 idm_pdu_t *lack;
809
810 /*
811 * allocate the response pdu
812 */
813 lack = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0);
814 idm_pdu_init(lack, ict->ict_ic, ict, login_resp_complete_cb);
815 lack->isp_flags |= IDM_PDU_LOGIN_TX;
816
817 /*
818 * copy the response template into the response pdu
819 */
820 bcopy(lsm->icl_login_resp_tmpl, lack->isp_hdr, sizeof (iscsi_hdr_t));
821
822 iscsit_conn_hold(ict);
823 idm_pdu_tx(lack);
824 }
825
826 /*ARGSUSED*/
827 static idm_status_t
login_sm_validate_ack(iscsit_conn_t * ict,idm_pdu_t * pdu)828 login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu)
829 {
830 iscsi_hdr_t *ihp = pdu->isp_hdr;
831 if (ihp->flags & ISCSI_FLAG_TEXT_CONTINUE) {
832 return (IDM_STATUS_FAIL);
833 }
834 if (ntoh24(ihp->dlength) != 0) {
835 return (IDM_STATUS_FAIL);
836 }
837 return (IDM_STATUS_SUCCESS);
838 }
839
840 static boolean_t
login_sm_is_last_response(idm_pdu_t * pdu)841 login_sm_is_last_response(idm_pdu_t *pdu)
842 {
843
844 if (pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) {
845 return (B_FALSE);
846 }
847 return (B_TRUE);
848 }
849
850
851 static void
login_sm_handle_initial_login(iscsit_conn_t * ict,idm_pdu_t * pdu)852 login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu)
853 {
854 iscsi_login_hdr_t *lh_req = (iscsi_login_hdr_t *)pdu->isp_hdr;
855 iscsi_login_rsp_hdr_t *lh_resp =
856 ict->ict_login_sm.icl_login_resp_tmpl;
857
858 /*
859 * First login PDU, this connection should not have a sesssion
860 * associated.
861 */
862 ASSERT(ict->ict_sess == NULL);
863
864 /*
865 * Save off TSIH and ISID for later use in finding a session
866 */
867 ict->ict_login_sm.icl_cmdsn = ntohl(lh_req->cmdsn);
868 ict->ict_login_sm.icl_tsih = ntohs(lh_req->tsid);
869 bcopy(lh_req->isid, ict->ict_login_sm.icl_isid, ISCSI_ISID_LEN);
870
871 /*
872 * We'll need the CID as well
873 */
874 ict->ict_cid = ntohs(lh_req->cid);
875
876 /*
877 * Set the CSG, NSG and Transit bits based on the first PDU
878 * in the login sequence. The CSG already validated in
879 * login_sm_req_pdu_check(). We'll clear the transit bit if
880 * we encounter any login parameters in the request that
881 * required an additional login transfer (i.e. no acceptable
882 * choices in range or we needed to change a boolean
883 * value from "Yes" to "No").
884 */
885 ict->ict_login_sm.icl_login_csg =
886 ISCSI_LOGIN_CURRENT_STAGE(lh_req->flags);
887 ict->ict_login_sm.icl_login_nsg =
888 ISCSI_LOGIN_NEXT_STAGE(lh_req->flags);
889 ict->ict_login_sm.icl_login_transit =
890 lh_req->flags & ISCSI_FLAG_LOGIN_TRANSIT;
891
892 /*
893 * Initialize header for login reject response. This will also
894 * be copied for use as a template for other login responses
895 */
896 lh_resp->opcode = ISCSI_OP_LOGIN_RSP;
897 lh_resp->max_version = ISCSIT_MAX_VERSION;
898
899 /*
900 * We already validated that we can support one of the initiator's
901 * versions in login_sm_req_pdu_check().
902 */
903 #if (ISCSIT_MAX_VERSION > 0)
904 if (ISCSIT_MAX_VERSION >= lh_req->min_version) {
905 lh_resp->active_version =
906 MIN(lh_req->max_version, ISCSIT_MAX_VERSION);
907 } else {
908 ASSERT(ISCSIT_MAX_VERSION <= lh_req->max_version);
909 lh_resp->active_version = ISCSIT_MAX_VERSION;
910 }
911 #endif
912
913 lh_resp->hlength = 0; /* No AHS */
914 bcopy(lh_req->isid, lh_resp->isid, ISCSI_ISID_LEN);
915 lh_resp->tsid = lh_req->tsid;
916 lh_resp->itt = lh_req->itt;
917
918 /*
919 * StatSn, ExpCmdSn and MaxCmdSn will be set immediately before
920 * transmission
921 */
922 }
923
924 static void
login_sm_send_next_response(iscsit_conn_t * ict,idm_pdu_t * pdu)925 login_sm_send_next_response(iscsit_conn_t *ict, idm_pdu_t *pdu)
926 {
927 iscsi_login_rsp_hdr_t *lh_resp = (iscsi_login_rsp_hdr_t *)pdu->isp_hdr;
928
929 /* Make sure this PDU is part of the login phase */
930 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0);
931
932 /*
933 * Fill in header values
934 */
935 hton24(lh_resp->dlength, pdu->isp_datalen);
936
937 /*
938 * If the login is successful, this login response will contain
939 * the next StatSN and advance the StatSN for the connection.
940 */
941 if (lh_resp->status_class == ISCSI_STATUS_CLASS_SUCCESS) {
942 ASSERT(ict->ict_sess != NULL);
943
944 if ((lh_resp->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
945 (ISCSI_LOGIN_NEXT_STAGE(lh_resp->flags) ==
946 ISCSI_FULL_FEATURE_PHASE) &&
947 !(lh_resp->flags & ISCSI_FLAG_LOGIN_CONTINUE)) {
948 iscsit_login_sm_event(ict, ILE_LOGIN_FFP, NULL);
949 }
950 if (login_sm_is_last_response(pdu) == B_TRUE) {
951 /*
952 * The last of a potentially mult-PDU response finished.
953 */
954 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_COMPLETE,
955 NULL);
956 }
957
958 iscsit_conn_hold(ict);
959 pdu->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
960 iscsit_pdu_tx(pdu);
961 } else {
962 /*
963 * If status_class != ISCSI_STATUS_CLASS_SUCCESS then
964 * StatSN is not valid and we can call idm_pdu_tx instead
965 * of iscsit_pdu_tx. This is very good thing since in
966 * some cases of login failure we may not have a session.
967 * Since iscsit_calc_rspsn grabs the session mutex while
968 * it is retrieving values for expcmdsn and maxcmdsn this
969 * would cause a panic.
970 *
971 * Since we still want a value for expcmdsn, fill in an
972 * appropriate value based on the login request before
973 * sending the response. Cmdsn/expcmdsn do not advance during
974 * login phase.
975 */
976 lh_resp->expcmdsn = htonl(ict->ict_login_sm.icl_cmdsn);
977 lh_resp->maxcmdsn = htonl(ict->ict_login_sm.icl_cmdsn + 1);
978
979 iscsit_conn_hold(ict);
980 idm_pdu_tx(pdu);
981 }
982
983 }
984
985 static void
login_sm_process_request(iscsit_conn_t * ict)986 login_sm_process_request(iscsit_conn_t *ict)
987 {
988 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
989 uint8_t error_class = 0;
990 uint8_t error_detail = 0;
991
992 /*
993 * First walk all the PDU's that make up this login request
994 * and compile all the iSCSI key-value pairs into nvlist format.
995 */
996
997 ASSERT(lsm->icl_request_nvlist == NULL);
998 /* create an nvlist for request key/value pairs */
999 if (idm_pdu_list_to_nvlist(&lsm->icl_pdu_list,
1000 &lsm->icl_request_nvlist, &error_detail) != IDM_STATUS_SUCCESS) {
1001 error_class = ISCSI_STATUS_CLASS_TARGET_ERR;
1002 SET_LOGIN_ERROR(ict, error_class, error_detail);
1003 goto request_fail;
1004 }
1005
1006 /* Allocate a new nvlist for response key/value pairs */
1007 ASSERT(lsm->icl_response_nvlist == NULL);
1008 if (nvlist_alloc(&lsm->icl_response_nvlist, NV_UNIQUE_NAME,
1009 KM_NOSLEEP) != 0) {
1010 error_class = ISCSI_STATUS_CLASS_TARGET_ERR;
1011 error_detail = ISCSI_LOGIN_STATUS_NO_RESOURCES;
1012 SET_LOGIN_ERROR(ict, error_class, error_detail);
1013 goto request_fail;
1014 }
1015
1016 /*
1017 * This would be a very good time to make sure we have
1018 * negotiated the required values for the login phase. For
1019 * example we definitely should have defined InitiatorName,
1020 * and Target name regardless of our current login phase.
1021 */
1022 if (!ict->ict_op.op_initial_params_set) {
1023 if (login_sm_validate_initial_parameters(ict) !=
1024 IDM_STATUS_SUCCESS) {
1025 goto request_fail;
1026 }
1027
1028 /*
1029 * Now setup our session association. This includes
1030 * create a new session or looking up an existing session,
1031 * and if this is not a discovery session then we will
1032 * also register this session with STMF.
1033 */
1034 if (login_sm_session_bind(ict) != IDM_STATUS_SUCCESS) {
1035 goto request_fail;
1036 }
1037
1038 if (login_sm_set_auth(ict) != IDM_STATUS_SUCCESS) {
1039 goto request_fail;
1040 }
1041
1042 /*
1043 * Prepend TargetAlias and PortalGroupTag
1044 */
1045 if (ict->ict_op.op_discovery_session == B_FALSE) {
1046 if ((lsm->icl_auth.ca_tgt_alias[0]) != '\0') {
1047 (void) iscsit_reply_string(ict,
1048 "TargetAlias",
1049 &lsm->icl_auth.ca_tgt_alias[0]);
1050 }
1051 (void) iscsit_reply_numerical(ict,
1052 "TargetPortalGroupTag",
1053 (uint64_t)lsm->icl_tpgt_tag);
1054 }
1055
1056 ict->ict_op.op_initial_params_set = B_TRUE;
1057 }
1058
1059 if (login_sm_process_nvlist(ict) != IDM_STATUS_SUCCESS) {
1060 goto request_fail;
1061 }
1062
1063 if (login_sm_check_security(ict) != IDM_STATUS_SUCCESS) {
1064 goto request_fail;
1065 }
1066
1067 /* clean up request_nvlist */
1068 if (lsm->icl_request_nvlist != NULL) {
1069 nvlist_free(lsm->icl_request_nvlist);
1070 lsm->icl_request_nvlist = NULL;
1071 }
1072
1073 /* convert any responses to textbuf form */
1074 ASSERT(lsm->icl_login_resp_itb == NULL);
1075 if (lsm->icl_response_nvlist) {
1076 lsm->icl_login_resp_itb = idm_nvlist_to_itextbuf(
1077 lsm->icl_response_nvlist);
1078 if (lsm->icl_login_resp_itb == NULL) {
1079 /* Still need to send the resp so continue */
1080 SET_LOGIN_ERROR(ict,
1081 ISCSI_STATUS_CLASS_TARGET_ERR,
1082 ISCSI_LOGIN_STATUS_NO_RESOURCES);
1083 }
1084 /* clean up response_nvlist */
1085 nvlist_free(lsm->icl_response_nvlist);
1086 lsm->icl_response_nvlist = NULL;
1087 }
1088
1089 /* tell the state machine to send the textbuf */
1090 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_READY, NULL);
1091 return;
1092
1093 request_fail:
1094
1095 /* clean up request_nvlist and response_nvlist */
1096 if (lsm->icl_request_nvlist != NULL) {
1097 nvlist_free(lsm->icl_request_nvlist);
1098 lsm->icl_request_nvlist = NULL;
1099 }
1100 if (lsm->icl_response_nvlist != NULL) {
1101 nvlist_free(lsm->icl_response_nvlist);
1102 lsm->icl_response_nvlist = NULL;
1103 }
1104 /* Make sure we already set the login error */
1105 if (ict->ict_login_sm.icl_login_resp_err_class ==
1106 ISCSI_STATUS_CLASS_SUCCESS) {
1107 SET_LOGIN_ERROR(ict,
1108 ISCSI_STATUS_CLASS_TARGET_ERR,
1109 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1110 }
1111 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_READY, NULL);
1112 }
1113
1114
1115 static void
login_sm_ffp_actions(iscsit_conn_t * ict)1116 login_sm_ffp_actions(iscsit_conn_t *ict)
1117 {
1118 iscsit_process_negotiated_values(ict);
1119 }
1120
1121 static idm_status_t
login_sm_validate_initial_parameters(iscsit_conn_t * ict)1122 login_sm_validate_initial_parameters(iscsit_conn_t *ict)
1123 {
1124 int nvrc;
1125 char *string_val;
1126 char *u8_iscsi_name;
1127 size_t u8_iscsi_name_len;
1128 uint8_t error_class = ISCSI_STATUS_CLASS_INITIATOR_ERR;
1129 uint8_t error_detail = ISCSI_LOGIN_STATUS_MISSING_FIELDS;
1130 idm_status_t status = IDM_STATUS_FAIL;
1131 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1132
1133 /*
1134 * Make sure we received the required information from the initial
1135 * login. Add these declaratives to the negotiated list and
1136 * remove them from the request list as we go. If anything fails,
1137 * the caller will clean-up the nvlists.
1138 */
1139
1140 /*
1141 * Initiator name
1142 */
1143 if ((nvrc = nvlist_lookup_string(lsm->icl_request_nvlist,
1144 "InitiatorName", &string_val)) != 0) {
1145 goto initial_params_done;
1146 }
1147
1148 u8_iscsi_name = iscsit_fold_name(string_val, &u8_iscsi_name_len);
1149 if (u8_iscsi_name == NULL)
1150 goto initial_params_done;
1151 nvrc = nvlist_add_string(lsm->icl_negotiated_values, "InitiatorName",
1152 u8_iscsi_name);
1153 kmem_free(u8_iscsi_name, u8_iscsi_name_len);
1154 if (nvrc != 0)
1155 goto initial_params_done;
1156
1157 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values,
1158 "InitiatorName", &string_val)) != 0) {
1159 goto initial_params_done;
1160 }
1161 lsm->icl_initiator_name = string_val;
1162 idm_conn_set_initiator_name(ict->ict_ic, lsm->icl_initiator_name);
1163 if ((nvrc = nvlist_remove(lsm->icl_request_nvlist,
1164 "InitiatorName", DATA_TYPE_STRING)) != 0) {
1165 goto initial_params_done;
1166 }
1167
1168 /*
1169 * Session type
1170 */
1171 ict->ict_op.op_discovery_session = B_FALSE;
1172 nvrc = nvlist_lookup_string(lsm->icl_request_nvlist,
1173 "SessionType", &string_val);
1174 if (nvrc != ENOENT && nvrc != 0) {
1175 goto initial_params_done;
1176 }
1177 if (nvrc == 0) {
1178 if (strcmp(string_val, "Discovery") == 0) {
1179 ict->ict_op.op_discovery_session = B_TRUE;
1180 } else if (strcmp(string_val, "Normal") != 0) {
1181 goto initial_params_done;
1182 }
1183 if ((nvrc = nvlist_add_string(lsm->icl_negotiated_values,
1184 "SessionType", string_val)) != 0) {
1185 goto initial_params_done;
1186 }
1187 if ((nvrc = nvlist_remove(lsm->icl_request_nvlist,
1188 "SessionType", DATA_TYPE_STRING)) != 0) {
1189 goto initial_params_done;
1190 }
1191 }
1192
1193 /*
1194 * Must have either TargetName or SessionType==Discovery
1195 */
1196 lsm->icl_target_name = NULL;
1197 nvrc = nvlist_lookup_string(lsm->icl_request_nvlist,
1198 "TargetName", &string_val);
1199 if (nvrc != ENOENT && nvrc != 0) {
1200 goto initial_params_done;
1201 }
1202 if (nvrc == 0) {
1203 u8_iscsi_name = iscsit_fold_name(string_val,
1204 &u8_iscsi_name_len);
1205 if (u8_iscsi_name == NULL)
1206 goto initial_params_done;
1207 nvrc = nvlist_add_string(lsm->icl_negotiated_values,
1208 "TargetName", u8_iscsi_name);
1209 kmem_free(u8_iscsi_name, u8_iscsi_name_len);
1210 if (nvrc != 0)
1211 goto initial_params_done;
1212 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values,
1213 "TargetName", &string_val)) != 0) {
1214 goto initial_params_done;
1215 }
1216 lsm->icl_target_name = string_val;
1217 idm_conn_set_target_name(ict->ict_ic, lsm->icl_target_name);
1218 if ((nvrc = nvlist_remove(lsm->icl_request_nvlist,
1219 "TargetName", DATA_TYPE_STRING)) != 0) {
1220 goto initial_params_done;
1221 }
1222 } else if (ict->ict_op.op_discovery_session == B_FALSE) {
1223 /*
1224 * Missing target name
1225 */
1226 goto initial_params_done;
1227 }
1228
1229 idm_conn_set_isid(ict->ict_ic, lsm->icl_isid);
1230 (void) snprintf(ict->ict_ic->ic_tsih, ISCSI_MAX_TSIH_LEN + 1, "0x%04x",
1231 lsm->icl_tsih);
1232
1233 IDM_SM_LOG(CE_NOTE, "conn %p: initiator=%s", (void *)ict->ict_ic,
1234 (lsm->icl_initiator_name == NULL) ? "N/A" :
1235 lsm->icl_initiator_name);
1236 IDM_SM_LOG(CE_NOTE, "conn %p: target=%s", (void *)ict->ict_ic,
1237 (lsm->icl_target_name == NULL) ? "N/A" :
1238 lsm->icl_target_name);
1239 IDM_SM_LOG(CE_NOTE, "conn %p: sessiontype=%s", (void *)ict->ict_ic,
1240 ict->ict_op.op_discovery_session ? "Discovery" : "Normal");
1241
1242 /* Sucess */
1243 status = IDM_STATUS_SUCCESS;
1244 error_class = ISCSI_STATUS_CLASS_SUCCESS;
1245 error_detail = ISCSI_LOGIN_STATUS_ACCEPT;
1246
1247 initial_params_done:
1248 SET_LOGIN_ERROR(ict, error_class, error_detail);
1249 return (status);
1250 }
1251
1252
1253 /*
1254 * login_sm_session_bind
1255 *
1256 * This function looks at the data from the initial login request
1257 * of a new connection and either looks up and existing session,
1258 * creates a new session, or returns an error. RFC3720 section 5.3.1
1259 * defines these rules:
1260 *
1261 * +------------------------------------------------------------------+
1262 * |ISID | TSIH | CID | Target action |
1263 * +------------------------------------------------------------------+
1264 * |new | non-zero | any | fail the login |
1265 * | | | | ("session does not exist") |
1266 * +------------------------------------------------------------------+
1267 * |new | zero | any | instantiate a new session |
1268 * +------------------------------------------------------------------+
1269 * |existing | zero | any | do session reinstatement |
1270 * | | | | (see section 5.3.5) |
1271 * +------------------------------------------------------------------+
1272 * |existing | non-zero | new | add a new connection to |
1273 * | | existing | | the session |
1274 * +------------------------------------------------------------------+
1275 * |existing | non-zero |existing| do connection reinstatement|
1276 * | | existing | | (see section 5.3.4) |
1277 * +------------------------------------------------------------------+
1278 * |existing | non-zero | any | fail the login |
1279 * | | new | | ("session does not exist") |
1280 * +------------------------------------------------------------------+
1281 *
1282 */
1283
1284 /*
1285 * Map an <ipv6,port> address to an <ipv4,port> address if possible.
1286 * Returns:
1287 * 1 - success
1288 * 0 - address not mapable
1289 */
1290
1291 int
iscsit_is_v4_mapped(struct sockaddr_storage * sa,struct sockaddr_storage * v4sa)1292 iscsit_is_v4_mapped(struct sockaddr_storage *sa, struct sockaddr_storage *v4sa)
1293 {
1294 struct sockaddr_in *sin;
1295 struct in_addr *in;
1296 struct sockaddr_in6 *sin6;
1297 struct in6_addr *in6;
1298 int ret = 0;
1299
1300 sin6 = (struct sockaddr_in6 *)sa;
1301 in6 = &sin6->sin6_addr;
1302 if ((sa->ss_family == AF_INET6) &&
1303 (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6))) {
1304 sin = (struct sockaddr_in *)v4sa;
1305 in = &sin->sin_addr;
1306 v4sa->ss_family = AF_INET;
1307 sin->sin_port = sin6->sin6_port;
1308 IN6_V4MAPPED_TO_INADDR(in6, in);
1309 ret = 1;
1310 }
1311 return (ret);
1312 }
1313
1314 static idm_status_t
login_sm_session_bind(iscsit_conn_t * ict)1315 login_sm_session_bind(iscsit_conn_t *ict)
1316 {
1317 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1318 iscsit_tgt_t *tgt = NULL;
1319 iscsit_tpgt_t *tpgt = NULL;
1320 iscsit_portal_t *portal = NULL;
1321 iscsit_sess_t *existing_sess = NULL;
1322 iscsit_sess_t *new_sess = NULL;
1323 iscsit_conn_t *existing_ict = NULL;
1324 uint8_t error_class;
1325 uint8_t error_detail;
1326
1327 /*
1328 * The multi-threaded execution of binding login sessions to target
1329 * introduced race conditions in the session creation/binding and
1330 * allowed duplicate sessions to tbe created. The addition of the
1331 * global mutex login_sm_session_mutex makes this function single
1332 * threaded to avoid such race conditions. Although this causes
1333 * a small portion of the login to be serialized, it is unlikely
1334 * that there would be numerous simultaneous logins to become a
1335 * performance issue.
1336 */
1337 mutex_enter(&login_sm_session_mutex);
1338
1339 /*
1340 * Look up target and then check if there are sessions or connections
1341 * that match this request (see below). Any holds taken on objects
1342 * must be released at the end of the function (let's keep things
1343 * simple).
1344 *
1345 * If target name is set then we should have a corresponding target
1346 * context configured.
1347 */
1348 if (lsm->icl_target_name != NULL) {
1349 /*
1350 * iscsit_tgt_lookup implicitly takes a ref on the target
1351 */
1352 ISCSIT_GLOBAL_LOCK(RW_READER);
1353 tgt = iscsit_tgt_lookup_locked(lsm->icl_target_name);
1354 if (tgt == NULL) {
1355 ISCSIT_GLOBAL_UNLOCK();
1356 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1357 ISCSI_LOGIN_STATUS_TGT_NOT_FOUND);
1358 goto session_bind_error;
1359 } else {
1360 mutex_enter(&tgt->target_mutex);
1361 tpgt = avl_first(&tgt->target_tpgt_list);
1362
1363 if (IS_DEFAULT_TPGT(tpgt)) {
1364 lsm->icl_tpgt_tag = ISCSIT_DEFAULT_TPGT;
1365 } else {
1366 /*
1367 * Find the portal group tag for the
1368 * login response.
1369 */
1370 struct sockaddr_storage v4sa, *sa;
1371
1372 sa = &ict->ict_ic->ic_laddr;
1373 portal = iscsit_tgt_lookup_portal(tgt,
1374 sa, &tpgt);
1375 if (portal == NULL &&
1376 iscsit_is_v4_mapped(sa, &v4sa)) {
1377 /*
1378 * Try again if the local address
1379 * was v6 mappable to v4.
1380 */
1381 portal = iscsit_tgt_lookup_portal(tgt,
1382 &v4sa, &tpgt);
1383
1384 }
1385 if (portal == NULL) {
1386 /*
1387 * Initiator came in on wrong address
1388 */
1389 SET_LOGIN_ERROR(ict,
1390 ISCSI_STATUS_CLASS_INITIATOR_ERR,
1391 ISCSI_LOGIN_STATUS_TGT_NOT_FOUND);
1392 mutex_exit(&tgt->target_mutex);
1393 ISCSIT_GLOBAL_UNLOCK();
1394 goto session_bind_error;
1395 }
1396
1397 /*
1398 * Need to release holds on the portal and
1399 * tpgt after processing is complete.
1400 */
1401 lsm->icl_tpgt_tag = tpgt->tpgt_tag;
1402 iscsit_portal_rele(portal);
1403 iscsit_tpgt_rele(tpgt);
1404 }
1405
1406 mutex_enter(&iscsit_global.global_state_mutex);
1407 if ((tgt->target_state != TS_STMF_ONLINE) ||
1408 ((iscsit_global.global_svc_state != ISE_ENABLED) &&
1409 ((iscsit_global.global_svc_state != ISE_BUSY)))) {
1410 mutex_exit(&iscsit_global.global_state_mutex);
1411 SET_LOGIN_ERROR(ict,
1412 ISCSI_STATUS_CLASS_TARGET_ERR,
1413 ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
1414 mutex_exit(&tgt->target_mutex);
1415 ISCSIT_GLOBAL_UNLOCK();
1416 goto session_bind_error;
1417 }
1418 mutex_exit(&iscsit_global.global_state_mutex);
1419 mutex_exit(&tgt->target_mutex);
1420 ISCSIT_GLOBAL_UNLOCK();
1421 }
1422 }
1423
1424 ASSERT((tgt != NULL) || (ict->ict_op.op_discovery_session == B_TRUE));
1425
1426 /*
1427 * Check if there is an existing session matching this ISID. If
1428 * tgt == NULL then we'll look for the session on the global list
1429 * of discovery session. If we find a session then the ISID
1430 * exists.
1431 */
1432 existing_sess = iscsit_tgt_lookup_sess(tgt, lsm->icl_initiator_name,
1433 lsm->icl_isid, lsm->icl_tsih, lsm->icl_tpgt_tag);
1434 if (existing_sess != NULL) {
1435 existing_ict = iscsit_sess_lookup_conn(existing_sess,
1436 ict->ict_cid);
1437 }
1438
1439 /*
1440 * If this is a discovery session, make sure it has appropriate
1441 * parameters.
1442 */
1443 if ((ict->ict_op.op_discovery_session == B_TRUE) &&
1444 ((lsm->icl_tsih != ISCSI_UNSPEC_TSIH) || (existing_sess != NULL))) {
1445 /* XXX Do we need to check for existing ISID (sess != NULL)? */
1446 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1447 ISCSI_LOGIN_STATUS_INVALID_REQUEST);
1448 goto session_bind_error;
1449 }
1450
1451 /*
1452 * Check the two error conditions from the table.
1453 *
1454 * ISID=new, TSIH=non-zero
1455 */
1456 if ((existing_sess == NULL) && (lsm->icl_tsih != ISCSI_UNSPEC_TSIH)) {
1457 /* fail the login */
1458 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1459 ISCSI_LOGIN_STATUS_NO_SESSION);
1460 goto session_bind_error;
1461 }
1462
1463 /* ISID=existing, TSIH=non-zero new */
1464 if ((existing_sess != NULL) && (lsm->icl_tsih != 0) &&
1465 (existing_sess->ist_tsih != lsm->icl_tsih)) {
1466 /* fail the login */
1467 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1468 ISCSI_LOGIN_STATUS_NO_SESSION);
1469 goto session_bind_error;
1470 }
1471
1472 /*
1473 * Handle the remaining table cases in order
1474 */
1475 if (existing_sess == NULL) {
1476 /* Should have caught this above */
1477 ASSERT(lsm->icl_tsih == ISCSI_UNSPEC_TSIH);
1478 /*
1479 * ISID=new, TSIH=zero --> instantiate a new session
1480 */
1481 new_sess = iscsit_sess_create(tgt, ict, lsm->icl_cmdsn,
1482 lsm->icl_isid, lsm->icl_tpgt_tag, lsm->icl_initiator_name,
1483 lsm->icl_target_name, &error_class, &error_detail);
1484 ASSERT(new_sess != NULL);
1485
1486 /* Session create may have failed even if it returned a value */
1487 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) {
1488 SET_LOGIN_ERROR(ict, error_class, error_detail);
1489 goto session_bind_error;
1490 }
1491
1492 /*
1493 * If we don't already have an STMF session and this is not
1494 * a discovery session then we need to allocate and register
1495 * one.
1496 */
1497 if (!ict->ict_op.op_discovery_session) {
1498 if (login_sm_session_register(ict) !=
1499 IDM_STATUS_SUCCESS) {
1500 /* login_sm_session_register sets error codes */
1501 goto session_bind_error;
1502 }
1503 }
1504
1505 } else {
1506 if (lsm->icl_tsih == ISCSI_UNSPEC_TSIH) {
1507 /*
1508 * ISID=existing, TSIH=zero --> Session reinstatement
1509 */
1510 new_sess = iscsit_sess_reinstate(tgt, existing_sess,
1511 ict, &error_class, &error_detail);
1512 ASSERT(new_sess != NULL);
1513
1514 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) {
1515 SET_LOGIN_ERROR(ict, error_class, error_detail);
1516 goto session_bind_error;
1517 }
1518
1519 /*
1520 * If we don't already have an STMF session and this is
1521 * not a discovery session then we need to allocate and
1522 * register one.
1523 */
1524 if (!ict->ict_op.op_discovery_session) {
1525 if (login_sm_session_register(ict) !=
1526 IDM_STATUS_SUCCESS) {
1527 /*
1528 * login_sm_session_register sets
1529 * error codes
1530 */
1531 goto session_bind_error;
1532 }
1533 }
1534 } else {
1535 /*
1536 * The following code covers these two cases:
1537 * ISID=existing, TSIH=non-zero existing, CID=new
1538 * --> add new connection to MC/S session
1539 * ISID=existing, TSIH=non-zero existing, CID=existing
1540 * --> do connection reinstatement
1541 *
1542 * Session continuation uses this path as well
1543 */
1544 cmn_err(CE_NOTE, "login_sm_session_bind: add new "
1545 "conn/sess continue");
1546 if (existing_ict != NULL) {
1547 /*
1548 * ISID=existing, TSIH=non-zero existing,
1549 * CID=existing --> do connection reinstatement
1550 */
1551 if (iscsit_conn_reinstate(existing_ict, ict) !=
1552 IDM_STATUS_SUCCESS) {
1553 /*
1554 * Most likely this means the connection
1555 * the initiator is trying to reinstate
1556 * is not in an acceptable state.
1557 */
1558 SET_LOGIN_ERROR(ict,
1559 ISCSI_STATUS_CLASS_INITIATOR_ERR,
1560 ISCSI_LOGIN_STATUS_INIT_ERR);
1561 goto session_bind_error;
1562 }
1563 }
1564
1565 iscsit_sess_sm_event(existing_sess, SE_CONN_IN_LOGIN,
1566 ict);
1567 }
1568 }
1569
1570 if (tgt != NULL)
1571 iscsit_tgt_rele(tgt);
1572 if (existing_sess != NULL)
1573 iscsit_sess_rele(existing_sess);
1574 if (existing_ict != NULL)
1575 iscsit_conn_rele(existing_ict);
1576
1577 mutex_exit(&login_sm_session_mutex);
1578 return (IDM_STATUS_SUCCESS);
1579
1580 session_bind_error:
1581 if (tgt != NULL)
1582 iscsit_tgt_rele(tgt);
1583 if (existing_sess != NULL)
1584 iscsit_sess_rele(existing_sess);
1585 if (existing_ict != NULL)
1586 iscsit_conn_rele(existing_ict);
1587
1588 /*
1589 * If session bind fails we will fail the login but don't destroy
1590 * the session until later.
1591 */
1592 mutex_exit(&login_sm_session_mutex);
1593 return (IDM_STATUS_FAIL);
1594 }
1595
1596
1597 static idm_status_t
login_sm_set_auth(iscsit_conn_t * ict)1598 login_sm_set_auth(iscsit_conn_t *ict)
1599 {
1600 idm_status_t idmrc = IDM_STATUS_SUCCESS;
1601 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1602 iscsit_ini_t *ini;
1603 iscsit_tgt_t *tgt;
1604 char *auth = "";
1605 char *radiusserver = "";
1606 char *radiussecret = "";
1607 char *chapuser = "";
1608 char *chapsecret = "";
1609 char *targetchapuser = "";
1610 char *targetchapsecret = "";
1611 char *targetalias = "";
1612 int i;
1613
1614 ISCSIT_GLOBAL_LOCK(RW_READER);
1615
1616 /*
1617 * Set authentication method to none for discovery session.
1618 */
1619 if (ict->ict_op.op_discovery_session == B_TRUE) {
1620 lsm->icl_auth.ca_method_valid_list[0] = AM_NONE;
1621 ISCSIT_GLOBAL_UNLOCK();
1622 return (idmrc);
1623 }
1624
1625 /*
1626 * Get all the authentication parameters we need -- since we hold
1627 * the global config lock we guarantee that the parameters will
1628 * be consistent with each other.
1629 */
1630 (void) nvlist_lookup_string(iscsit_global.global_props,
1631 PROP_AUTH, &auth);
1632 (void) nvlist_lookup_string(iscsit_global.global_props,
1633 PROP_RADIUS_SERVER, &radiusserver);
1634 (void) nvlist_lookup_string(iscsit_global.global_props,
1635 PROP_RADIUS_SECRET, &radiussecret);
1636
1637 ini = iscsit_ini_lookup_locked(lsm->icl_initiator_name);
1638 if (ini != NULL) {
1639 /* Get Initiator CHAP parameters */
1640 (void) nvlist_lookup_string(ini->ini_props, PROP_CHAP_USER,
1641 &chapuser);
1642 (void) nvlist_lookup_string(ini->ini_props, PROP_CHAP_SECRET,
1643 &chapsecret);
1644 }
1645
1646 tgt = ict->ict_sess->ist_tgt;
1647 if (tgt != NULL) {
1648 /* See if we have a target-specific authentication setting */
1649 (void) nvlist_lookup_string(tgt->target_props, PROP_AUTH,
1650 &auth);
1651 /* Get target CHAP parameters */
1652 (void) nvlist_lookup_string(tgt->target_props,
1653 PROP_TARGET_CHAP_USER, &targetchapuser);
1654 (void) nvlist_lookup_string(tgt->target_props,
1655 PROP_TARGET_CHAP_SECRET, &targetchapsecret);
1656 /* Get alias */
1657 (void) nvlist_lookup_string(tgt->target_props,
1658 PROP_ALIAS, &targetalias);
1659 }
1660
1661 /* Set authentication method */
1662 i = 0;
1663 if (strcmp(auth, PA_AUTH_RADIUS) == 0) {
1664 /* CHAP authentication using RADIUS server */
1665 lsm->icl_auth.ca_method_valid_list[i++] = AM_CHAP;
1666 lsm->icl_auth.ca_use_radius = B_TRUE;
1667 } else if (strcmp(auth, PA_AUTH_CHAP) == 0) {
1668 /* Local CHAP authentication */
1669 lsm->icl_auth.ca_method_valid_list[i++] = AM_CHAP;
1670 lsm->icl_auth.ca_use_radius = B_FALSE;
1671 } else if ((strcmp(auth, PA_AUTH_NONE) == 0) ||
1672 (strcmp(auth, "") == 0)) {
1673 /* No authentication */
1674 lsm->icl_auth.ca_method_valid_list[i++] = AM_NONE;
1675 }
1676
1677 /*
1678 * If initiator/target CHAP username is not set then use the
1679 * node name. If lsm->icl_target_name == NULL then this is
1680 * a discovery session so we don't need to work about the target.
1681 */
1682 if (strcmp(chapuser, "") == 0) {
1683 (void) strlcpy(lsm->icl_auth.ca_ini_chapuser,
1684 lsm->icl_initiator_name,
1685 min(iscsitAuthStringMaxLength, MAX_ISCSI_NODENAMELEN));
1686 } else {
1687 (void) strlcpy(lsm->icl_auth.ca_ini_chapuser, chapuser,
1688 iscsitAuthStringMaxLength);
1689 }
1690 if ((lsm->icl_target_name != NULL) &&
1691 (strcmp(targetchapuser, "") == 0)) {
1692 (void) strlcpy(lsm->icl_auth.ca_tgt_chapuser,
1693 lsm->icl_target_name,
1694 min(iscsitAuthStringMaxLength, MAX_ISCSI_NODENAMELEN));
1695 } else {
1696 (void) strlcpy(lsm->icl_auth.ca_tgt_chapuser,
1697 targetchapuser, iscsitAuthStringMaxLength);
1698 }
1699
1700 /*
1701 * Secrets are stored in base64-encoded format so we need to
1702 * decode them into binary form
1703 */
1704 if (strcmp(chapsecret, "") == 0) {
1705 lsm->icl_auth.ca_ini_chapsecretlen = 0;
1706 } else {
1707 if (iscsi_base64_str_to_binary(chapsecret,
1708 strnlen(chapsecret, iscsitAuthStringMaxLength),
1709 lsm->icl_auth.ca_ini_chapsecret, iscsitAuthStringMaxLength,
1710 &lsm->icl_auth.ca_ini_chapsecretlen) != 0) {
1711 cmn_err(CE_WARN, "Corrupted CHAP secret"
1712 " for initiator %s", lsm->icl_initiator_name);
1713 lsm->icl_auth.ca_ini_chapsecretlen = 0;
1714 }
1715 }
1716 if (strcmp(targetchapsecret, "") == 0) {
1717 lsm->icl_auth.ca_tgt_chapsecretlen = 0;
1718 } else {
1719 if (iscsi_base64_str_to_binary(targetchapsecret,
1720 strnlen(targetchapsecret, iscsitAuthStringMaxLength),
1721 lsm->icl_auth.ca_tgt_chapsecret, iscsitAuthStringMaxLength,
1722 &lsm->icl_auth.ca_tgt_chapsecretlen) != 0) {
1723 cmn_err(CE_WARN, "Corrupted CHAP secret"
1724 " for target %s", lsm->icl_target_name);
1725 lsm->icl_auth.ca_tgt_chapsecretlen = 0;
1726 }
1727 }
1728 if (strcmp(radiussecret, "") == 0) {
1729 lsm->icl_auth.ca_radius_secretlen = 0;
1730 } else {
1731 if (iscsi_base64_str_to_binary(radiussecret,
1732 strnlen(radiussecret, iscsitAuthStringMaxLength),
1733 lsm->icl_auth.ca_radius_secret, iscsitAuthStringMaxLength,
1734 &lsm->icl_auth.ca_radius_secretlen) != 0) {
1735 cmn_err(CE_WARN, "Corrupted RADIUS secret");
1736 lsm->icl_auth.ca_radius_secretlen = 0;
1737 }
1738 }
1739
1740 /*
1741 * Set alias
1742 */
1743 (void) strlcpy(lsm->icl_auth.ca_tgt_alias, targetalias,
1744 MAX_ISCSI_NODENAMELEN);
1745
1746 /*
1747 * Now that authentication parameters are setup, validate the parameters
1748 * against the authentication mode
1749 * Decode RADIUS server value int lsm->icl_auth.ca_radius_server
1750 */
1751 if ((strcmp(auth, PA_AUTH_RADIUS) == 0) &&
1752 ((lsm->icl_auth.ca_radius_secretlen == 0) ||
1753 (strcmp(radiusserver, "") == 0) ||
1754 it_common_convert_sa(radiusserver,
1755 &lsm->icl_auth.ca_radius_server,
1756 DEFAULT_RADIUS_PORT) == NULL)) {
1757 cmn_err(CE_WARN, "RADIUS authentication selected "
1758 "for target %s but RADIUS parameters are not "
1759 "configured.", lsm->icl_target_name);
1760 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1761 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1762 idmrc = IDM_STATUS_FAIL;
1763 } else if ((strcmp(auth, PA_AUTH_CHAP) == 0) &&
1764 (lsm->icl_auth.ca_ini_chapsecretlen == 0)) {
1765 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1766 ISCSI_LOGIN_STATUS_AUTH_FAILED);
1767 idmrc = IDM_STATUS_FAIL;
1768 }
1769
1770 ISCSIT_GLOBAL_UNLOCK();
1771
1772 return (idmrc);
1773 }
1774
1775
1776 static idm_status_t
login_sm_session_register(iscsit_conn_t * ict)1777 login_sm_session_register(iscsit_conn_t *ict)
1778 {
1779 iscsit_sess_t *ist = ict->ict_sess;
1780 stmf_scsi_session_t *ss;
1781 iscsi_transport_id_t *iscsi_tptid;
1782 uint16_t ident_len, adn_len, tptid_sz;
1783 char prop_buf[KSTAT_STRLEN + 1];
1784 char peer_buf[IDM_SA_NTOP_BUFSIZ];
1785
1786 /*
1787 * Hold target mutex until we have finished registering with STMF
1788 */
1789 mutex_enter(&ist->ist_tgt->target_mutex);
1790 if (ist->ist_tgt->target_state != TS_STMF_ONLINE) {
1791 mutex_exit(&ist->ist_tgt->target_mutex);
1792 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
1793 ISCSI_LOGIN_STATUS_TGT_REMOVED);
1794 return (IDM_STATUS_FAIL);
1795 }
1796
1797 ss = stmf_alloc(STMF_STRUCT_SCSI_SESSION, 0,
1798 0);
1799 if (ss == NULL) {
1800 mutex_exit(&ist->ist_tgt->target_mutex);
1801 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1802 ISCSI_LOGIN_STATUS_NO_RESOURCES);
1803 return (IDM_STATUS_FAIL);
1804 }
1805
1806 ident_len = strlen(ist->ist_initiator_name) + 1;
1807 ss->ss_rport_id = kmem_zalloc(sizeof (scsi_devid_desc_t) +
1808 ident_len, KM_SLEEP);
1809 (void) strcpy((char *)ss->ss_rport_id->ident, ist->ist_initiator_name);
1810 ss->ss_rport_id->ident_length = ident_len - 1;
1811 ss->ss_rport_id->protocol_id = PROTOCOL_iSCSI;
1812 ss->ss_rport_id->piv = 1;
1813 ss->ss_rport_id->code_set = CODE_SET_ASCII;
1814 ss->ss_rport_id->association = ID_IS_TARGET_PORT;
1815
1816 /* adn_len should be 4 byte aligned, SPC3 rev 23, section 7.54.6 */
1817 adn_len = (ident_len + 3) & ~ 3;
1818 tptid_sz = sizeof (iscsi_transport_id_t) - 1 + adn_len;
1819 ss->ss_rport = stmf_remote_port_alloc(tptid_sz);
1820 ss->ss_rport->rport_tptid->protocol_id = PROTOCOL_iSCSI;
1821 ss->ss_rport->rport_tptid->format_code = 0;
1822 iscsi_tptid = (iscsi_transport_id_t *)ss->ss_rport->rport_tptid;
1823 SCSI_WRITE16(&iscsi_tptid->add_len, adn_len);
1824 (void) strlcpy((char *)iscsi_tptid->iscsi_name,
1825 ist->ist_initiator_name, ident_len);
1826
1827 ss->ss_lport = ist->ist_lport;
1828
1829 if (stmf_register_scsi_session(ict->ict_sess->ist_lport, ss) !=
1830 STMF_SUCCESS) {
1831 mutex_exit(&ist->ist_tgt->target_mutex);
1832 kmem_free(ss->ss_rport_id,
1833 sizeof (scsi_devid_desc_t) +
1834 strlen(ist->ist_initiator_name) + 1);
1835 stmf_remote_port_free(ss->ss_rport);
1836 stmf_free(ss);
1837 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_TARGET_ERR,
1838 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1839 return (IDM_STATUS_FAIL);
1840 }
1841
1842 ss->ss_port_private = ict->ict_sess;
1843 ict->ict_sess->ist_stmf_sess = ss;
1844 mutex_exit(&ist->ist_tgt->target_mutex);
1845 (void) snprintf(prop_buf, sizeof (prop_buf), "peername_%"PRIxPTR"",
1846 (uintptr_t)ict->ict_sess);
1847 (void) idm_sa_ntop(&ict->ict_ic->ic_raddr, peer_buf,
1848 sizeof (peer_buf));
1849 (void) stmf_add_rport_info(ss, prop_buf, peer_buf);
1850
1851 return (IDM_STATUS_SUCCESS);
1852 }
1853
1854
1855 static idm_status_t
login_sm_req_pdu_check(iscsit_conn_t * ict,idm_pdu_t * pdu)1856 login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu)
1857 {
1858 uint8_t csg_req;
1859 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1860 iscsi_login_hdr_t *lh = (iscsi_login_hdr_t *)pdu->isp_hdr;
1861 iscsi_login_rsp_hdr_t *lh_resp = lsm->icl_login_resp_tmpl;
1862
1863 /*
1864 * Check CSG
1865 */
1866 csg_req = ISCSI_LOGIN_CURRENT_STAGE(lh->flags);
1867 switch (csg_req) {
1868 case ISCSI_SECURITY_NEGOTIATION_STAGE:
1869 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
1870 if ((csg_req != lsm->icl_login_csg) &&
1871 (lsm->icl_login_state != ILS_LOGIN_INIT)) {
1872 /*
1873 * Inappropriate CSG change. Initiator can only
1874 * change CSG after we've responded with the
1875 * transit bit set. If we had responded with
1876 * a CSG change previous we would have updated
1877 * our copy of CSG.
1878 *
1879 * The exception is when we are in ILS_LOGIN_INIT
1880 * state since we haven't determined our initial
1881 * CSG value yet.
1882 */
1883 goto pdu_check_fail;
1884 }
1885 break;
1886 case ISCSI_FULL_FEATURE_PHASE:
1887 default:
1888 goto pdu_check_fail;
1889 }
1890
1891 /*
1892 * If this is the first login PDU for a new connection then
1893 * the session will be NULL.
1894 */
1895 if (ict->ict_sess != NULL) {
1896 /*
1897 * We've already created a session on a previous PDU. Make
1898 * sure this PDU is consistent with what we've already seen
1899 */
1900 if ((ict->ict_cid != ntohs(lh->cid)) ||
1901 (bcmp(ict->ict_sess->ist_isid, lh->isid,
1902 ISCSI_ISID_LEN) != 0)) {
1903 goto pdu_check_fail;
1904 }
1905 }
1906
1907 /*
1908 * Make sure we are compatible with the version range
1909 */
1910 #if (ISCSIT_MAX_VERSION > 0)
1911 if ((lh->min_version > ISCSIT_MAX_VERSION) ||
1912 (lh->max_version < ISCSIT_MIN_VERSION)) {
1913 goto pdu_check_fail;
1914 }
1915 #endif
1916
1917 /*
1918 * Just in case the initiator changes things up on us along the way
1919 * check against our active_version -- we can't change the active
1920 * version and the initiator is not *supposed* to change its
1921 * min_version and max_version values so this should never happen.
1922 * Of course we only do this if the response header template has
1923 * been built.
1924 */
1925 if ((lh_resp->opcode == ISCSI_OP_LOGIN_RSP) && /* header valid */
1926 ((lh->min_version > lh_resp->active_version) ||
1927 (lh->max_version < lh_resp->active_version))) {
1928 goto pdu_check_fail;
1929 }
1930
1931 return (IDM_STATUS_SUCCESS);
1932
1933 pdu_check_fail:
1934 return (IDM_STATUS_FAIL);
1935 }
1936
1937 static idm_status_t
login_sm_process_nvlist(iscsit_conn_t * ict)1938 login_sm_process_nvlist(iscsit_conn_t *ict)
1939 {
1940 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1941 char *nvp_name;
1942 nvpair_t *nvp;
1943 nvpair_t *next_nvp;
1944 nvpair_t *negotiated_nvp;
1945 kv_status_t kvrc;
1946 uint8_t error_class;
1947 uint8_t error_detail;
1948 idm_status_t idm_status;
1949
1950 error_class = ISCSI_STATUS_CLASS_SUCCESS;
1951 error_detail = ISCSI_LOGIN_STATUS_ACCEPT;
1952
1953 /* First, request that the transport process the list */
1954 kvrc = idm_negotiate_key_values(ict->ict_ic, lsm->icl_request_nvlist,
1955 lsm->icl_response_nvlist, lsm->icl_negotiated_values);
1956 idm_kvstat_to_error(kvrc, &error_class, &error_detail);
1957 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) {
1958 SET_LOGIN_ERROR(ict, error_class, error_detail);
1959 idm_status = IDM_STATUS_FAIL;
1960 return (idm_status);
1961 }
1962
1963 /* Ensure we clear transit bit if the transport layer has countered */
1964 if (kvrc == KV_HANDLED_NO_TRANSIT) {
1965 lsm->icl_login_transit = B_FALSE;
1966 }
1967
1968 /* Prepend the declarative params */
1969 if (!ict->ict_op.op_declarative_params_set &&
1970 lsm->icl_login_csg == ISCSI_OP_PARMS_NEGOTIATION_STAGE) {
1971 if (iscsit_add_declarative_keys(ict) != IDM_STATUS_SUCCESS) {
1972 idm_status = IDM_STATUS_FAIL;
1973 return (idm_status);
1974 }
1975 ict->ict_op.op_declarative_params_set = B_TRUE;
1976 }
1977
1978 /* Now, move on and process the rest of the pairs */
1979 nvp = nvlist_next_nvpair(lsm->icl_request_nvlist, NULL);
1980 while (nvp != NULL) {
1981 next_nvp = nvlist_next_nvpair(lsm->icl_request_nvlist, nvp);
1982 nvp_name = nvpair_name(nvp);
1983 /*
1984 * If we've already agreed upon a value then make sure this
1985 * is not attempting to change that value. From RFC3270
1986 * section 5.3:
1987 *
1988 * "Neither the initiator nor the target should attempt to
1989 * declare or negotiate a parameter more than once during
1990 * login except for responses to specific keys that
1991 * explicitly allow repeated key declarations (e.g.,
1992 * TargetAddress). An attempt to renegotiate/redeclare
1993 * parameters not specifically allowed MUST be detected
1994 * by the initiator and target. If such an attempt is
1995 * detected by the target, the target MUST respond
1996 * with Login reject (initiator error); ..."
1997 */
1998 if (nvlist_lookup_nvpair(lsm->icl_negotiated_values,
1999 nvp_name, &negotiated_nvp) == 0) {
2000 kvrc = KV_HANDLED;
2001 } else {
2002 kvrc = iscsit_handle_key(ict, nvp, nvp_name);
2003 }
2004
2005 idm_kvstat_to_error(kvrc, &error_class, &error_detail);
2006 if (error_class != ISCSI_STATUS_CLASS_SUCCESS) {
2007 break;
2008 }
2009
2010 nvp = next_nvp;
2011 }
2012
2013 if (error_class == ISCSI_STATUS_CLASS_SUCCESS) {
2014 idm_status = IDM_STATUS_SUCCESS;
2015 } else {
2016 /* supply login class/detail for login errors */
2017 SET_LOGIN_ERROR(ict, error_class, error_detail);
2018 idm_status = IDM_STATUS_FAIL;
2019 }
2020
2021 return (idm_status);
2022 }
2023
2024 static idm_status_t
login_sm_check_security(iscsit_conn_t * ict)2025 login_sm_check_security(iscsit_conn_t *ict)
2026 {
2027 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2028 conn_auth_t *auth = &lsm->icl_auth;
2029 iscsit_auth_method_t *am_list = &auth->ca_method_valid_list[0];
2030 kv_status_t kvrc;
2031 uint8_t error_class;
2032 uint8_t error_detail;
2033 idm_status_t idm_status;
2034
2035 error_class = ISCSI_STATUS_CLASS_SUCCESS;
2036 error_detail = ISCSI_LOGIN_STATUS_ACCEPT;
2037
2038 /* Check authentication status. */
2039 if (lsm->icl_login_csg == ISCSI_SECURITY_NEGOTIATION_STAGE) {
2040 /*
2041 * We should have some authentication key/value pair(s)
2042 * received from initiator and the authentication phase
2043 * has been shifted when the key/value pair(s) are being
2044 * handled in the previous call iscsit_handle_security_key.
2045 * Now it turns to target to check the authentication phase
2046 * and shift it after taking some authentication action.
2047 */
2048 kvrc = iscsit_reply_security_key(ict);
2049 idm_kvstat_to_error(kvrc, &error_class, &error_detail);
2050 } else if (!ict->ict_login_sm.icl_auth_pass) {
2051 /*
2052 * Check to see if the target allows initiators to bypass the
2053 * security check. If the target is configured to require
2054 * authentication, we reject the connection.
2055 */
2056 if (am_list[0] == AM_NONE || am_list[0] == 0) {
2057 ict->ict_login_sm.icl_auth_pass = 1;
2058 } else {
2059 error_class = ISCSI_STATUS_CLASS_INITIATOR_ERR;
2060 error_detail = ISCSI_LOGIN_STATUS_AUTH_FAILED;
2061 }
2062 }
2063
2064 if (error_class == ISCSI_STATUS_CLASS_SUCCESS) {
2065 idm_status = IDM_STATUS_SUCCESS;
2066 } else {
2067 /* supply login class/detail for login errors */
2068 SET_LOGIN_ERROR(ict, error_class, error_detail);
2069 idm_status = IDM_STATUS_FAIL;
2070 }
2071
2072 return (idm_status);
2073 }
2074
2075 static idm_pdu_t *
login_sm_build_login_response(iscsit_conn_t * ict)2076 login_sm_build_login_response(iscsit_conn_t *ict)
2077 {
2078 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2079 iscsi_login_rsp_hdr_t *lh;
2080 int transit, text_transit = 1;
2081 idm_pdu_t *login_resp;
2082
2083 /*
2084 * Create a response PDU and fill it with as much of
2085 * the response text that will fit.
2086 */
2087
2088 if (lsm->icl_login_resp_itb) {
2089 /* allocate a pdu with space for text */
2090 login_resp = idm_pdu_alloc(sizeof (iscsi_hdr_t),
2091 ISCSI_DEFAULT_MAX_RECV_SEG_LEN);
2092 /* copy a chunk of text into the pdu */
2093 lsm->icl_login_resp_buf = idm_pdu_init_text_data(
2094 login_resp, lsm->icl_login_resp_itb,
2095 ISCSI_DEFAULT_MAX_RECV_SEG_LEN,
2096 lsm->icl_login_resp_buf, &text_transit);
2097 if (text_transit) {
2098 /* text buf has been consumed */
2099 idm_itextbuf_free(lsm->icl_login_resp_itb);
2100 lsm->icl_login_resp_itb = NULL;
2101 lsm->icl_login_resp_buf = NULL;
2102 }
2103 } else {
2104 /* allocate a pdu for just a header */
2105 login_resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0);
2106 }
2107 /* finish initializing the pdu */
2108 idm_pdu_init(login_resp,
2109 ict->ict_ic, ict, login_resp_complete_cb);
2110 login_resp->isp_flags |= IDM_PDU_LOGIN_TX;
2111
2112 /*
2113 * Use the BHS header values from the response template
2114 */
2115 bcopy(lsm->icl_login_resp_tmpl,
2116 login_resp->isp_hdr, sizeof (iscsi_login_rsp_hdr_t));
2117
2118 lh = (iscsi_login_rsp_hdr_t *)login_resp->isp_hdr;
2119
2120 /* Set error class/detail */
2121 lh->status_class = lsm->icl_login_resp_err_class;
2122 lh->status_detail = lsm->icl_login_resp_err_detail;
2123 /* Set CSG, NSG and Transit */
2124 lh->flags = 0;
2125 lh->flags |= lsm->icl_login_csg << 2;
2126
2127
2128 if (lh->status_class == ISCSI_STATUS_CLASS_SUCCESS) {
2129 if (lsm->icl_login_transit &&
2130 lsm->icl_auth_pass != 0) {
2131 transit = 1;
2132 } else {
2133 transit = 0;
2134 }
2135 /*
2136 * inititalize the text data
2137 */
2138 if (transit == 1 && text_transit == 1) {
2139 lh->flags |= lsm->icl_login_nsg;
2140 lsm->icl_login_csg = lsm->icl_login_nsg;
2141 lh->flags |= ISCSI_FLAG_LOGIN_TRANSIT;
2142 } else {
2143 lh->flags &= ~ISCSI_FLAG_LOGIN_TRANSIT;
2144 }
2145
2146 /* If we are transitioning to FFP then set TSIH */
2147 if (transit && (lh->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
2148 lsm->icl_login_csg == ISCSI_FULL_FEATURE_PHASE) {
2149 lh->tsid = htons(ict->ict_sess->ist_tsih);
2150 }
2151 } else {
2152 login_resp->isp_data = 0;
2153 login_resp->isp_datalen = 0;
2154 }
2155 return (login_resp);
2156 }
2157
2158 static kv_status_t
iscsit_handle_key(iscsit_conn_t * ict,nvpair_t * nvp,char * nvp_name)2159 iscsit_handle_key(iscsit_conn_t *ict, nvpair_t *nvp, char *nvp_name)
2160 {
2161 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2162 kv_status_t kvrc;
2163 const idm_kv_xlate_t *ikvx;
2164
2165 ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name));
2166 if (ikvx->ik_key_id == KI_MAX_KEY) {
2167 /*
2168 * Any key not understood by the acceptor may be igonred
2169 * by the acceptor without affecting the basic function.
2170 * However, the answer for a key not understood MUST be
2171 * key=NotUnderstood.
2172 */
2173 kvrc = iscsit_reply_string(ict, nvp_name,
2174 ISCSI_TEXT_NOTUNDERSTOOD);
2175 } else {
2176 kvrc = iscsit_handle_common_key(ict, nvp, ikvx);
2177 if (kvrc == KV_UNHANDLED) {
2178 switch (lsm->icl_login_csg) {
2179 case ISCSI_SECURITY_NEGOTIATION_STAGE:
2180 kvrc = iscsit_handle_security_key(
2181 ict, nvp, ikvx);
2182 break;
2183 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
2184 kvrc = iscsit_handle_operational_key(
2185 ict, nvp, ikvx);
2186 break;
2187 case ISCSI_FULL_FEATURE_PHASE:
2188 default:
2189 /* What are we doing here? */
2190 ASSERT(0);
2191 kvrc = KV_UNHANDLED;
2192 }
2193 }
2194 }
2195
2196 return (kvrc);
2197 }
2198
2199 static kv_status_t
iscsit_handle_common_key(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)2200 iscsit_handle_common_key(iscsit_conn_t *ict, nvpair_t *nvp,
2201 const idm_kv_xlate_t *ikvx)
2202 {
2203 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2204 kv_status_t kvrc;
2205 char *string_val;
2206 int nvrc;
2207
2208 switch (ikvx->ik_key_id) {
2209 case KI_INITIATOR_NAME:
2210 case KI_INITIATOR_ALIAS:
2211 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp);
2212 kvrc = idm_nvstat_to_kvstat(nvrc);
2213 break;
2214 case KI_TARGET_NAME:
2215 /* We'll validate the target during login_sm_session_bind() */
2216 nvrc = nvpair_value_string(nvp, &string_val);
2217 ASSERT(nvrc == 0); /* We built this nvlist */
2218
2219 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp);
2220 kvrc = idm_nvstat_to_kvstat(nvrc);
2221 break;
2222 case KI_TARGET_ALIAS:
2223 case KI_TARGET_ADDRESS:
2224 case KI_TARGET_PORTAL_GROUP_TAG:
2225 kvrc = KV_TARGET_ONLY; /* Only the target can declare this */
2226 break;
2227 case KI_SESSION_TYPE:
2228 /*
2229 * If we don't receive this key on the initial login
2230 * we assume this is a normal session.
2231 */
2232 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp);
2233 kvrc = idm_nvstat_to_kvstat(nvrc);
2234 nvrc = nvpair_value_string(nvp, &string_val);
2235 ASSERT(nvrc == 0); /* We built this nvlist */
2236 ict->ict_op.op_discovery_session =
2237 strcmp(string_val, "Discovery") == 0 ? B_TRUE : B_FALSE;
2238 break;
2239 default:
2240 /*
2241 * This is not really an error but we should
2242 * leave this nvpair on the list since we
2243 * didn't do anything with it. Either
2244 * the security or operational phase
2245 * handling functions should process it.
2246 */
2247 kvrc = KV_UNHANDLED;
2248 break;
2249 }
2250
2251 return (kvrc);
2252 }
2253
2254 static kv_status_t
iscsit_handle_security_key(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)2255 iscsit_handle_security_key(iscsit_conn_t *ict, nvpair_t *nvp,
2256 const idm_kv_xlate_t *ikvx)
2257 {
2258 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2259 iscsit_auth_client_t *client = &lsm->icl_auth_client;
2260 iscsikey_id_t kv_id;
2261 kv_status_t kvrc;
2262 iscsit_auth_handler_t handler;
2263
2264 /*
2265 * After all of security keys are handled, this function will
2266 * be called again to verify current authentication status
2267 * and perform some actual authentication work. At this time,
2268 * the nvp and ikvx will be passed in as NULLs.
2269 */
2270 if (ikvx != NULL) {
2271 kv_id = ikvx->ik_key_id;
2272 } else {
2273 kv_id = 0;
2274 }
2275
2276 handler = iscsit_auth_get_handler(client, kv_id);
2277 if (handler) {
2278 kvrc = handler(ict, nvp, ikvx);
2279 } else {
2280 kvrc = KV_UNHANDLED; /* invalid request */
2281 }
2282
2283 return (kvrc);
2284 }
2285
2286 static kv_status_t
iscsit_reply_security_key(iscsit_conn_t * ict)2287 iscsit_reply_security_key(iscsit_conn_t *ict)
2288 {
2289 return (iscsit_handle_security_key(ict, NULL, NULL));
2290 }
2291
2292 static kv_status_t
iscsit_handle_operational_key(iscsit_conn_t * ict,nvpair_t * nvp,const idm_kv_xlate_t * ikvx)2293 iscsit_handle_operational_key(iscsit_conn_t *ict, nvpair_t *nvp,
2294 const idm_kv_xlate_t *ikvx)
2295 {
2296 kv_status_t kvrc = KV_UNHANDLED;
2297 boolean_t bool_val;
2298 uint64_t num_val;
2299 int nvrc;
2300
2301 /*
2302 * Retrieve values. All value lookups are expected to succeed
2303 * since we build the nvlist while decoding the text buffer. This
2304 * step is intended to eliminate some duplication of code (for example
2305 * we only need to code the numerical value lookup once). We will
2306 * handle the values (if necessary) below.
2307 */
2308 switch (ikvx->ik_key_id) {
2309 /* Lists */
2310 case KI_HEADER_DIGEST:
2311 case KI_DATA_DIGEST:
2312 break;
2313 /* Booleans */
2314 case KI_INITIAL_R2T:
2315 case KI_IMMEDIATE_DATA:
2316 case KI_DATA_PDU_IN_ORDER:
2317 case KI_DATA_SEQUENCE_IN_ORDER:
2318 case KI_IFMARKER:
2319 case KI_OFMARKER:
2320 nvrc = nvpair_value_boolean_value(nvp, &bool_val);
2321 ASSERT(nvrc == 0); /* We built this nvlist */
2322 break;
2323 /* Numericals */
2324 case KI_MAX_CONNECTIONS:
2325 case KI_MAX_RECV_DATA_SEGMENT_LENGTH:
2326 case KI_MAX_BURST_LENGTH:
2327 case KI_FIRST_BURST_LENGTH:
2328 case KI_DEFAULT_TIME_2_WAIT:
2329 case KI_DEFAULT_TIME_2_RETAIN:
2330 case KI_MAX_OUTSTANDING_R2T:
2331 case KI_ERROR_RECOVERY_LEVEL:
2332 nvrc = nvpair_value_uint64(nvp, &num_val);
2333 ASSERT(nvrc == 0);
2334 break;
2335 /* Ranges */
2336 case KI_OFMARKERINT:
2337 case KI_IFMARKERINT:
2338 break;
2339 default:
2340 break;
2341 }
2342
2343 /*
2344 * Now handle the values according to the key name. Sometimes we
2345 * don't care what the value is -- in that case we just add the nvpair
2346 * to the negotiated values list.
2347 */
2348 switch (ikvx->ik_key_id) {
2349 case KI_HEADER_DIGEST:
2350 kvrc = iscsit_handle_digest(ict, nvp, ikvx);
2351 break;
2352 case KI_DATA_DIGEST:
2353 kvrc = iscsit_handle_digest(ict, nvp, ikvx);
2354 break;
2355 case KI_INITIAL_R2T:
2356 /* We *require* INITIAL_R2T=yes */
2357 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx,
2358 B_TRUE);
2359 break;
2360 case KI_IMMEDIATE_DATA:
2361 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx,
2362 bool_val);
2363 break;
2364 case KI_DATA_PDU_IN_ORDER:
2365 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx,
2366 B_TRUE);
2367 break;
2368 case KI_DATA_SEQUENCE_IN_ORDER:
2369 /* We allow any value for DATA_SEQUENCE_IN_ORDER */
2370 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx,
2371 bool_val);
2372 break;
2373 case KI_OFMARKER:
2374 case KI_IFMARKER:
2375 /* We don't support markers */
2376 kvrc = iscsit_handle_boolean(ict, nvp, bool_val, ikvx,
2377 B_FALSE);
2378 break;
2379 case KI_MAX_CONNECTIONS:
2380 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2381 ISCSI_MIN_CONNECTIONS,
2382 ISCSI_MAX_CONNECTIONS,
2383 ISCSIT_MAX_CONNECTIONS);
2384 break;
2385 /* this is a declartive param */
2386 case KI_MAX_RECV_DATA_SEGMENT_LENGTH:
2387 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2388 ISCSI_MIN_RECV_DATA_SEGMENT_LENGTH,
2389 ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH,
2390 ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH);
2391 break;
2392 case KI_MAX_BURST_LENGTH:
2393 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2394 ISCSI_MIN_MAX_BURST_LENGTH,
2395 ISCSI_MAX_BURST_LENGTH,
2396 ISCSIT_MAX_BURST_LENGTH);
2397 break;
2398 case KI_FIRST_BURST_LENGTH:
2399 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2400 ISCSI_MIN_FIRST_BURST_LENGTH,
2401 ISCSI_MAX_FIRST_BURST_LENGTH,
2402 ISCSIT_MAX_FIRST_BURST_LENGTH);
2403 break;
2404 case KI_DEFAULT_TIME_2_WAIT:
2405 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2406 ISCSI_MIN_TIME2WAIT,
2407 ISCSI_MAX_TIME2WAIT,
2408 ISCSIT_MAX_TIME2WAIT);
2409 break;
2410 case KI_DEFAULT_TIME_2_RETAIN:
2411 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2412 ISCSI_MIN_TIME2RETAIN,
2413 ISCSI_MAX_TIME2RETAIN,
2414 ISCSIT_MAX_TIME2RETAIN);
2415 break;
2416 case KI_MAX_OUTSTANDING_R2T:
2417 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2418 ISCSI_MIN_MAX_OUTSTANDING_R2T,
2419 ISCSI_MAX_OUTSTANDING_R2T,
2420 ISCSIT_MAX_OUTSTANDING_R2T);
2421 break;
2422 case KI_ERROR_RECOVERY_LEVEL:
2423 kvrc = iscsit_handle_numerical(ict, nvp, num_val, ikvx,
2424 ISCSI_MIN_ERROR_RECOVERY_LEVEL,
2425 ISCSI_MAX_ERROR_RECOVERY_LEVEL,
2426 ISCSIT_MAX_ERROR_RECOVERY_LEVEL);
2427 break;
2428 case KI_OFMARKERINT:
2429 case KI_IFMARKERINT:
2430 kvrc = iscsit_reply_string(ict, ikvx->ik_key_name,
2431 ISCSI_TEXT_IRRELEVANT);
2432 break;
2433 default:
2434 kvrc = KV_UNHANDLED; /* invalid request */
2435 break;
2436 }
2437
2438 return (kvrc);
2439 }
2440
2441 static kv_status_t
iscsit_reply_numerical(iscsit_conn_t * ict,const char * nvp_name,const uint64_t value)2442 iscsit_reply_numerical(iscsit_conn_t *ict,
2443 const char *nvp_name, const uint64_t value)
2444 {
2445 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2446 kv_status_t kvrc;
2447 int nvrc;
2448
2449 nvrc = nvlist_add_uint64(lsm->icl_response_nvlist,
2450 nvp_name, value);
2451 kvrc = idm_nvstat_to_kvstat(nvrc);
2452
2453 return (kvrc);
2454 }
2455
2456 static kv_status_t
iscsit_reply_string(iscsit_conn_t * ict,const char * nvp_name,const char * text)2457 iscsit_reply_string(iscsit_conn_t *ict,
2458 const char *nvp_name, const char *text)
2459 {
2460 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2461 kv_status_t kvrc;
2462 int nvrc;
2463
2464 nvrc = nvlist_add_string(lsm->icl_response_nvlist,
2465 nvp_name, text);
2466 kvrc = idm_nvstat_to_kvstat(nvrc);
2467
2468 return (kvrc);
2469 }
2470
2471 static kv_status_t
iscsit_handle_digest(iscsit_conn_t * ict,nvpair_t * choices,const idm_kv_xlate_t * ikvx)2472 iscsit_handle_digest(iscsit_conn_t *ict, nvpair_t *choices,
2473 const idm_kv_xlate_t *ikvx)
2474 {
2475 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2476 kv_status_t kvrc = KV_VALUE_ERROR;
2477 int nvrc;
2478 nvpair_t *digest_choice;
2479 char *digest_choice_string;
2480
2481 /*
2482 * Need to add persistent config here if we want users to allow
2483 * disabling of digests on the target side. You could argue that
2484 * this makes things too complicated... just let the initiator state
2485 * what it wants and we'll take it. For now that's exactly what
2486 * we'll do.
2487 *
2488 * Basic digest negotiation happens here at iSCSI level. IDM
2489 * can override this during negotiate_key_values phase to
2490 * decline to set up any digest processing.
2491 */
2492 digest_choice = idm_get_next_listvalue(choices, NULL);
2493
2494 /*
2495 * Loop through all choices. As soon as we find a choice
2496 * that we support add the value to our negotiated values list
2497 * and respond with that value in the login response.
2498 */
2499 while (digest_choice != NULL) {
2500 nvrc = nvpair_value_string(digest_choice,
2501 &digest_choice_string);
2502 ASSERT(nvrc == 0);
2503
2504 if ((strcasecmp(digest_choice_string, "crc32c") == 0) ||
2505 (strcasecmp(digest_choice_string, "none") == 0)) {
2506 /* Add to negotiated values list */
2507 nvrc = nvlist_add_string(lsm->icl_negotiated_values,
2508 ikvx->ik_key_name, digest_choice_string);
2509 kvrc = idm_nvstat_to_kvstat(nvrc);
2510 if (nvrc == 0) {
2511 /* Add to login response list */
2512 nvrc = nvlist_add_string(
2513 lsm->icl_response_nvlist,
2514 ikvx->ik_key_name, digest_choice_string);
2515 kvrc = idm_nvstat_to_kvstat(nvrc);
2516 }
2517 break;
2518 }
2519 digest_choice = idm_get_next_listvalue(choices,
2520 digest_choice);
2521 }
2522
2523 if (digest_choice == NULL)
2524 kvrc = KV_VALUE_ERROR;
2525
2526 return (kvrc);
2527 }
2528
2529 static kv_status_t
iscsit_handle_boolean(iscsit_conn_t * ict,nvpair_t * nvp,boolean_t value,const idm_kv_xlate_t * ikvx,boolean_t iscsit_value)2530 iscsit_handle_boolean(iscsit_conn_t *ict, nvpair_t *nvp, boolean_t value,
2531 const idm_kv_xlate_t *ikvx, boolean_t iscsit_value)
2532 {
2533 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2534 kv_status_t kvrc;
2535 int nvrc;
2536
2537 if (ikvx->ik_declarative) {
2538 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp);
2539 } else {
2540 if (value != iscsit_value) {
2541 /* Respond back to initiator with our value */
2542 value = iscsit_value;
2543 nvrc = nvlist_add_boolean_value(
2544 lsm->icl_negotiated_values,
2545 ikvx->ik_key_name, value);
2546 lsm->icl_login_transit = B_FALSE;
2547 } else {
2548 /* Add this to our negotiated values */
2549 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values,
2550 nvp);
2551 }
2552
2553 /* Response of Simple-value Negotiation */
2554 if (nvrc == 0) {
2555 nvrc = nvlist_add_boolean_value(
2556 lsm->icl_response_nvlist, ikvx->ik_key_name, value);
2557 }
2558 }
2559
2560 kvrc = idm_nvstat_to_kvstat(nvrc);
2561
2562 return (kvrc);
2563 }
2564
2565 static kv_status_t
iscsit_handle_numerical(iscsit_conn_t * ict,nvpair_t * nvp,uint64_t value,const idm_kv_xlate_t * ikvx,uint64_t iscsi_min_value,uint64_t iscsi_max_value,uint64_t iscsit_max_value)2566 iscsit_handle_numerical(iscsit_conn_t *ict, nvpair_t *nvp, uint64_t value,
2567 const idm_kv_xlate_t *ikvx,
2568 uint64_t iscsi_min_value, uint64_t iscsi_max_value,
2569 uint64_t iscsit_max_value)
2570 {
2571 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2572 kv_status_t kvrc;
2573 int nvrc;
2574
2575 /* Validate against standard */
2576 if ((value < iscsi_min_value) || (value > iscsi_max_value)) {
2577 kvrc = KV_VALUE_ERROR;
2578 } else if (ikvx->ik_declarative) {
2579 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values, nvp);
2580 kvrc = idm_nvstat_to_kvstat(nvrc);
2581 } else {
2582 if (value > iscsit_max_value) {
2583 /* Respond back to initiator with our value */
2584 value = iscsit_max_value;
2585 nvrc = nvlist_add_uint64(lsm->icl_negotiated_values,
2586 ikvx->ik_key_name, value);
2587 lsm->icl_login_transit = B_FALSE;
2588 } else {
2589 /* Add this to our negotiated values */
2590 nvrc = nvlist_add_nvpair(lsm->icl_negotiated_values,
2591 nvp);
2592 }
2593
2594 /* Response of Simple-value Negotiation */
2595 if (nvrc == 0) {
2596 nvrc = nvlist_add_uint64(lsm->icl_response_nvlist,
2597 ikvx->ik_key_name, value);
2598 }
2599 kvrc = idm_nvstat_to_kvstat(nvrc);
2600 }
2601
2602 return (kvrc);
2603 }
2604
2605
2606 static void
iscsit_process_negotiated_values(iscsit_conn_t * ict)2607 iscsit_process_negotiated_values(iscsit_conn_t *ict)
2608 {
2609 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2610 char *string_val;
2611 boolean_t boolean_val;
2612 uint64_t uint64_val;
2613 int nvrc;
2614
2615 /* Let the IDM level activate its parameters first */
2616 idm_notice_key_values(ict->ict_ic, lsm->icl_negotiated_values);
2617
2618 /*
2619 * Initiator alias and target alias
2620 */
2621 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values,
2622 "InitiatorAlias", &string_val)) != ENOENT) {
2623 ASSERT(nvrc == 0);
2624 ict->ict_sess->ist_initiator_alias =
2625 kmem_alloc(strlen(string_val) + 1, KM_SLEEP);
2626 (void) strcpy(ict->ict_sess->ist_initiator_alias, string_val);
2627 if (ict->ict_sess->ist_stmf_sess)
2628 ict->ict_sess->ist_stmf_sess->ss_rport_alias =
2629 strdup(string_val);
2630 }
2631
2632 if ((nvrc = nvlist_lookup_string(lsm->icl_negotiated_values,
2633 "TargetAlias", &string_val)) != ENOENT) {
2634 ASSERT(nvrc == 0);
2635 ict->ict_sess->ist_target_alias =
2636 kmem_alloc(strlen(string_val) + 1, KM_SLEEP);
2637 (void) strcpy(ict->ict_sess->ist_target_alias, string_val);
2638 }
2639
2640 /*
2641 * Operational parameters. We process SessionType when it is
2642 * initially received since it is required on the initial login.
2643 */
2644 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values,
2645 "InitialR2T", &boolean_val)) != ENOENT) {
2646 ASSERT(nvrc == 0);
2647 ict->ict_op.op_initial_r2t = boolean_val;
2648 }
2649
2650 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values,
2651 "ImmediateData", &boolean_val)) != ENOENT) {
2652 ASSERT(nvrc == 0);
2653 ict->ict_op.op_immed_data = boolean_val;
2654 }
2655
2656 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values,
2657 "DataPDUInOrder", &boolean_val)) != ENOENT) {
2658 ASSERT(nvrc == 0);
2659 ict->ict_op.op_data_pdu_in_order = boolean_val;
2660 }
2661
2662 if ((nvrc = nvlist_lookup_boolean_value(lsm->icl_negotiated_values,
2663 "DataSequenceInOrder", &boolean_val)) != ENOENT) {
2664 ASSERT(nvrc == 0);
2665 ict->ict_op.op_data_sequence_in_order = boolean_val;
2666 }
2667
2668 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2669 "MaxConnections", &uint64_val)) != ENOENT) {
2670 ASSERT(nvrc == 0);
2671 ict->ict_op.op_max_connections = uint64_val;
2672 }
2673
2674 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2675 "MaxRecvDataSegmentLength", &uint64_val)) != ENOENT) {
2676 ASSERT(nvrc == 0);
2677 ict->ict_op.op_max_recv_data_segment_length = uint64_val;
2678 }
2679
2680 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2681 "MaxBurstLength", &uint64_val)) != ENOENT) {
2682 ASSERT(nvrc == 0);
2683 ict->ict_op.op_max_burst_length = uint64_val;
2684 }
2685
2686 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2687 "FirstBurstLength", &uint64_val)) != ENOENT) {
2688 ASSERT(nvrc == 0);
2689 ict->ict_op.op_first_burst_length = uint64_val;
2690 }
2691
2692 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2693 "DefaultTime2Wait", &uint64_val)) != ENOENT) {
2694 ASSERT(nvrc == 0);
2695 ict->ict_op.op_default_time_2_wait = uint64_val;
2696 }
2697
2698 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2699 "DefaultTime2Retain", &uint64_val)) != ENOENT) {
2700 ASSERT(nvrc == 0);
2701 ict->ict_op.op_default_time_2_retain = uint64_val;
2702 }
2703
2704 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2705 "MaxOutstandingR2T", &uint64_val)) != ENOENT) {
2706 ASSERT(nvrc == 0);
2707 ict->ict_op.op_max_outstanding_r2t = uint64_val;
2708 }
2709
2710 if ((nvrc = nvlist_lookup_uint64(lsm->icl_negotiated_values,
2711 "ErrorRecoveryLevel", &uint64_val)) != ENOENT) {
2712 ASSERT(nvrc == 0);
2713 ict->ict_op.op_error_recovery_level = uint64_val;
2714 }
2715 }
2716
2717 static idm_status_t
iscsit_add_declarative_keys(iscsit_conn_t * ict)2718 iscsit_add_declarative_keys(iscsit_conn_t *ict)
2719 {
2720 nvlist_t *cfg_nv = NULL;
2721 kv_status_t kvrc;
2722 int nvrc;
2723 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2724 uint8_t error_class;
2725 uint8_t error_detail;
2726 idm_status_t idm_status;
2727
2728 if ((nvrc = nvlist_alloc(&cfg_nv, NV_UNIQUE_NAME, KM_NOSLEEP)) != 0) {
2729 kvrc = idm_nvstat_to_kvstat(nvrc);
2730 goto alloc_fail;
2731 }
2732 if ((nvrc = nvlist_add_uint64(cfg_nv, "MaxRecvDataSegmentLength",
2733 max_dataseglen_target)) != 0) {
2734 kvrc = idm_nvstat_to_kvstat(nvrc);
2735 goto done;
2736 }
2737
2738 kvrc = idm_declare_key_values(ict->ict_ic, cfg_nv,
2739 lsm->icl_response_nvlist);
2740 done:
2741 nvlist_free(cfg_nv);
2742 alloc_fail:
2743 idm_kvstat_to_error(kvrc, &error_class, &error_detail);
2744 if (error_class == ISCSI_STATUS_CLASS_SUCCESS) {
2745 idm_status = IDM_STATUS_SUCCESS;
2746 } else {
2747 SET_LOGIN_ERROR(ict, error_class, error_detail);
2748 idm_status = IDM_STATUS_FAIL;
2749 }
2750 return (idm_status);
2751 }
2752
2753 static char *
iscsit_fold_name(char * name,size_t * buflen)2754 iscsit_fold_name(char *name, size_t *buflen)
2755 {
2756 char *ret;
2757 const char *sns;
2758 int errnum;
2759 int flag = U8_TEXTPREP_NFKC;
2760 size_t inlen, outlen, coff;
2761
2762 if (name == NULL)
2763 return (NULL);
2764
2765 /* Check for one of the supported name types */
2766 if (strncasecmp(name, SNS_EUI ".", strlen(SNS_EUI) + 1) == 0) {
2767 sns = SNS_EUI;
2768 *buflen = SNS_EUI_LEN_MAX + 1;
2769 flag |= U8_TEXTPREP_TOUPPER;
2770 } else if (strncasecmp(name, SNS_IQN ".", strlen(SNS_IQN) + 1) == 0) {
2771 sns = SNS_IQN;
2772 *buflen = SNS_IQN_LEN_MAX + 1;
2773 flag |= U8_TEXTPREP_TOLOWER;
2774 } else if (strncasecmp(name, SNS_NAA ".", strlen(SNS_NAA) + 1) == 0) {
2775 sns = SNS_NAA;
2776 *buflen = SNS_NAA_LEN_MAX + 1;
2777 flag |= U8_TEXTPREP_TOUPPER;
2778 } else {
2779 return (NULL);
2780 }
2781
2782 ret = kmem_zalloc(*buflen, KM_SLEEP);
2783 coff = strlen(sns);
2784 inlen = strlen(name) - coff;
2785 outlen = *buflen - coff - 1;
2786
2787 /* Fold the case and normalize string */
2788 if (u8_textprep_str(name + coff, &inlen, ret + coff, &outlen, flag,
2789 U8_UNICODE_320, &errnum) == (size_t)-1) {
2790 kmem_free(ret, *buflen);
2791 return (NULL);
2792 }
2793
2794 /* Copy the name type prefix */
2795 bcopy(sns, ret, coff);
2796
2797 return (ret);
2798 }
2799