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.
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.
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]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2016 Nexenta Systems, Inc.
27 #include <sys/cpuvar.h>
28 #include <sys/types.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>
37 #include <sys/socket.h>
38 #include <sys/strsubr.h>
39 #include <sys/sysmacros.h>
42 #include <sys/errno.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>
50 #define ISCSIT_LOGIN_SM_STRINGS
52 #include "iscsit_auth.h"
55 list_node_t le_ctx_node
;
56 iscsit_login_event_t le_ctx_event
;
68 #define DEFAULT_RADIUS_PORT 1812
71 login_sm_complete(void *ict_void
);
74 login_sm_event_dispatch(iscsit_conn_login_t
*lsm
, iscsit_conn_t
*ict
,
75 login_event_ctx_t
*ctx
);
78 login_sm_init(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
81 login_sm_waiting(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
84 login_sm_processing(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
87 login_sm_responding(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
90 login_sm_responded(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
93 login_sm_ffp(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
96 login_sm_done(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
99 login_sm_error(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
);
102 login_sm_new_state(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
,
103 iscsit_login_state_t new_state
);
106 login_sm_send_ack(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
);
109 login_sm_validate_ack(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
);
112 login_sm_is_last_response(idm_pdu_t
*pdu
);
115 login_sm_handle_initial_login(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
);
118 login_sm_send_next_response(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
);
121 login_sm_process_request(iscsit_conn_t
*ict
);
124 login_sm_req_pdu_check(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
);
127 login_sm_process_nvlist(iscsit_conn_t
*ict
);
130 login_sm_check_security(iscsit_conn_t
*ict
);
133 login_sm_build_login_response(iscsit_conn_t
*ict
);
136 login_sm_ffp_actions(iscsit_conn_t
*ict
);
139 login_sm_validate_initial_parameters(iscsit_conn_t
*ict
);
142 login_sm_session_bind(iscsit_conn_t
*ict
);
145 login_sm_set_auth(iscsit_conn_t
*ict
);
148 login_sm_session_register(iscsit_conn_t
*ict
);
151 iscsit_handle_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
, char *nvp_name
);
154 iscsit_handle_common_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
,
155 const idm_kv_xlate_t
*ikvx
);
158 iscsit_handle_security_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
,
159 const idm_kv_xlate_t
*ikvx
);
162 iscsit_reply_security_key(iscsit_conn_t
*ict
);
165 iscsit_handle_operational_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
,
166 const idm_kv_xlate_t
*ikvx
);
169 iscsit_reply_numerical(iscsit_conn_t
*ict
,
170 const char *nvp_name
, const uint64_t value
);
173 iscsit_reply_string(iscsit_conn_t
*ict
,
174 const char *nvp_name
, const char *text
);
177 iscsit_handle_digest(iscsit_conn_t
*ict
, nvpair_t
*choices
,
178 const idm_kv_xlate_t
*ikvx
);
181 iscsit_handle_boolean(iscsit_conn_t
*ict
, nvpair_t
*nvp
, boolean_t value
,
182 const idm_kv_xlate_t
*ikvx
, boolean_t iscsit_value
);
185 iscsit_handle_numerical(iscsit_conn_t
*ict
, nvpair_t
*nvp
, uint64_t value
,
186 const idm_kv_xlate_t
*ikvx
,
187 uint64_t iscsi_min_value
, uint64_t iscsi_max_value
,
188 uint64_t iscsit_max_value
);
191 iscsit_process_negotiated_values(iscsit_conn_t
*ict
);
194 login_resp_complete_cb(idm_pdu_t
*pdu
, idm_status_t status
);
197 iscsit_add_declarative_keys(iscsit_conn_t
*ict
);
200 iscsit_fold_name(char *name
, size_t *buflen
);
202 uint64_t max_dataseglen_target
= ISCSIT_MAX_RECV_DATA_SEGMENT_LENGTH
;
205 * global mutex defined in iscsit.c to enforce
206 * login_sm_session_bind as a critical section
208 extern kmutex_t login_sm_session_mutex
;
211 iscsit_login_sm_init(iscsit_conn_t
*ict
)
213 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
215 bzero(lsm
, sizeof (iscsit_conn_login_t
));
217 (void) nvlist_alloc(&lsm
->icl_negotiated_values
, NV_UNIQUE_NAME
,
221 * Hold connection until the login state machine completes
223 iscsit_conn_hold(ict
);
226 * Pre-allocating a login response PDU means we will always be
227 * able to respond to a login request -- even if we can't allocate
228 * a data buffer to hold the text responses we can at least send
231 lsm
->icl_login_resp_tmpl
= kmem_zalloc(sizeof (iscsi_login_rsp_hdr_t
),
234 idm_sm_audit_init(&lsm
->icl_state_audit
);
235 mutex_init(&lsm
->icl_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
236 list_create(&lsm
->icl_login_events
, sizeof (login_event_ctx_t
),
237 offsetof(login_event_ctx_t
, le_ctx_node
));
238 list_create(&lsm
->icl_pdu_list
, sizeof (idm_pdu_t
),
239 offsetof(idm_pdu_t
, isp_client_lnd
));
241 lsm
->icl_login_state
= ILS_LOGIN_INIT
;
242 lsm
->icl_login_last_state
= ILS_LOGIN_INIT
;
245 * Initialize operational parameters to default values. Anything
246 * we don't specifically negotiate stays at the default.
248 ict
->ict_op
.op_discovery_session
= B_FALSE
;
249 ict
->ict_op
.op_initial_r2t
= ISCSI_DEFAULT_INITIALR2T
;
250 ict
->ict_op
.op_immed_data
= ISCSI_DEFAULT_IMMEDIATE_DATA
;
251 ict
->ict_op
.op_data_pdu_in_order
= ISCSI_DEFAULT_DATA_PDU_IN_ORDER
;
252 ict
->ict_op
.op_data_sequence_in_order
=
253 ISCSI_DEFAULT_DATA_SEQUENCE_IN_ORDER
;
254 ict
->ict_op
.op_max_connections
= ISCSI_DEFAULT_MAX_CONNECTIONS
;
255 ict
->ict_op
.op_max_recv_data_segment_length
=
256 ISCSI_DEFAULT_MAX_RECV_SEG_LEN
;
257 ict
->ict_op
.op_max_burst_length
= ISCSI_DEFAULT_MAX_BURST_LENGTH
;
258 ict
->ict_op
.op_first_burst_length
= ISCSI_DEFAULT_FIRST_BURST_LENGTH
;
259 ict
->ict_op
.op_default_time_2_wait
= ISCSI_DEFAULT_TIME_TO_WAIT
;
260 ict
->ict_op
.op_default_time_2_retain
= ISCSI_DEFAULT_TIME_TO_RETAIN
;
261 ict
->ict_op
.op_max_outstanding_r2t
= ISCSI_DEFAULT_MAX_OUT_R2T
;
262 ict
->ict_op
.op_error_recovery_level
=
263 ISCSI_DEFAULT_ERROR_RECOVERY_LEVEL
;
265 return (IDM_STATUS_SUCCESS
);
269 login_resp_complete_cb(idm_pdu_t
*pdu
, idm_status_t status
)
271 iscsit_conn_t
*ict
= pdu
->isp_private
;
274 * Check that this is a login pdu
276 ASSERT((pdu
->isp_flags
& IDM_PDU_LOGIN_TX
) != 0);
279 if ((status
!= IDM_STATUS_SUCCESS
) ||
280 (ict
->ict_login_sm
.icl_login_resp_err_class
!= 0)) {
282 * Transport or login error occurred.
284 iscsit_login_sm_event(ict
, ILE_LOGIN_ERROR
, NULL
);
286 iscsit_conn_rele(ict
);
290 iscsit_login_sm_fini(iscsit_conn_t
*ict
)
292 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
294 mutex_enter(&lsm
->icl_mutex
);
295 list_destroy(&lsm
->icl_pdu_list
);
296 list_destroy(&lsm
->icl_login_events
);
298 kmem_free(lsm
->icl_login_resp_tmpl
, sizeof (iscsi_login_rsp_hdr_t
));
300 /* clean up the login response idm text buffer */
301 if (lsm
->icl_login_resp_itb
!= NULL
) {
302 idm_itextbuf_free(lsm
->icl_login_resp_itb
);
303 lsm
->icl_login_resp_itb
= NULL
;
306 nvlist_free(lsm
->icl_negotiated_values
);
307 mutex_destroy(&lsm
->icl_mutex
);
311 iscsit_login_sm_event(iscsit_conn_t
*ict
, iscsit_login_event_t event
,
315 * This is a bit ugly but if we're already in ILS_LOGIN_ERROR
316 * or ILS_LOGIN_DONE then just drop any additional events. They
317 * won't change the state and it's possible we've already called
318 * iscsit_login_sm_fini in which case the mutex is destroyed.
320 if ((ict
->ict_login_sm
.icl_login_state
== ILS_LOGIN_ERROR
) ||
321 (ict
->ict_login_sm
.icl_login_state
== ILS_LOGIN_DONE
))
324 mutex_enter(&ict
->ict_login_sm
.icl_mutex
);
325 iscsit_login_sm_event_locked(ict
, event
, pdu
);
326 mutex_exit(&ict
->ict_login_sm
.icl_mutex
);
329 iscsit_login_sm_event_locked(iscsit_conn_t
*ict
, iscsit_login_event_t event
,
332 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
333 login_event_ctx_t
*ctx
;
335 ASSERT(mutex_owned(&lsm
->icl_mutex
));
336 ctx
= kmem_zalloc(sizeof (*ctx
), KM_SLEEP
);
338 ctx
->le_ctx_event
= event
;
341 list_insert_tail(&lsm
->icl_login_events
, ctx
);
344 * Use the icl_busy flag to keep the state machine single threaded.
345 * This also serves as recursion avoidance since this flag will
346 * always be set if we call login_sm_event from within the
347 * state machine code.
349 if (!lsm
->icl_busy
) {
350 lsm
->icl_busy
= B_TRUE
;
351 while (!list_is_empty(&lsm
->icl_login_events
)) {
352 ctx
= list_head(&lsm
->icl_login_events
);
353 list_remove(&lsm
->icl_login_events
, ctx
);
354 idm_sm_audit_event(&lsm
->icl_state_audit
,
355 SAS_ISCSIT_LOGIN
, (int)lsm
->icl_login_state
,
356 (int)ctx
->le_ctx_event
, (uintptr_t)pdu
);
359 * If the lsm is in a terminal state, just drain
360 * any remaining events.
362 if ((lsm
->icl_login_state
== ILS_LOGIN_ERROR
) ||
363 (lsm
->icl_login_state
== ILS_LOGIN_DONE
)) {
364 kmem_free(ctx
, sizeof (*ctx
));
367 mutex_exit(&lsm
->icl_mutex
);
368 login_sm_event_dispatch(lsm
, ict
, ctx
);
369 mutex_enter(&lsm
->icl_mutex
);
371 lsm
->icl_busy
= B_FALSE
;
374 * When the state machine reaches ILS_LOGIN_DONE or
375 * ILS_LOGIN_ERROR state the login process has completed
376 * and it's time to cleanup. The state machine code will
377 * mark itself "complete" when this happens.
379 * To protect against spurious events (which shouldn't
380 * happen) set icl_busy again.
382 if (lsm
->icl_login_complete
) {
383 lsm
->icl_busy
= B_TRUE
;
384 if (taskq_dispatch(iscsit_global
.global_dispatch_taskq
,
385 login_sm_complete
, ict
, DDI_SLEEP
)
386 == (uintptr_t)NULL
) {
387 cmn_err(CE_WARN
, "iscsit_login_sm_event_locked:"
388 " Failed to dispatch task");
395 login_sm_complete(void *ict_void
)
397 iscsit_conn_t
*ict
= ict_void
;
400 * State machine has run to completion, resources
401 * will be cleaned up when connection is destroyed.
403 iscsit_conn_rele(ict
);
407 login_sm_event_dispatch(iscsit_conn_login_t
*lsm
, iscsit_conn_t
*ict
,
408 login_event_ctx_t
*ctx
)
410 idm_pdu_t
*pdu
= ctx
->le_pdu
; /* Only valid for some events */
412 DTRACE_PROBE2(login__event
, iscsit_conn_t
*, ict
,
413 login_event_ctx_t
*, ctx
);
415 IDM_SM_LOG(CE_NOTE
, "login_sm_event_dispatch: ict %p event %s(%d)",
417 iscsit_ile_name
[ctx
->le_ctx_event
], ctx
->le_ctx_event
);
419 /* State independent actions */
420 switch (ctx
->le_ctx_event
) {
422 /* Perform basic sanity checks on the header */
423 if (login_sm_req_pdu_check(ict
, pdu
) != IDM_STATUS_SUCCESS
) {
426 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_INITIATOR_ERR
,
427 ISCSI_LOGIN_STATUS_INVALID_REQUEST
);
429 * If we haven't processed any PDU's yet then use
430 * this one as a template for the response
432 if (ict
->ict_login_sm
.icl_login_resp_tmpl
->opcode
== 0)
433 login_sm_handle_initial_login(ict
, pdu
);
434 rpdu
= login_sm_build_login_response(ict
);
435 login_sm_send_next_response(ict
, rpdu
);
436 idm_pdu_complete(pdu
, IDM_STATUS_SUCCESS
);
437 kmem_free(ctx
, sizeof (*ctx
));
445 /* State dependent actions */
446 switch (lsm
->icl_login_state
) {
448 login_sm_init(ict
, ctx
);
450 case ILS_LOGIN_WAITING
:
451 login_sm_waiting(ict
, ctx
);
453 case ILS_LOGIN_PROCESSING
:
454 login_sm_processing(ict
, ctx
);
456 case ILS_LOGIN_RESPONDING
:
457 login_sm_responding(ict
, ctx
);
459 case ILS_LOGIN_RESPONDED
:
460 login_sm_responded(ict
, ctx
);
463 login_sm_ffp(ict
, ctx
);
466 login_sm_done(ict
, ctx
);
468 case ILS_LOGIN_ERROR
:
469 login_sm_error(ict
, ctx
);
473 kmem_free(ctx
, sizeof (*ctx
));
477 login_sm_init(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
481 switch (ctx
->le_ctx_event
) {
486 * This is the first login PDU we've received so use
487 * it to build the login response template and set our CSG.
489 login_sm_handle_initial_login(ict
, pdu
);
492 * Accumulate all the login PDU's that make up this
493 * request on a queue.
495 mutex_enter(&ict
->ict_login_sm
.icl_mutex
);
496 list_insert_tail(&ict
->ict_login_sm
.icl_pdu_list
, pdu
);
497 mutex_exit(&ict
->ict_login_sm
.icl_mutex
);
499 if (pdu
->isp_hdr
->flags
& ISCSI_FLAG_LOGIN_CONTINUE
) {
500 login_sm_send_ack(ict
, pdu
);
501 login_sm_new_state(ict
, ctx
, ILS_LOGIN_WAITING
);
503 login_sm_new_state(ict
, ctx
, ILS_LOGIN_PROCESSING
);
506 case ILE_LOGIN_CONN_ERROR
:
507 case ILE_LOGIN_ERROR
:
508 login_sm_new_state(ict
, ctx
, ILS_LOGIN_ERROR
);
516 login_sm_waiting(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
520 switch (ctx
->le_ctx_event
) {
523 mutex_enter(&ict
->ict_login_sm
.icl_mutex
);
524 list_insert_tail(&ict
->ict_login_sm
.icl_pdu_list
, pdu
);
525 mutex_exit(&ict
->ict_login_sm
.icl_mutex
);
526 if (!(pdu
->isp_hdr
->flags
& ISCSI_FLAG_LOGIN_CONTINUE
)) {
527 login_sm_new_state(ict
, ctx
, ILS_LOGIN_PROCESSING
);
529 login_sm_send_ack(ict
, pdu
);
532 case ILE_LOGIN_ERROR
:
533 login_sm_new_state(ict
, ctx
, ILS_LOGIN_ERROR
);
535 case ILE_LOGIN_RESP_COMPLETE
:
543 login_sm_processing(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
545 switch (ctx
->le_ctx_event
) {
546 case ILE_LOGIN_RESP_READY
:
547 login_sm_new_state(ict
, ctx
, ILS_LOGIN_RESPONDING
);
550 idm_pdu_complete(ctx
->le_pdu
, IDM_STATUS_SUCCESS
);
552 case ILE_LOGIN_CONN_ERROR
:
553 case ILE_LOGIN_ERROR
:
554 login_sm_new_state(ict
, ctx
, ILS_LOGIN_ERROR
);
562 login_sm_responding(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
564 idm_pdu_t
*pdu
, *rpdu
;
566 switch (ctx
->le_ctx_event
) {
570 * We should only be in "responding" state if we have not
571 * sent the last PDU of a multi-PDU login response sequence.
572 * In that case we expect this received PDU to be an
573 * acknowledgement from the initiator (login PDU with C
574 * bit cleared and no data). If it's the acknowledgement
575 * we are expecting then we send the next PDU in the login
576 * response sequence. Otherwise it's a protocol error and
579 if (login_sm_validate_ack(ict
, pdu
) == IDM_STATUS_SUCCESS
) {
580 rpdu
= login_sm_build_login_response(ict
);
581 login_sm_send_next_response(ict
, rpdu
);
583 login_sm_new_state(ict
, ctx
, ILS_LOGIN_ERROR
);
585 idm_pdu_complete(pdu
, IDM_STATUS_SUCCESS
);
588 login_sm_new_state(ict
, ctx
, ILS_LOGIN_FFP
);
590 case ILE_LOGIN_RESP_COMPLETE
:
591 login_sm_new_state(ict
, ctx
, ILS_LOGIN_RESPONDED
);
593 case ILE_LOGIN_CONN_ERROR
:
594 case ILE_LOGIN_ERROR
:
595 login_sm_new_state(ict
, ctx
, ILS_LOGIN_ERROR
);
603 login_sm_responded(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
606 iscsi_login_hdr_t
*lh
;
608 switch (ctx
->le_ctx_event
) {
611 lh
= (iscsi_login_hdr_t
*)pdu
->isp_hdr
;
613 * Set the CSG, NSG and Transit bits based on the this PDU.
614 * The CSG already validated in login_sm_req_pdu_check().
615 * We'll clear the transit bit if we encounter any login
616 * parameters in the request that required an additional
617 * login transfer (i.e. no acceptable
618 * choices in range or we needed to change a boolean
619 * value from "Yes" to "No").
621 ict
->ict_login_sm
.icl_login_csg
=
622 ISCSI_LOGIN_CURRENT_STAGE(lh
->flags
);
623 ict
->ict_login_sm
.icl_login_nsg
=
624 ISCSI_LOGIN_NEXT_STAGE(lh
->flags
);
625 ict
->ict_login_sm
.icl_login_transit
=
626 lh
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
;
627 mutex_enter(&ict
->ict_login_sm
.icl_mutex
);
628 list_insert_tail(&ict
->ict_login_sm
.icl_pdu_list
, pdu
);
629 mutex_exit(&ict
->ict_login_sm
.icl_mutex
);
630 if (pdu
->isp_hdr
->flags
& ISCSI_FLAG_LOGIN_CONTINUE
) {
631 login_sm_send_ack(ict
, pdu
);
632 login_sm_new_state(ict
, ctx
, ILS_LOGIN_WAITING
);
634 login_sm_new_state(ict
, ctx
, ILS_LOGIN_PROCESSING
);
637 case ILE_LOGIN_CONN_ERROR
:
638 case ILE_LOGIN_ERROR
:
639 login_sm_new_state(ict
, ctx
, ILS_LOGIN_ERROR
);
647 login_sm_ffp(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
649 switch (ctx
->le_ctx_event
) {
650 case ILE_LOGIN_RESP_COMPLETE
:
651 login_sm_new_state(ict
, ctx
, ILS_LOGIN_DONE
);
653 case ILE_LOGIN_CONN_ERROR
:
654 case ILE_LOGIN_ERROR
:
655 login_sm_new_state(ict
, ctx
, ILS_LOGIN_ERROR
);
665 login_sm_done(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
667 /* Terminal state, we should get no events */
668 switch (ctx
->le_ctx_event
) {
671 * We've already processed everything we're going to
672 * process. Drop any additional login PDU's.
674 idm_pdu_complete(ctx
->le_pdu
, IDM_STATUS_SUCCESS
);
676 case ILE_LOGIN_CONN_ERROR
:
686 login_sm_error(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
)
688 switch (ctx
->le_ctx_event
) {
691 * We've already processed everything we're going to
692 * process. Drop any additional login PDU's.
694 idm_pdu_complete(ctx
->le_pdu
, IDM_STATUS_SUCCESS
);
696 case ILE_LOGIN_CONN_ERROR
:
705 login_sm_new_state(iscsit_conn_t
*ict
, login_event_ctx_t
*ctx
,
706 iscsit_login_state_t new_state
)
708 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
714 ASSERT(new_state
!= ILS_UNDEFINED
);
715 ASSERT3U(new_state
, <, ILS_MAX_STATE
);
717 new_state
= (new_state
< ILS_MAX_STATE
) ?
718 new_state
: ILS_UNDEFINED
;
720 IDM_SM_LOG(CE_NOTE
, "login_sm_new_state: conn %p "
721 "%s (%d) --> %s (%d)\n", (void *)ict
->ict_ic
,
722 iscsit_ils_name
[lsm
->icl_login_state
], lsm
->icl_login_state
,
723 iscsit_ils_name
[new_state
], new_state
);
725 DTRACE_PROBE3(login__state__change
,
726 iscsit_conn_t
*, ict
, login_event_ctx_t
*, ctx
,
727 iscsit_login_state_t
, new_state
);
729 mutex_enter(&lsm
->icl_mutex
);
730 idm_sm_audit_state_change(&lsm
->icl_state_audit
, SAS_ISCSIT_LOGIN
,
731 (int)lsm
->icl_login_state
, (int)new_state
);
732 lsm
->icl_login_last_state
= lsm
->icl_login_state
;
733 lsm
->icl_login_state
= new_state
;
734 mutex_exit(&lsm
->icl_mutex
);
736 switch (lsm
->icl_login_state
) {
737 case ILS_LOGIN_WAITING
:
738 /* Do nothing, waiting for more login PDU's */
740 case ILS_LOGIN_PROCESSING
:
741 /* All login PDU's received, process login request */
742 login_sm_process_request(ict
);
744 case ILS_LOGIN_RESPONDING
:
745 rpdu
= login_sm_build_login_response(ict
);
746 login_sm_send_next_response(ict
, rpdu
);
748 case ILS_LOGIN_RESPONDED
:
749 /* clean up the login response idm text buffer */
750 if (lsm
->icl_login_resp_itb
!= NULL
) {
751 idm_itextbuf_free(lsm
->icl_login_resp_itb
);
752 lsm
->icl_login_resp_itb
= NULL
;
756 login_sm_ffp_actions(ict
);
759 case ILS_LOGIN_ERROR
:
761 * Flag the terminal state for the dispatcher
763 lsm
->icl_login_complete
= B_TRUE
;
765 case ILS_LOGIN_INIT
: /* Initial state, can't return */
774 login_sm_send_ack(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
)
776 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
780 * allocate the response pdu
782 lack
= idm_pdu_alloc(sizeof (iscsi_hdr_t
), 0);
783 idm_pdu_init(lack
, ict
->ict_ic
, ict
, login_resp_complete_cb
);
784 lack
->isp_flags
|= IDM_PDU_LOGIN_TX
;
787 * copy the response template into the response pdu
789 bcopy(lsm
->icl_login_resp_tmpl
, lack
->isp_hdr
, sizeof (iscsi_hdr_t
));
791 iscsit_conn_hold(ict
);
797 login_sm_validate_ack(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
)
799 iscsi_hdr_t
*ihp
= pdu
->isp_hdr
;
800 if (ihp
->flags
& ISCSI_FLAG_TEXT_CONTINUE
) {
801 return (IDM_STATUS_FAIL
);
803 if (ntoh24(ihp
->dlength
) != 0) {
804 return (IDM_STATUS_FAIL
);
806 return (IDM_STATUS_SUCCESS
);
810 login_sm_is_last_response(idm_pdu_t
*pdu
)
813 if (pdu
->isp_hdr
->flags
& ISCSI_FLAG_LOGIN_CONTINUE
) {
821 login_sm_handle_initial_login(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
)
823 iscsi_login_hdr_t
*lh_req
= (iscsi_login_hdr_t
*)pdu
->isp_hdr
;
824 iscsi_login_rsp_hdr_t
*lh_resp
=
825 ict
->ict_login_sm
.icl_login_resp_tmpl
;
828 * First login PDU, this connection should not have a sesssion
831 ASSERT(ict
->ict_sess
== NULL
);
834 * Save off TSIH and ISID for later use in finding a session
836 ict
->ict_login_sm
.icl_cmdsn
= ntohl(lh_req
->cmdsn
);
837 ict
->ict_login_sm
.icl_tsih
= ntohs(lh_req
->tsid
);
838 bcopy(lh_req
->isid
, ict
->ict_login_sm
.icl_isid
, ISCSI_ISID_LEN
);
841 * We'll need the CID as well
843 ict
->ict_cid
= ntohs(lh_req
->cid
);
846 * Set the CSG, NSG and Transit bits based on the first PDU
847 * in the login sequence. The CSG already validated in
848 * login_sm_req_pdu_check(). We'll clear the transit bit if
849 * we encounter any login parameters in the request that
850 * required an additional login transfer (i.e. no acceptable
851 * choices in range or we needed to change a boolean
852 * value from "Yes" to "No").
854 ict
->ict_login_sm
.icl_login_csg
=
855 ISCSI_LOGIN_CURRENT_STAGE(lh_req
->flags
);
856 ict
->ict_login_sm
.icl_login_nsg
=
857 ISCSI_LOGIN_NEXT_STAGE(lh_req
->flags
);
858 ict
->ict_login_sm
.icl_login_transit
=
859 lh_req
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
;
862 * Initialize header for login reject response. This will also
863 * be copied for use as a template for other login responses
865 lh_resp
->opcode
= ISCSI_OP_LOGIN_RSP
;
866 lh_resp
->max_version
= ISCSIT_MAX_VERSION
;
869 * We already validated that we can support one of the initiator's
870 * versions in login_sm_req_pdu_check().
872 #if (ISCSIT_MAX_VERSION > 0)
873 if (ISCSIT_MAX_VERSION
>= lh_req
->min_version
) {
874 lh_resp
->active_version
=
875 MIN(lh_req
->max_version
, ISCSIT_MAX_VERSION
);
877 ASSERT(ISCSIT_MAX_VERSION
<= lh_req
->max_version
);
878 lh_resp
->active_version
= ISCSIT_MAX_VERSION
;
882 lh_resp
->hlength
= 0; /* No AHS */
883 bcopy(lh_req
->isid
, lh_resp
->isid
, ISCSI_ISID_LEN
);
884 lh_resp
->tsid
= lh_req
->tsid
;
885 lh_resp
->itt
= lh_req
->itt
;
888 * StatSn, ExpCmdSn and MaxCmdSn will be set immediately before
894 login_sm_send_next_response(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
)
896 iscsi_login_rsp_hdr_t
*lh_resp
= (iscsi_login_rsp_hdr_t
*)pdu
->isp_hdr
;
898 /* Make sure this PDU is part of the login phase */
899 ASSERT((pdu
->isp_flags
& IDM_PDU_LOGIN_TX
) != 0);
902 * Fill in header values
904 hton24(lh_resp
->dlength
, pdu
->isp_datalen
);
907 * If the login is successful, this login response will contain
908 * the next StatSN and advance the StatSN for the connection.
910 if (lh_resp
->status_class
== ISCSI_STATUS_CLASS_SUCCESS
) {
911 ASSERT(ict
->ict_sess
!= NULL
);
913 if ((lh_resp
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
) &&
914 (ISCSI_LOGIN_NEXT_STAGE(lh_resp
->flags
) ==
915 ISCSI_FULL_FEATURE_PHASE
) &&
916 !(lh_resp
->flags
& ISCSI_FLAG_LOGIN_CONTINUE
)) {
917 iscsit_login_sm_event(ict
, ILE_LOGIN_FFP
, NULL
);
919 if (login_sm_is_last_response(pdu
) == B_TRUE
) {
921 * The last of a potentially mult-PDU response finished.
923 iscsit_login_sm_event(ict
, ILE_LOGIN_RESP_COMPLETE
,
927 iscsit_conn_hold(ict
);
928 pdu
->isp_flags
|= IDM_PDU_SET_STATSN
| IDM_PDU_ADVANCE_STATSN
;
932 * If status_class != ISCSI_STATUS_CLASS_SUCCESS then
933 * StatSN is not valid and we can call idm_pdu_tx instead
934 * of iscsit_pdu_tx. This is very good thing since in
935 * some cases of login failure we may not have a session.
936 * Since iscsit_calc_rspsn grabs the session mutex while
937 * it is retrieving values for expcmdsn and maxcmdsn this
938 * would cause a panic.
940 * Since we still want a value for expcmdsn, fill in an
941 * appropriate value based on the login request before
942 * sending the response. Cmdsn/expcmdsn do not advance during
945 lh_resp
->expcmdsn
= htonl(ict
->ict_login_sm
.icl_cmdsn
);
946 lh_resp
->maxcmdsn
= htonl(ict
->ict_login_sm
.icl_cmdsn
+ 1);
948 iscsit_conn_hold(ict
);
955 login_sm_process_request(iscsit_conn_t
*ict
)
957 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
958 uint8_t error_class
= 0;
959 uint8_t error_detail
= 0;
962 * First walk all the PDU's that make up this login request
963 * and compile all the iSCSI key-value pairs into nvlist format.
966 ASSERT(lsm
->icl_request_nvlist
== NULL
);
967 /* create an nvlist for request key/value pairs */
968 if (idm_pdu_list_to_nvlist(&lsm
->icl_pdu_list
,
969 &lsm
->icl_request_nvlist
, &error_detail
) != IDM_STATUS_SUCCESS
) {
970 error_class
= ISCSI_STATUS_CLASS_TARGET_ERR
;
971 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
975 /* Allocate a new nvlist for response key/value pairs */
976 ASSERT(lsm
->icl_response_nvlist
== NULL
);
977 if (nvlist_alloc(&lsm
->icl_response_nvlist
, NV_UNIQUE_NAME
,
979 error_class
= ISCSI_STATUS_CLASS_TARGET_ERR
;
980 error_detail
= ISCSI_LOGIN_STATUS_NO_RESOURCES
;
981 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
986 * This would be a very good time to make sure we have
987 * negotiated the required values for the login phase. For
988 * example we definitely should have defined InitiatorName,
989 * and Target name regardless of our current login phase.
991 if (!ict
->ict_op
.op_initial_params_set
) {
992 if (login_sm_validate_initial_parameters(ict
) !=
993 IDM_STATUS_SUCCESS
) {
998 * Now setup our session association. This includes
999 * create a new session or looking up an existing session,
1000 * and if this is not a discovery session then we will
1001 * also register this session with STMF.
1003 if (login_sm_session_bind(ict
) != IDM_STATUS_SUCCESS
) {
1007 if (login_sm_set_auth(ict
) != IDM_STATUS_SUCCESS
) {
1012 * Prepend TargetAlias and PortalGroupTag
1014 if (ict
->ict_op
.op_discovery_session
== B_FALSE
) {
1015 if ((lsm
->icl_auth
.ca_tgt_alias
[0]) != '\0') {
1016 (void) iscsit_reply_string(ict
,
1018 &lsm
->icl_auth
.ca_tgt_alias
[0]);
1020 (void) iscsit_reply_numerical(ict
,
1021 "TargetPortalGroupTag",
1022 (uint64_t)lsm
->icl_tpgt_tag
);
1025 ict
->ict_op
.op_initial_params_set
= B_TRUE
;
1028 if (login_sm_process_nvlist(ict
) != IDM_STATUS_SUCCESS
) {
1032 if (login_sm_check_security(ict
) != IDM_STATUS_SUCCESS
) {
1036 /* clean up request_nvlist */
1037 if (lsm
->icl_request_nvlist
!= NULL
) {
1038 nvlist_free(lsm
->icl_request_nvlist
);
1039 lsm
->icl_request_nvlist
= NULL
;
1042 /* convert any responses to textbuf form */
1043 ASSERT(lsm
->icl_login_resp_itb
== NULL
);
1044 if (lsm
->icl_response_nvlist
) {
1045 lsm
->icl_login_resp_itb
= idm_nvlist_to_itextbuf(
1046 lsm
->icl_response_nvlist
);
1047 if (lsm
->icl_login_resp_itb
== NULL
) {
1048 /* Still need to send the resp so continue */
1049 SET_LOGIN_ERROR(ict
,
1050 ISCSI_STATUS_CLASS_TARGET_ERR
,
1051 ISCSI_LOGIN_STATUS_NO_RESOURCES
);
1053 /* clean up response_nvlist */
1054 nvlist_free(lsm
->icl_response_nvlist
);
1055 lsm
->icl_response_nvlist
= NULL
;
1058 /* tell the state machine to send the textbuf */
1059 iscsit_login_sm_event(ict
, ILE_LOGIN_RESP_READY
, NULL
);
1064 /* clean up request_nvlist and response_nvlist */
1065 if (lsm
->icl_request_nvlist
!= NULL
) {
1066 nvlist_free(lsm
->icl_request_nvlist
);
1067 lsm
->icl_request_nvlist
= NULL
;
1069 if (lsm
->icl_response_nvlist
!= NULL
) {
1070 nvlist_free(lsm
->icl_response_nvlist
);
1071 lsm
->icl_response_nvlist
= NULL
;
1073 /* Make sure we already set the login error */
1074 if (ict
->ict_login_sm
.icl_login_resp_err_class
==
1075 ISCSI_STATUS_CLASS_SUCCESS
) {
1076 SET_LOGIN_ERROR(ict
,
1077 ISCSI_STATUS_CLASS_TARGET_ERR
,
1078 ISCSI_LOGIN_STATUS_TARGET_ERROR
);
1080 iscsit_login_sm_event(ict
, ILE_LOGIN_RESP_READY
, NULL
);
1085 login_sm_ffp_actions(iscsit_conn_t
*ict
)
1087 iscsit_process_negotiated_values(ict
);
1091 login_sm_validate_initial_parameters(iscsit_conn_t
*ict
)
1095 char *u8_iscsi_name
;
1096 size_t u8_iscsi_name_len
;
1097 uint8_t error_class
= ISCSI_STATUS_CLASS_INITIATOR_ERR
;
1098 uint8_t error_detail
= ISCSI_LOGIN_STATUS_MISSING_FIELDS
;
1099 idm_status_t status
= IDM_STATUS_FAIL
;
1100 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
1103 * Make sure we received the required information from the initial
1104 * login. Add these declaratives to the negotiated list and
1105 * remove them from the request list as we go. If anything fails,
1106 * the caller will clean-up the nvlists.
1112 if ((nvrc
= nvlist_lookup_string(lsm
->icl_request_nvlist
,
1113 "InitiatorName", &string_val
)) != 0) {
1114 goto initial_params_done
;
1117 u8_iscsi_name
= iscsit_fold_name(string_val
, &u8_iscsi_name_len
);
1118 if (u8_iscsi_name
== NULL
)
1119 goto initial_params_done
;
1120 nvrc
= nvlist_add_string(lsm
->icl_negotiated_values
, "InitiatorName",
1122 kmem_free(u8_iscsi_name
, u8_iscsi_name_len
);
1124 goto initial_params_done
;
1126 if ((nvrc
= nvlist_lookup_string(lsm
->icl_negotiated_values
,
1127 "InitiatorName", &string_val
)) != 0) {
1128 goto initial_params_done
;
1130 lsm
->icl_initiator_name
= string_val
;
1131 idm_conn_set_initiator_name(ict
->ict_ic
, lsm
->icl_initiator_name
);
1132 if ((nvrc
= nvlist_remove(lsm
->icl_request_nvlist
,
1133 "InitiatorName", DATA_TYPE_STRING
)) != 0) {
1134 goto initial_params_done
;
1140 ict
->ict_op
.op_discovery_session
= B_FALSE
;
1141 nvrc
= nvlist_lookup_string(lsm
->icl_request_nvlist
,
1142 "SessionType", &string_val
);
1143 if (nvrc
!= ENOENT
&& nvrc
!= 0) {
1144 goto initial_params_done
;
1147 if (strcmp(string_val
, "Discovery") == 0) {
1148 ict
->ict_op
.op_discovery_session
= B_TRUE
;
1149 } else if (strcmp(string_val
, "Normal") != 0) {
1150 goto initial_params_done
;
1152 if ((nvrc
= nvlist_add_string(lsm
->icl_negotiated_values
,
1153 "SessionType", string_val
)) != 0) {
1154 goto initial_params_done
;
1156 if ((nvrc
= nvlist_remove(lsm
->icl_request_nvlist
,
1157 "SessionType", DATA_TYPE_STRING
)) != 0) {
1158 goto initial_params_done
;
1163 * Must have either TargetName or SessionType==Discovery
1165 lsm
->icl_target_name
= NULL
;
1166 nvrc
= nvlist_lookup_string(lsm
->icl_request_nvlist
,
1167 "TargetName", &string_val
);
1168 if (nvrc
!= ENOENT
&& nvrc
!= 0) {
1169 goto initial_params_done
;
1172 u8_iscsi_name
= iscsit_fold_name(string_val
,
1173 &u8_iscsi_name_len
);
1174 if (u8_iscsi_name
== NULL
)
1175 goto initial_params_done
;
1176 nvrc
= nvlist_add_string(lsm
->icl_negotiated_values
,
1177 "TargetName", u8_iscsi_name
);
1178 kmem_free(u8_iscsi_name
, u8_iscsi_name_len
);
1180 goto initial_params_done
;
1181 if ((nvrc
= nvlist_lookup_string(lsm
->icl_negotiated_values
,
1182 "TargetName", &string_val
)) != 0) {
1183 goto initial_params_done
;
1185 lsm
->icl_target_name
= string_val
;
1186 idm_conn_set_target_name(ict
->ict_ic
, lsm
->icl_target_name
);
1187 if ((nvrc
= nvlist_remove(lsm
->icl_request_nvlist
,
1188 "TargetName", DATA_TYPE_STRING
)) != 0) {
1189 goto initial_params_done
;
1191 } else if (ict
->ict_op
.op_discovery_session
== B_FALSE
) {
1193 * Missing target name
1195 goto initial_params_done
;
1198 idm_conn_set_isid(ict
->ict_ic
, lsm
->icl_isid
);
1199 (void) snprintf(ict
->ict_ic
->ic_tsih
, ISCSI_MAX_TSIH_LEN
+ 1, "0x%04x",
1202 IDM_SM_LOG(CE_NOTE
, "conn %p: initiator=%s", (void *)ict
->ict_ic
,
1203 (lsm
->icl_initiator_name
== NULL
) ? "N/A" :
1204 lsm
->icl_initiator_name
);
1205 IDM_SM_LOG(CE_NOTE
, "conn %p: target=%s", (void *)ict
->ict_ic
,
1206 (lsm
->icl_target_name
== NULL
) ? "N/A" :
1207 lsm
->icl_target_name
);
1208 IDM_SM_LOG(CE_NOTE
, "conn %p: sessiontype=%s", (void *)ict
->ict_ic
,
1209 ict
->ict_op
.op_discovery_session
? "Discovery" : "Normal");
1212 status
= IDM_STATUS_SUCCESS
;
1213 error_class
= ISCSI_STATUS_CLASS_SUCCESS
;
1214 error_detail
= ISCSI_LOGIN_STATUS_ACCEPT
;
1216 initial_params_done
:
1217 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
1223 * login_sm_session_bind
1225 * This function looks at the data from the initial login request
1226 * of a new connection and either looks up and existing session,
1227 * creates a new session, or returns an error. RFC3720 section 5.3.1
1228 * defines these rules:
1230 * +------------------------------------------------------------------+
1231 * |ISID | TSIH | CID | Target action |
1232 * +------------------------------------------------------------------+
1233 * |new | non-zero | any | fail the login |
1234 * | | | | ("session does not exist") |
1235 * +------------------------------------------------------------------+
1236 * |new | zero | any | instantiate a new session |
1237 * +------------------------------------------------------------------+
1238 * |existing | zero | any | do session reinstatement |
1239 * | | | | (see section 5.3.5) |
1240 * +------------------------------------------------------------------+
1241 * |existing | non-zero | new | add a new connection to |
1242 * | | existing | | the session |
1243 * +------------------------------------------------------------------+
1244 * |existing | non-zero |existing| do connection reinstatement|
1245 * | | existing | | (see section 5.3.4) |
1246 * +------------------------------------------------------------------+
1247 * |existing | non-zero | any | fail the login |
1248 * | | new | | ("session does not exist") |
1249 * +------------------------------------------------------------------+
1254 * Map an <ipv6,port> address to an <ipv4,port> address if possible.
1257 * 0 - address not mapable
1261 iscsit_is_v4_mapped(struct sockaddr_storage
*sa
, struct sockaddr_storage
*v4sa
)
1263 struct sockaddr_in
*sin
;
1265 struct sockaddr_in6
*sin6
;
1266 struct in6_addr
*in6
;
1269 sin6
= (struct sockaddr_in6
*)sa
;
1270 in6
= &sin6
->sin6_addr
;
1271 if ((sa
->ss_family
== AF_INET6
) &&
1272 (IN6_IS_ADDR_V4MAPPED(in6
) || IN6_IS_ADDR_V4COMPAT(in6
))) {
1273 sin
= (struct sockaddr_in
*)v4sa
;
1274 in
= &sin
->sin_addr
;
1275 v4sa
->ss_family
= AF_INET
;
1276 sin
->sin_port
= sin6
->sin6_port
;
1277 IN6_V4MAPPED_TO_INADDR(in6
, in
);
1284 login_sm_session_bind(iscsit_conn_t
*ict
)
1286 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
1287 iscsit_tgt_t
*tgt
= NULL
;
1288 iscsit_tpgt_t
*tpgt
= NULL
;
1289 iscsit_portal_t
*portal
= NULL
;
1290 iscsit_sess_t
*existing_sess
= NULL
;
1291 iscsit_sess_t
*new_sess
= NULL
;
1292 iscsit_conn_t
*existing_ict
= NULL
;
1293 uint8_t error_class
;
1294 uint8_t error_detail
;
1297 * The multi-threaded execution of binding login sessions to target
1298 * introduced race conditions in the session creation/binding and
1299 * allowed duplicate sessions to tbe created. The addition of the
1300 * global mutex login_sm_session_mutex makes this function single
1301 * threaded to avoid such race conditions. Although this causes
1302 * a small portion of the login to be serialized, it is unlikely
1303 * that there would be numerous simultaneous logins to become a
1304 * performance issue.
1306 mutex_enter(&login_sm_session_mutex
);
1309 * Look up target and then check if there are sessions or connections
1310 * that match this request (see below). Any holds taken on objects
1311 * must be released at the end of the function (let's keep things
1314 * If target name is set then we should have a corresponding target
1315 * context configured.
1317 if (lsm
->icl_target_name
!= NULL
) {
1319 * iscsit_tgt_lookup implicitly takes a ref on the target
1321 ISCSIT_GLOBAL_LOCK(RW_READER
);
1322 tgt
= iscsit_tgt_lookup_locked(lsm
->icl_target_name
);
1324 ISCSIT_GLOBAL_UNLOCK();
1325 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1326 ISCSI_LOGIN_STATUS_TGT_NOT_FOUND
);
1327 goto session_bind_error
;
1329 mutex_enter(&tgt
->target_mutex
);
1330 tpgt
= avl_first(&tgt
->target_tpgt_list
);
1332 if (IS_DEFAULT_TPGT(tpgt
)) {
1333 lsm
->icl_tpgt_tag
= ISCSIT_DEFAULT_TPGT
;
1336 * Find the portal group tag for the
1339 struct sockaddr_storage v4sa
, *sa
;
1341 sa
= &ict
->ict_ic
->ic_laddr
;
1342 portal
= iscsit_tgt_lookup_portal(tgt
,
1344 if (portal
== NULL
&&
1345 iscsit_is_v4_mapped(sa
, &v4sa
)) {
1347 * Try again if the local address
1348 * was v6 mappable to v4.
1350 portal
= iscsit_tgt_lookup_portal(tgt
,
1354 if (portal
== NULL
) {
1356 * Initiator came in on wrong address
1358 SET_LOGIN_ERROR(ict
,
1359 ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1360 ISCSI_LOGIN_STATUS_TGT_NOT_FOUND
);
1361 mutex_exit(&tgt
->target_mutex
);
1362 ISCSIT_GLOBAL_UNLOCK();
1363 goto session_bind_error
;
1367 * Need to release holds on the portal and
1368 * tpgt after processing is complete.
1370 lsm
->icl_tpgt_tag
= tpgt
->tpgt_tag
;
1371 iscsit_portal_rele(portal
);
1372 iscsit_tpgt_rele(tpgt
);
1375 mutex_enter(&iscsit_global
.global_state_mutex
);
1376 if ((tgt
->target_state
!= TS_STMF_ONLINE
) ||
1377 ((iscsit_global
.global_svc_state
!= ISE_ENABLED
) &&
1378 ((iscsit_global
.global_svc_state
!= ISE_BUSY
)))) {
1379 mutex_exit(&iscsit_global
.global_state_mutex
);
1380 SET_LOGIN_ERROR(ict
,
1381 ISCSI_STATUS_CLASS_TARGET_ERR
,
1382 ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE
);
1383 mutex_exit(&tgt
->target_mutex
);
1384 ISCSIT_GLOBAL_UNLOCK();
1385 goto session_bind_error
;
1387 mutex_exit(&iscsit_global
.global_state_mutex
);
1388 mutex_exit(&tgt
->target_mutex
);
1389 ISCSIT_GLOBAL_UNLOCK();
1393 ASSERT((tgt
!= NULL
) || (ict
->ict_op
.op_discovery_session
== B_TRUE
));
1396 * Check if there is an existing session matching this ISID. If
1397 * tgt == NULL then we'll look for the session on the global list
1398 * of discovery session. If we find a session then the ISID
1401 existing_sess
= iscsit_tgt_lookup_sess(tgt
, lsm
->icl_initiator_name
,
1402 lsm
->icl_isid
, lsm
->icl_tsih
, lsm
->icl_tpgt_tag
);
1403 if (existing_sess
!= NULL
) {
1404 existing_ict
= iscsit_sess_lookup_conn(existing_sess
,
1409 * If this is a discovery session, make sure it has appropriate
1412 if ((ict
->ict_op
.op_discovery_session
== B_TRUE
) &&
1413 ((lsm
->icl_tsih
!= ISCSI_UNSPEC_TSIH
) || (existing_sess
!= NULL
))) {
1414 /* XXX Do we need to check for existing ISID (sess != NULL)? */
1415 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1416 ISCSI_LOGIN_STATUS_INVALID_REQUEST
);
1417 goto session_bind_error
;
1421 * Check the two error conditions from the table.
1423 * ISID=new, TSIH=non-zero
1425 if ((existing_sess
== NULL
) && (lsm
->icl_tsih
!= ISCSI_UNSPEC_TSIH
)) {
1426 /* fail the login */
1427 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1428 ISCSI_LOGIN_STATUS_NO_SESSION
);
1429 goto session_bind_error
;
1432 /* ISID=existing, TSIH=non-zero new */
1433 if ((existing_sess
!= NULL
) && (lsm
->icl_tsih
!= 0) &&
1434 (existing_sess
->ist_tsih
!= lsm
->icl_tsih
)) {
1435 /* fail the login */
1436 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1437 ISCSI_LOGIN_STATUS_NO_SESSION
);
1438 goto session_bind_error
;
1442 * Handle the remaining table cases in order
1444 if (existing_sess
== NULL
) {
1445 /* Should have caught this above */
1446 ASSERT(lsm
->icl_tsih
== ISCSI_UNSPEC_TSIH
);
1448 * ISID=new, TSIH=zero --> instantiate a new session
1450 new_sess
= iscsit_sess_create(tgt
, ict
, lsm
->icl_cmdsn
,
1451 lsm
->icl_isid
, lsm
->icl_tpgt_tag
, lsm
->icl_initiator_name
,
1452 lsm
->icl_target_name
, &error_class
, &error_detail
);
1453 ASSERT(new_sess
!= NULL
);
1455 /* Session create may have failed even if it returned a value */
1456 if (error_class
!= ISCSI_STATUS_CLASS_SUCCESS
) {
1457 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
1458 goto session_bind_error
;
1462 * If we don't already have an STMF session and this is not
1463 * a discovery session then we need to allocate and register
1466 if (!ict
->ict_op
.op_discovery_session
) {
1467 if (login_sm_session_register(ict
) !=
1468 IDM_STATUS_SUCCESS
) {
1469 /* login_sm_session_register sets error codes */
1470 goto session_bind_error
;
1475 if (lsm
->icl_tsih
== ISCSI_UNSPEC_TSIH
) {
1477 * ISID=existing, TSIH=zero --> Session reinstatement
1479 new_sess
= iscsit_sess_reinstate(tgt
, existing_sess
,
1480 ict
, &error_class
, &error_detail
);
1481 ASSERT(new_sess
!= NULL
);
1483 if (error_class
!= ISCSI_STATUS_CLASS_SUCCESS
) {
1484 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
1485 goto session_bind_error
;
1489 * If we don't already have an STMF session and this is
1490 * not a discovery session then we need to allocate and
1493 if (!ict
->ict_op
.op_discovery_session
) {
1494 if (login_sm_session_register(ict
) !=
1495 IDM_STATUS_SUCCESS
) {
1497 * login_sm_session_register sets
1500 goto session_bind_error
;
1505 * The following code covers these two cases:
1506 * ISID=existing, TSIH=non-zero existing, CID=new
1507 * --> add new connection to MC/S session
1508 * ISID=existing, TSIH=non-zero existing, CID=existing
1509 * --> do connection reinstatement
1511 * Session continuation uses this path as well
1513 cmn_err(CE_NOTE
, "login_sm_session_bind: add new "
1514 "conn/sess continue");
1515 if (existing_ict
!= NULL
) {
1517 * ISID=existing, TSIH=non-zero existing,
1518 * CID=existing --> do connection reinstatement
1520 if (iscsit_conn_reinstate(existing_ict
, ict
) !=
1521 IDM_STATUS_SUCCESS
) {
1523 * Most likely this means the connection
1524 * the initiator is trying to reinstate
1525 * is not in an acceptable state.
1527 SET_LOGIN_ERROR(ict
,
1528 ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1529 ISCSI_LOGIN_STATUS_INIT_ERR
);
1530 goto session_bind_error
;
1534 iscsit_sess_sm_event(existing_sess
, SE_CONN_IN_LOGIN
,
1540 iscsit_tgt_rele(tgt
);
1541 if (existing_sess
!= NULL
)
1542 iscsit_sess_rele(existing_sess
);
1543 if (existing_ict
!= NULL
)
1544 iscsit_conn_rele(existing_ict
);
1546 mutex_exit(&login_sm_session_mutex
);
1547 return (IDM_STATUS_SUCCESS
);
1551 iscsit_tgt_rele(tgt
);
1552 if (existing_sess
!= NULL
)
1553 iscsit_sess_rele(existing_sess
);
1554 if (existing_ict
!= NULL
)
1555 iscsit_conn_rele(existing_ict
);
1558 * If session bind fails we will fail the login but don't destroy
1559 * the session until later.
1561 mutex_exit(&login_sm_session_mutex
);
1562 return (IDM_STATUS_FAIL
);
1567 login_sm_set_auth(iscsit_conn_t
*ict
)
1569 idm_status_t idmrc
= IDM_STATUS_SUCCESS
;
1570 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
1574 char *radiusserver
= "";
1575 char *radiussecret
= "";
1576 char *chapuser
= "";
1577 char *chapsecret
= "";
1578 char *targetchapuser
= "";
1579 char *targetchapsecret
= "";
1580 char *targetalias
= "";
1583 ISCSIT_GLOBAL_LOCK(RW_READER
);
1586 * Set authentication method to none for discovery session.
1588 if (ict
->ict_op
.op_discovery_session
== B_TRUE
) {
1589 lsm
->icl_auth
.ca_method_valid_list
[0] = AM_NONE
;
1590 ISCSIT_GLOBAL_UNLOCK();
1595 * Get all the authentication parameters we need -- since we hold
1596 * the global config lock we guarantee that the parameters will
1597 * be consistent with each other.
1599 (void) nvlist_lookup_string(iscsit_global
.global_props
,
1601 (void) nvlist_lookup_string(iscsit_global
.global_props
,
1602 PROP_RADIUS_SERVER
, &radiusserver
);
1603 (void) nvlist_lookup_string(iscsit_global
.global_props
,
1604 PROP_RADIUS_SECRET
, &radiussecret
);
1606 ini
= iscsit_ini_lookup_locked(lsm
->icl_initiator_name
);
1608 /* Get Initiator CHAP parameters */
1609 (void) nvlist_lookup_string(ini
->ini_props
, PROP_CHAP_USER
,
1611 (void) nvlist_lookup_string(ini
->ini_props
, PROP_CHAP_SECRET
,
1615 tgt
= ict
->ict_sess
->ist_tgt
;
1617 /* See if we have a target-specific authentication setting */
1618 (void) nvlist_lookup_string(tgt
->target_props
, PROP_AUTH
,
1620 /* Get target CHAP parameters */
1621 (void) nvlist_lookup_string(tgt
->target_props
,
1622 PROP_TARGET_CHAP_USER
, &targetchapuser
);
1623 (void) nvlist_lookup_string(tgt
->target_props
,
1624 PROP_TARGET_CHAP_SECRET
, &targetchapsecret
);
1626 (void) nvlist_lookup_string(tgt
->target_props
,
1627 PROP_ALIAS
, &targetalias
);
1630 /* Set authentication method */
1632 if (strcmp(auth
, PA_AUTH_RADIUS
) == 0) {
1633 /* CHAP authentication using RADIUS server */
1634 lsm
->icl_auth
.ca_method_valid_list
[i
++] = AM_CHAP
;
1635 lsm
->icl_auth
.ca_use_radius
= B_TRUE
;
1636 } else if (strcmp(auth
, PA_AUTH_CHAP
) == 0) {
1637 /* Local CHAP authentication */
1638 lsm
->icl_auth
.ca_method_valid_list
[i
++] = AM_CHAP
;
1639 lsm
->icl_auth
.ca_use_radius
= B_FALSE
;
1640 } else if ((strcmp(auth
, PA_AUTH_NONE
) == 0) ||
1641 (strcmp(auth
, "") == 0)) {
1642 /* No authentication */
1643 lsm
->icl_auth
.ca_method_valid_list
[i
++] = AM_NONE
;
1647 * If initiator/target CHAP username is not set then use the
1648 * node name. If lsm->icl_target_name == NULL then this is
1649 * a discovery session so we don't need to work about the target.
1651 if (strcmp(chapuser
, "") == 0) {
1652 (void) strlcpy(lsm
->icl_auth
.ca_ini_chapuser
,
1653 lsm
->icl_initiator_name
,
1654 min(iscsitAuthStringMaxLength
, MAX_ISCSI_NODENAMELEN
));
1656 (void) strlcpy(lsm
->icl_auth
.ca_ini_chapuser
, chapuser
,
1657 iscsitAuthStringMaxLength
);
1659 if ((lsm
->icl_target_name
!= NULL
) &&
1660 (strcmp(targetchapuser
, "") == 0)) {
1661 (void) strlcpy(lsm
->icl_auth
.ca_tgt_chapuser
,
1662 lsm
->icl_target_name
,
1663 min(iscsitAuthStringMaxLength
, MAX_ISCSI_NODENAMELEN
));
1665 (void) strlcpy(lsm
->icl_auth
.ca_tgt_chapuser
,
1666 targetchapuser
, iscsitAuthStringMaxLength
);
1670 * Secrets are stored in base64-encoded format so we need to
1671 * decode them into binary form
1673 if (strcmp(chapsecret
, "") == 0) {
1674 lsm
->icl_auth
.ca_ini_chapsecretlen
= 0;
1676 if (iscsi_base64_str_to_binary(chapsecret
,
1677 strnlen(chapsecret
, iscsitAuthStringMaxLength
),
1678 lsm
->icl_auth
.ca_ini_chapsecret
, iscsitAuthStringMaxLength
,
1679 &lsm
->icl_auth
.ca_ini_chapsecretlen
) != 0) {
1680 cmn_err(CE_WARN
, "Corrupted CHAP secret"
1681 " for initiator %s", lsm
->icl_initiator_name
);
1682 lsm
->icl_auth
.ca_ini_chapsecretlen
= 0;
1685 if (strcmp(targetchapsecret
, "") == 0) {
1686 lsm
->icl_auth
.ca_tgt_chapsecretlen
= 0;
1688 if (iscsi_base64_str_to_binary(targetchapsecret
,
1689 strnlen(targetchapsecret
, iscsitAuthStringMaxLength
),
1690 lsm
->icl_auth
.ca_tgt_chapsecret
, iscsitAuthStringMaxLength
,
1691 &lsm
->icl_auth
.ca_tgt_chapsecretlen
) != 0) {
1692 cmn_err(CE_WARN
, "Corrupted CHAP secret"
1693 " for target %s", lsm
->icl_target_name
);
1694 lsm
->icl_auth
.ca_tgt_chapsecretlen
= 0;
1697 if (strcmp(radiussecret
, "") == 0) {
1698 lsm
->icl_auth
.ca_radius_secretlen
= 0;
1700 if (iscsi_base64_str_to_binary(radiussecret
,
1701 strnlen(radiussecret
, iscsitAuthStringMaxLength
),
1702 lsm
->icl_auth
.ca_radius_secret
, iscsitAuthStringMaxLength
,
1703 &lsm
->icl_auth
.ca_radius_secretlen
) != 0) {
1704 cmn_err(CE_WARN
, "Corrupted RADIUS secret");
1705 lsm
->icl_auth
.ca_radius_secretlen
= 0;
1712 (void) strlcpy(lsm
->icl_auth
.ca_tgt_alias
, targetalias
,
1713 MAX_ISCSI_NODENAMELEN
);
1716 * Now that authentication parameters are setup, validate the parameters
1717 * against the authentication mode
1718 * Decode RADIUS server value int lsm->icl_auth.ca_radius_server
1720 if ((strcmp(auth
, PA_AUTH_RADIUS
) == 0) &&
1721 ((lsm
->icl_auth
.ca_radius_secretlen
== 0) ||
1722 (strcmp(radiusserver
, "") == 0) ||
1723 it_common_convert_sa(radiusserver
,
1724 &lsm
->icl_auth
.ca_radius_server
,
1725 DEFAULT_RADIUS_PORT
) == NULL
)) {
1726 cmn_err(CE_WARN
, "RADIUS authentication selected "
1727 "for target %s but RADIUS parameters are not "
1728 "configured.", lsm
->icl_target_name
);
1729 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_TARGET_ERR
,
1730 ISCSI_LOGIN_STATUS_TARGET_ERROR
);
1731 idmrc
= IDM_STATUS_FAIL
;
1732 } else if ((strcmp(auth
, PA_AUTH_CHAP
) == 0) &&
1733 (lsm
->icl_auth
.ca_ini_chapsecretlen
== 0)) {
1734 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1735 ISCSI_LOGIN_STATUS_AUTH_FAILED
);
1736 idmrc
= IDM_STATUS_FAIL
;
1739 ISCSIT_GLOBAL_UNLOCK();
1746 login_sm_session_register(iscsit_conn_t
*ict
)
1748 iscsit_sess_t
*ist
= ict
->ict_sess
;
1749 stmf_scsi_session_t
*ss
;
1750 iscsi_transport_id_t
*iscsi_tptid
;
1751 uint16_t ident_len
, adn_len
, tptid_sz
;
1754 * Hold target mutex until we have finished registering with STMF
1756 mutex_enter(&ist
->ist_tgt
->target_mutex
);
1757 if (ist
->ist_tgt
->target_state
!= TS_STMF_ONLINE
) {
1758 mutex_exit(&ist
->ist_tgt
->target_mutex
);
1759 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_INITIATOR_ERR
,
1760 ISCSI_LOGIN_STATUS_TGT_REMOVED
);
1761 return (IDM_STATUS_FAIL
);
1764 ss
= stmf_alloc(STMF_STRUCT_SCSI_SESSION
, 0,
1767 mutex_exit(&ist
->ist_tgt
->target_mutex
);
1768 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_TARGET_ERR
,
1769 ISCSI_LOGIN_STATUS_NO_RESOURCES
);
1770 return (IDM_STATUS_FAIL
);
1773 ident_len
= strlen(ist
->ist_initiator_name
) + 1;
1774 ss
->ss_rport_id
= kmem_zalloc(sizeof (scsi_devid_desc_t
) +
1775 ident_len
, KM_SLEEP
);
1776 (void) strcpy((char *)ss
->ss_rport_id
->ident
, ist
->ist_initiator_name
);
1777 ss
->ss_rport_id
->ident_length
= ident_len
- 1;
1778 ss
->ss_rport_id
->protocol_id
= PROTOCOL_iSCSI
;
1779 ss
->ss_rport_id
->piv
= 1;
1780 ss
->ss_rport_id
->code_set
= CODE_SET_ASCII
;
1781 ss
->ss_rport_id
->association
= ID_IS_TARGET_PORT
;
1783 /* adn_len should be 4 byte aligned, SPC3 rev 23, section 7.54.6 */
1784 adn_len
= (ident_len
+ 3) & ~ 3;
1785 tptid_sz
= sizeof (iscsi_transport_id_t
) - 1 + adn_len
;
1786 ss
->ss_rport
= stmf_remote_port_alloc(tptid_sz
);
1787 ss
->ss_rport
->rport_tptid
->protocol_id
= PROTOCOL_iSCSI
;
1788 ss
->ss_rport
->rport_tptid
->format_code
= 0;
1789 iscsi_tptid
= (iscsi_transport_id_t
*)ss
->ss_rport
->rport_tptid
;
1790 SCSI_WRITE16(&iscsi_tptid
->add_len
, adn_len
);
1791 (void) strlcpy((char *)iscsi_tptid
->iscsi_name
,
1792 ist
->ist_initiator_name
, ident_len
);
1794 ss
->ss_lport
= ist
->ist_lport
;
1796 if (stmf_register_scsi_session(ict
->ict_sess
->ist_lport
, ss
) !=
1798 mutex_exit(&ist
->ist_tgt
->target_mutex
);
1799 kmem_free(ss
->ss_rport_id
,
1800 sizeof (scsi_devid_desc_t
) +
1801 strlen(ist
->ist_initiator_name
) + 1);
1802 stmf_remote_port_free(ss
->ss_rport
);
1804 SET_LOGIN_ERROR(ict
, ISCSI_STATUS_CLASS_TARGET_ERR
,
1805 ISCSI_LOGIN_STATUS_TARGET_ERROR
);
1806 return (IDM_STATUS_FAIL
);
1809 ss
->ss_port_private
= ict
->ict_sess
;
1810 ict
->ict_sess
->ist_stmf_sess
= ss
;
1811 mutex_exit(&ist
->ist_tgt
->target_mutex
);
1813 return (IDM_STATUS_SUCCESS
);
1818 login_sm_req_pdu_check(iscsit_conn_t
*ict
, idm_pdu_t
*pdu
)
1821 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
1822 iscsi_login_hdr_t
*lh
= (iscsi_login_hdr_t
*)pdu
->isp_hdr
;
1823 iscsi_login_rsp_hdr_t
*lh_resp
= lsm
->icl_login_resp_tmpl
;
1828 csg_req
= ISCSI_LOGIN_CURRENT_STAGE(lh
->flags
);
1830 case ISCSI_SECURITY_NEGOTIATION_STAGE
:
1831 case ISCSI_OP_PARMS_NEGOTIATION_STAGE
:
1832 if ((csg_req
!= lsm
->icl_login_csg
) &&
1833 (lsm
->icl_login_state
!= ILS_LOGIN_INIT
)) {
1835 * Inappropriate CSG change. Initiator can only
1836 * change CSG after we've responded with the
1837 * transit bit set. If we had responded with
1838 * a CSG change previous we would have updated
1841 * The exception is when we are in ILS_LOGIN_INIT
1842 * state since we haven't determined our initial
1845 goto pdu_check_fail
;
1848 case ISCSI_FULL_FEATURE_PHASE
:
1850 goto pdu_check_fail
;
1854 * If this is the first login PDU for a new connection then
1855 * the session will be NULL.
1857 if (ict
->ict_sess
!= NULL
) {
1859 * We've already created a session on a previous PDU. Make
1860 * sure this PDU is consistent with what we've already seen
1862 if ((ict
->ict_cid
!= ntohs(lh
->cid
)) ||
1863 (bcmp(ict
->ict_sess
->ist_isid
, lh
->isid
,
1864 ISCSI_ISID_LEN
) != 0)) {
1865 goto pdu_check_fail
;
1870 * Make sure we are compatible with the version range
1872 #if (ISCSIT_MAX_VERSION > 0)
1873 if ((lh
->min_version
> ISCSIT_MAX_VERSION
) ||
1874 (lh
->max_version
< ISCSIT_MIN_VERSION
)) {
1875 goto pdu_check_fail
;
1880 * Just in case the initiator changes things up on us along the way
1881 * check against our active_version -- we can't change the active
1882 * version and the initiator is not *supposed* to change its
1883 * min_version and max_version values so this should never happen.
1884 * Of course we only do this if the response header template has
1887 if ((lh_resp
->opcode
== ISCSI_OP_LOGIN_RSP
) && /* header valid */
1888 ((lh
->min_version
> lh_resp
->active_version
) ||
1889 (lh
->max_version
< lh_resp
->active_version
))) {
1890 goto pdu_check_fail
;
1893 return (IDM_STATUS_SUCCESS
);
1896 return (IDM_STATUS_FAIL
);
1900 login_sm_process_nvlist(iscsit_conn_t
*ict
)
1902 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
1906 nvpair_t
*negotiated_nvp
;
1908 uint8_t error_class
;
1909 uint8_t error_detail
;
1910 idm_status_t idm_status
;
1912 error_class
= ISCSI_STATUS_CLASS_SUCCESS
;
1913 error_detail
= ISCSI_LOGIN_STATUS_ACCEPT
;
1915 /* First, request that the transport process the list */
1916 kvrc
= idm_negotiate_key_values(ict
->ict_ic
, lsm
->icl_request_nvlist
,
1917 lsm
->icl_response_nvlist
, lsm
->icl_negotiated_values
);
1918 idm_kvstat_to_error(kvrc
, &error_class
, &error_detail
);
1919 if (error_class
!= ISCSI_STATUS_CLASS_SUCCESS
) {
1920 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
1921 idm_status
= IDM_STATUS_FAIL
;
1922 return (idm_status
);
1925 /* Ensure we clear transit bit if the transport layer has countered */
1926 if (kvrc
== KV_HANDLED_NO_TRANSIT
) {
1927 lsm
->icl_login_transit
= B_FALSE
;
1930 /* Prepend the declarative params */
1931 if (!ict
->ict_op
.op_declarative_params_set
&&
1932 lsm
->icl_login_csg
== ISCSI_OP_PARMS_NEGOTIATION_STAGE
) {
1933 if (iscsit_add_declarative_keys(ict
) != IDM_STATUS_SUCCESS
) {
1934 idm_status
= IDM_STATUS_FAIL
;
1935 return (idm_status
);
1937 ict
->ict_op
.op_declarative_params_set
= B_TRUE
;
1940 /* Now, move on and process the rest of the pairs */
1941 nvp
= nvlist_next_nvpair(lsm
->icl_request_nvlist
, NULL
);
1942 while (nvp
!= NULL
) {
1943 next_nvp
= nvlist_next_nvpair(lsm
->icl_request_nvlist
, nvp
);
1944 nvp_name
= nvpair_name(nvp
);
1946 * If we've already agreed upon a value then make sure this
1947 * is not attempting to change that value. From RFC3270
1950 * "Neither the initiator nor the target should attempt to
1951 * declare or negotiate a parameter more than once during
1952 * login except for responses to specific keys that
1953 * explicitly allow repeated key declarations (e.g.,
1954 * TargetAddress). An attempt to renegotiate/redeclare
1955 * parameters not specifically allowed MUST be detected
1956 * by the initiator and target. If such an attempt is
1957 * detected by the target, the target MUST respond
1958 * with Login reject (initiator error); ..."
1960 if (nvlist_lookup_nvpair(lsm
->icl_negotiated_values
,
1961 nvp_name
, &negotiated_nvp
) == 0) {
1964 kvrc
= iscsit_handle_key(ict
, nvp
, nvp_name
);
1967 idm_kvstat_to_error(kvrc
, &error_class
, &error_detail
);
1968 if (error_class
!= ISCSI_STATUS_CLASS_SUCCESS
) {
1975 if (error_class
== ISCSI_STATUS_CLASS_SUCCESS
) {
1976 idm_status
= IDM_STATUS_SUCCESS
;
1978 /* supply login class/detail for login errors */
1979 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
1980 idm_status
= IDM_STATUS_FAIL
;
1983 return (idm_status
);
1987 login_sm_check_security(iscsit_conn_t
*ict
)
1989 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
1990 conn_auth_t
*auth
= &lsm
->icl_auth
;
1991 iscsit_auth_method_t
*am_list
= &auth
->ca_method_valid_list
[0];
1993 uint8_t error_class
;
1994 uint8_t error_detail
;
1995 idm_status_t idm_status
;
1997 error_class
= ISCSI_STATUS_CLASS_SUCCESS
;
1998 error_detail
= ISCSI_LOGIN_STATUS_ACCEPT
;
2000 /* Check authentication status. */
2001 if (lsm
->icl_login_csg
== ISCSI_SECURITY_NEGOTIATION_STAGE
) {
2003 * We should have some authentication key/value pair(s)
2004 * received from initiator and the authentication phase
2005 * has been shifted when the key/value pair(s) are being
2006 * handled in the previous call iscsit_handle_security_key.
2007 * Now it turns to target to check the authentication phase
2008 * and shift it after taking some authentication action.
2010 kvrc
= iscsit_reply_security_key(ict
);
2011 idm_kvstat_to_error(kvrc
, &error_class
, &error_detail
);
2012 } else if (!ict
->ict_login_sm
.icl_auth_pass
) {
2014 * Check to see if the target allows initiators to bypass the
2015 * security check. If the target is configured to require
2016 * authentication, we reject the connection.
2018 if (am_list
[0] == AM_NONE
|| am_list
[0] == 0) {
2019 ict
->ict_login_sm
.icl_auth_pass
= 1;
2021 error_class
= ISCSI_STATUS_CLASS_INITIATOR_ERR
;
2022 error_detail
= ISCSI_LOGIN_STATUS_AUTH_FAILED
;
2026 if (error_class
== ISCSI_STATUS_CLASS_SUCCESS
) {
2027 idm_status
= IDM_STATUS_SUCCESS
;
2029 /* supply login class/detail for login errors */
2030 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
2031 idm_status
= IDM_STATUS_FAIL
;
2034 return (idm_status
);
2038 login_sm_build_login_response(iscsit_conn_t
*ict
)
2040 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2041 iscsi_login_rsp_hdr_t
*lh
;
2042 int transit
, text_transit
= 1;
2043 idm_pdu_t
*login_resp
;
2046 * Create a response PDU and fill it with as much of
2047 * the response text that will fit.
2050 if (lsm
->icl_login_resp_itb
) {
2051 /* allocate a pdu with space for text */
2052 login_resp
= idm_pdu_alloc(sizeof (iscsi_hdr_t
),
2053 ISCSI_DEFAULT_MAX_RECV_SEG_LEN
);
2054 /* copy a chunk of text into the pdu */
2055 lsm
->icl_login_resp_buf
= idm_pdu_init_text_data(
2056 login_resp
, lsm
->icl_login_resp_itb
,
2057 ISCSI_DEFAULT_MAX_RECV_SEG_LEN
,
2058 lsm
->icl_login_resp_buf
, &text_transit
);
2060 /* text buf has been consumed */
2061 idm_itextbuf_free(lsm
->icl_login_resp_itb
);
2062 lsm
->icl_login_resp_itb
= NULL
;
2063 lsm
->icl_login_resp_buf
= NULL
;
2066 /* allocate a pdu for just a header */
2067 login_resp
= idm_pdu_alloc(sizeof (iscsi_hdr_t
), 0);
2069 /* finish initializing the pdu */
2070 idm_pdu_init(login_resp
,
2071 ict
->ict_ic
, ict
, login_resp_complete_cb
);
2072 login_resp
->isp_flags
|= IDM_PDU_LOGIN_TX
;
2075 * Use the BHS header values from the response template
2077 bcopy(lsm
->icl_login_resp_tmpl
,
2078 login_resp
->isp_hdr
, sizeof (iscsi_login_rsp_hdr_t
));
2080 lh
= (iscsi_login_rsp_hdr_t
*)login_resp
->isp_hdr
;
2082 /* Set error class/detail */
2083 lh
->status_class
= lsm
->icl_login_resp_err_class
;
2084 lh
->status_detail
= lsm
->icl_login_resp_err_detail
;
2085 /* Set CSG, NSG and Transit */
2087 lh
->flags
|= lsm
->icl_login_csg
<< 2;
2090 if (lh
->status_class
== ISCSI_STATUS_CLASS_SUCCESS
) {
2091 if (lsm
->icl_login_transit
&&
2092 lsm
->icl_auth_pass
!= 0) {
2098 * inititalize the text data
2100 if (transit
== 1 && text_transit
== 1) {
2101 lh
->flags
|= lsm
->icl_login_nsg
;
2102 lsm
->icl_login_csg
= lsm
->icl_login_nsg
;
2103 lh
->flags
|= ISCSI_FLAG_LOGIN_TRANSIT
;
2105 lh
->flags
&= ~ISCSI_FLAG_LOGIN_TRANSIT
;
2108 /* If we are transitioning to FFP then set TSIH */
2109 if (transit
&& (lh
->flags
& ISCSI_FLAG_LOGIN_TRANSIT
) &&
2110 lsm
->icl_login_csg
== ISCSI_FULL_FEATURE_PHASE
) {
2111 lh
->tsid
= htons(ict
->ict_sess
->ist_tsih
);
2114 login_resp
->isp_data
= 0;
2115 login_resp
->isp_datalen
= 0;
2117 return (login_resp
);
2121 iscsit_handle_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
, char *nvp_name
)
2123 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2125 const idm_kv_xlate_t
*ikvx
;
2127 ikvx
= idm_lookup_kv_xlate(nvp_name
, strlen(nvp_name
));
2128 if (ikvx
->ik_key_id
== KI_MAX_KEY
) {
2130 * Any key not understood by the acceptor may be igonred
2131 * by the acceptor without affecting the basic function.
2132 * However, the answer for a key not understood MUST be
2133 * key=NotUnderstood.
2135 kvrc
= iscsit_reply_string(ict
, nvp_name
,
2136 ISCSI_TEXT_NOTUNDERSTOOD
);
2138 kvrc
= iscsit_handle_common_key(ict
, nvp
, ikvx
);
2139 if (kvrc
== KV_UNHANDLED
) {
2140 switch (lsm
->icl_login_csg
) {
2141 case ISCSI_SECURITY_NEGOTIATION_STAGE
:
2142 kvrc
= iscsit_handle_security_key(
2145 case ISCSI_OP_PARMS_NEGOTIATION_STAGE
:
2146 kvrc
= iscsit_handle_operational_key(
2149 case ISCSI_FULL_FEATURE_PHASE
:
2151 /* What are we doing here? */
2153 kvrc
= KV_UNHANDLED
;
2162 iscsit_handle_common_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
,
2163 const idm_kv_xlate_t
*ikvx
)
2165 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2170 switch (ikvx
->ik_key_id
) {
2171 case KI_INITIATOR_NAME
:
2172 case KI_INITIATOR_ALIAS
:
2173 nvrc
= nvlist_add_nvpair(lsm
->icl_negotiated_values
, nvp
);
2174 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2176 case KI_TARGET_NAME
:
2177 /* We'll validate the target during login_sm_session_bind() */
2178 nvrc
= nvpair_value_string(nvp
, &string_val
);
2179 ASSERT(nvrc
== 0); /* We built this nvlist */
2181 nvrc
= nvlist_add_nvpair(lsm
->icl_negotiated_values
, nvp
);
2182 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2184 case KI_TARGET_ALIAS
:
2185 case KI_TARGET_ADDRESS
:
2186 case KI_TARGET_PORTAL_GROUP_TAG
:
2187 kvrc
= KV_TARGET_ONLY
; /* Only the target can declare this */
2189 case KI_SESSION_TYPE
:
2191 * If we don't receive this key on the initial login
2192 * we assume this is a normal session.
2194 nvrc
= nvlist_add_nvpair(lsm
->icl_negotiated_values
, nvp
);
2195 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2196 nvrc
= nvpair_value_string(nvp
, &string_val
);
2197 ASSERT(nvrc
== 0); /* We built this nvlist */
2198 ict
->ict_op
.op_discovery_session
=
2199 strcmp(string_val
, "Discovery") == 0 ? B_TRUE
: B_FALSE
;
2203 * This is not really an error but we should
2204 * leave this nvpair on the list since we
2205 * didn't do anything with it. Either
2206 * the security or operational phase
2207 * handling functions should process it.
2209 kvrc
= KV_UNHANDLED
;
2217 iscsit_handle_security_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
,
2218 const idm_kv_xlate_t
*ikvx
)
2220 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2221 iscsit_auth_client_t
*client
= &lsm
->icl_auth_client
;
2222 iscsikey_id_t kv_id
;
2224 iscsit_auth_handler_t handler
;
2227 * After all of security keys are handled, this function will
2228 * be called again to verify current authentication status
2229 * and perform some actual authentication work. At this time,
2230 * the nvp and ikvx will be passed in as NULLs.
2233 kv_id
= ikvx
->ik_key_id
;
2238 handler
= iscsit_auth_get_handler(client
, kv_id
);
2240 kvrc
= handler(ict
, nvp
, ikvx
);
2242 kvrc
= KV_UNHANDLED
; /* invalid request */
2249 iscsit_reply_security_key(iscsit_conn_t
*ict
)
2251 return (iscsit_handle_security_key(ict
, NULL
, NULL
));
2255 iscsit_handle_operational_key(iscsit_conn_t
*ict
, nvpair_t
*nvp
,
2256 const idm_kv_xlate_t
*ikvx
)
2258 kv_status_t kvrc
= KV_UNHANDLED
;
2264 * Retrieve values. All value lookups are expected to succeed
2265 * since we build the nvlist while decoding the text buffer. This
2266 * step is intended to eliminate some duplication of code (for example
2267 * we only need to code the numerical value lookup once). We will
2268 * handle the values (if necessary) below.
2270 switch (ikvx
->ik_key_id
) {
2272 case KI_HEADER_DIGEST
:
2273 case KI_DATA_DIGEST
:
2276 case KI_INITIAL_R2T
:
2277 case KI_IMMEDIATE_DATA
:
2278 case KI_DATA_PDU_IN_ORDER
:
2279 case KI_DATA_SEQUENCE_IN_ORDER
:
2282 nvrc
= nvpair_value_boolean_value(nvp
, &bool_val
);
2283 ASSERT(nvrc
== 0); /* We built this nvlist */
2286 case KI_MAX_CONNECTIONS
:
2287 case KI_MAX_RECV_DATA_SEGMENT_LENGTH
:
2288 case KI_MAX_BURST_LENGTH
:
2289 case KI_FIRST_BURST_LENGTH
:
2290 case KI_DEFAULT_TIME_2_WAIT
:
2291 case KI_DEFAULT_TIME_2_RETAIN
:
2292 case KI_MAX_OUTSTANDING_R2T
:
2293 case KI_ERROR_RECOVERY_LEVEL
:
2294 nvrc
= nvpair_value_uint64(nvp
, &num_val
);
2298 case KI_OFMARKERINT
:
2299 case KI_IFMARKERINT
:
2306 * Now handle the values according to the key name. Sometimes we
2307 * don't care what the value is -- in that case we just add the nvpair
2308 * to the negotiated values list.
2310 switch (ikvx
->ik_key_id
) {
2311 case KI_HEADER_DIGEST
:
2312 kvrc
= iscsit_handle_digest(ict
, nvp
, ikvx
);
2314 case KI_DATA_DIGEST
:
2315 kvrc
= iscsit_handle_digest(ict
, nvp
, ikvx
);
2317 case KI_INITIAL_R2T
:
2318 /* We *require* INITIAL_R2T=yes */
2319 kvrc
= iscsit_handle_boolean(ict
, nvp
, bool_val
, ikvx
,
2322 case KI_IMMEDIATE_DATA
:
2323 kvrc
= iscsit_handle_boolean(ict
, nvp
, bool_val
, ikvx
,
2326 case KI_DATA_PDU_IN_ORDER
:
2327 kvrc
= iscsit_handle_boolean(ict
, nvp
, bool_val
, ikvx
,
2330 case KI_DATA_SEQUENCE_IN_ORDER
:
2331 /* We allow any value for DATA_SEQUENCE_IN_ORDER */
2332 kvrc
= iscsit_handle_boolean(ict
, nvp
, bool_val
, ikvx
,
2337 /* We don't support markers */
2338 kvrc
= iscsit_handle_boolean(ict
, nvp
, bool_val
, ikvx
,
2341 case KI_MAX_CONNECTIONS
:
2342 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2343 ISCSI_MIN_CONNECTIONS
,
2344 ISCSI_MAX_CONNECTIONS
,
2345 ISCSIT_MAX_CONNECTIONS
);
2347 /* this is a declartive param */
2348 case KI_MAX_RECV_DATA_SEGMENT_LENGTH
:
2349 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2350 ISCSI_MIN_RECV_DATA_SEGMENT_LENGTH
,
2351 ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH
,
2352 ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH
);
2354 case KI_MAX_BURST_LENGTH
:
2355 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2356 ISCSI_MIN_MAX_BURST_LENGTH
,
2357 ISCSI_MAX_BURST_LENGTH
,
2358 ISCSIT_MAX_BURST_LENGTH
);
2360 case KI_FIRST_BURST_LENGTH
:
2361 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2362 ISCSI_MIN_FIRST_BURST_LENGTH
,
2363 ISCSI_MAX_FIRST_BURST_LENGTH
,
2364 ISCSIT_MAX_FIRST_BURST_LENGTH
);
2366 case KI_DEFAULT_TIME_2_WAIT
:
2367 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2368 ISCSI_MIN_TIME2WAIT
,
2369 ISCSI_MAX_TIME2WAIT
,
2370 ISCSIT_MAX_TIME2WAIT
);
2372 case KI_DEFAULT_TIME_2_RETAIN
:
2373 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2374 ISCSI_MIN_TIME2RETAIN
,
2375 ISCSI_MAX_TIME2RETAIN
,
2376 ISCSIT_MAX_TIME2RETAIN
);
2378 case KI_MAX_OUTSTANDING_R2T
:
2379 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2380 ISCSI_MIN_MAX_OUTSTANDING_R2T
,
2381 ISCSI_MAX_OUTSTANDING_R2T
,
2382 ISCSIT_MAX_OUTSTANDING_R2T
);
2384 case KI_ERROR_RECOVERY_LEVEL
:
2385 kvrc
= iscsit_handle_numerical(ict
, nvp
, num_val
, ikvx
,
2386 ISCSI_MIN_ERROR_RECOVERY_LEVEL
,
2387 ISCSI_MAX_ERROR_RECOVERY_LEVEL
,
2388 ISCSIT_MAX_ERROR_RECOVERY_LEVEL
);
2390 case KI_OFMARKERINT
:
2391 case KI_IFMARKERINT
:
2392 kvrc
= iscsit_reply_string(ict
, ikvx
->ik_key_name
,
2393 ISCSI_TEXT_IRRELEVANT
);
2396 kvrc
= KV_UNHANDLED
; /* invalid request */
2404 iscsit_reply_numerical(iscsit_conn_t
*ict
,
2405 const char *nvp_name
, const uint64_t value
)
2407 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2411 nvrc
= nvlist_add_uint64(lsm
->icl_response_nvlist
,
2413 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2419 iscsit_reply_string(iscsit_conn_t
*ict
,
2420 const char *nvp_name
, const char *text
)
2422 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2426 nvrc
= nvlist_add_string(lsm
->icl_response_nvlist
,
2428 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2434 iscsit_handle_digest(iscsit_conn_t
*ict
, nvpair_t
*choices
,
2435 const idm_kv_xlate_t
*ikvx
)
2437 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2438 kv_status_t kvrc
= KV_VALUE_ERROR
;
2440 nvpair_t
*digest_choice
;
2441 char *digest_choice_string
;
2444 * Need to add persistent config here if we want users to allow
2445 * disabling of digests on the target side. You could argue that
2446 * this makes things too complicated... just let the initiator state
2447 * what it wants and we'll take it. For now that's exactly what
2450 * Basic digest negotiation happens here at iSCSI level. IDM
2451 * can override this during negotiate_key_values phase to
2452 * decline to set up any digest processing.
2454 digest_choice
= idm_get_next_listvalue(choices
, NULL
);
2457 * Loop through all choices. As soon as we find a choice
2458 * that we support add the value to our negotiated values list
2459 * and respond with that value in the login response.
2461 while (digest_choice
!= NULL
) {
2462 nvrc
= nvpair_value_string(digest_choice
,
2463 &digest_choice_string
);
2466 if ((strcasecmp(digest_choice_string
, "crc32c") == 0) ||
2467 (strcasecmp(digest_choice_string
, "none") == 0)) {
2468 /* Add to negotiated values list */
2469 nvrc
= nvlist_add_string(lsm
->icl_negotiated_values
,
2470 ikvx
->ik_key_name
, digest_choice_string
);
2471 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2473 /* Add to login response list */
2474 nvrc
= nvlist_add_string(
2475 lsm
->icl_response_nvlist
,
2476 ikvx
->ik_key_name
, digest_choice_string
);
2477 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2481 digest_choice
= idm_get_next_listvalue(choices
,
2485 if (digest_choice
== NULL
)
2486 kvrc
= KV_VALUE_ERROR
;
2492 iscsit_handle_boolean(iscsit_conn_t
*ict
, nvpair_t
*nvp
, boolean_t value
,
2493 const idm_kv_xlate_t
*ikvx
, boolean_t iscsit_value
)
2495 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2499 if (ikvx
->ik_declarative
) {
2500 nvrc
= nvlist_add_nvpair(lsm
->icl_negotiated_values
, nvp
);
2502 if (value
!= iscsit_value
) {
2503 /* Respond back to initiator with our value */
2504 value
= iscsit_value
;
2505 nvrc
= nvlist_add_boolean_value(
2506 lsm
->icl_negotiated_values
,
2507 ikvx
->ik_key_name
, value
);
2508 lsm
->icl_login_transit
= B_FALSE
;
2510 /* Add this to our negotiated values */
2511 nvrc
= nvlist_add_nvpair(lsm
->icl_negotiated_values
,
2515 /* Response of Simple-value Negotiation */
2517 nvrc
= nvlist_add_boolean_value(
2518 lsm
->icl_response_nvlist
, ikvx
->ik_key_name
, value
);
2522 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2528 iscsit_handle_numerical(iscsit_conn_t
*ict
, nvpair_t
*nvp
, uint64_t value
,
2529 const idm_kv_xlate_t
*ikvx
,
2530 uint64_t iscsi_min_value
, uint64_t iscsi_max_value
,
2531 uint64_t iscsit_max_value
)
2533 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2537 /* Validate against standard */
2538 if ((value
< iscsi_min_value
) || (value
> iscsi_max_value
)) {
2539 kvrc
= KV_VALUE_ERROR
;
2540 } else if (ikvx
->ik_declarative
) {
2541 nvrc
= nvlist_add_nvpair(lsm
->icl_negotiated_values
, nvp
);
2542 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2544 if (value
> iscsit_max_value
) {
2545 /* Respond back to initiator with our value */
2546 value
= iscsit_max_value
;
2547 nvrc
= nvlist_add_uint64(lsm
->icl_negotiated_values
,
2548 ikvx
->ik_key_name
, value
);
2549 lsm
->icl_login_transit
= B_FALSE
;
2551 /* Add this to our negotiated values */
2552 nvrc
= nvlist_add_nvpair(lsm
->icl_negotiated_values
,
2556 /* Response of Simple-value Negotiation */
2558 nvrc
= nvlist_add_uint64(lsm
->icl_response_nvlist
,
2559 ikvx
->ik_key_name
, value
);
2561 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2569 iscsit_process_negotiated_values(iscsit_conn_t
*ict
)
2571 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2573 boolean_t boolean_val
;
2574 uint64_t uint64_val
;
2577 /* Let the IDM level activate its parameters first */
2578 idm_notice_key_values(ict
->ict_ic
, lsm
->icl_negotiated_values
);
2581 * Initiator alias and target alias
2583 if ((nvrc
= nvlist_lookup_string(lsm
->icl_negotiated_values
,
2584 "InitiatorAlias", &string_val
)) != ENOENT
) {
2586 ict
->ict_sess
->ist_initiator_alias
=
2587 kmem_alloc(strlen(string_val
) + 1, KM_SLEEP
);
2588 (void) strcpy(ict
->ict_sess
->ist_initiator_alias
, string_val
);
2589 if (ict
->ict_sess
->ist_stmf_sess
)
2590 ict
->ict_sess
->ist_stmf_sess
->ss_rport_alias
=
2594 if ((nvrc
= nvlist_lookup_string(lsm
->icl_negotiated_values
,
2595 "TargetAlias", &string_val
)) != ENOENT
) {
2597 ict
->ict_sess
->ist_target_alias
=
2598 kmem_alloc(strlen(string_val
) + 1, KM_SLEEP
);
2599 (void) strcpy(ict
->ict_sess
->ist_target_alias
, string_val
);
2603 * Operational parameters. We process SessionType when it is
2604 * initially received since it is required on the initial login.
2606 if ((nvrc
= nvlist_lookup_boolean_value(lsm
->icl_negotiated_values
,
2607 "InitialR2T", &boolean_val
)) != ENOENT
) {
2609 ict
->ict_op
.op_initial_r2t
= boolean_val
;
2612 if ((nvrc
= nvlist_lookup_boolean_value(lsm
->icl_negotiated_values
,
2613 "ImmediateData", &boolean_val
)) != ENOENT
) {
2615 ict
->ict_op
.op_immed_data
= boolean_val
;
2618 if ((nvrc
= nvlist_lookup_boolean_value(lsm
->icl_negotiated_values
,
2619 "DataPDUInOrder", &boolean_val
)) != ENOENT
) {
2621 ict
->ict_op
.op_data_pdu_in_order
= boolean_val
;
2624 if ((nvrc
= nvlist_lookup_boolean_value(lsm
->icl_negotiated_values
,
2625 "DataSequenceInOrder", &boolean_val
)) != ENOENT
) {
2627 ict
->ict_op
.op_data_sequence_in_order
= boolean_val
;
2630 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2631 "MaxConnections", &uint64_val
)) != ENOENT
) {
2633 ict
->ict_op
.op_max_connections
= uint64_val
;
2636 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2637 "MaxRecvDataSegmentLength", &uint64_val
)) != ENOENT
) {
2639 ict
->ict_op
.op_max_recv_data_segment_length
= uint64_val
;
2642 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2643 "MaxBurstLength", &uint64_val
)) != ENOENT
) {
2645 ict
->ict_op
.op_max_burst_length
= uint64_val
;
2648 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2649 "FirstBurstLength", &uint64_val
)) != ENOENT
) {
2651 ict
->ict_op
.op_first_burst_length
= uint64_val
;
2654 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2655 "DefaultTime2Wait", &uint64_val
)) != ENOENT
) {
2657 ict
->ict_op
.op_default_time_2_wait
= uint64_val
;
2660 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2661 "DefaultTime2Retain", &uint64_val
)) != ENOENT
) {
2663 ict
->ict_op
.op_default_time_2_retain
= uint64_val
;
2666 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2667 "MaxOutstandingR2T", &uint64_val
)) != ENOENT
) {
2669 ict
->ict_op
.op_max_outstanding_r2t
= uint64_val
;
2672 if ((nvrc
= nvlist_lookup_uint64(lsm
->icl_negotiated_values
,
2673 "ErrorRecoveryLevel", &uint64_val
)) != ENOENT
) {
2675 ict
->ict_op
.op_error_recovery_level
= uint64_val
;
2680 iscsit_add_declarative_keys(iscsit_conn_t
*ict
)
2682 nvlist_t
*cfg_nv
= NULL
;
2685 iscsit_conn_login_t
*lsm
= &ict
->ict_login_sm
;
2686 uint8_t error_class
;
2687 uint8_t error_detail
;
2688 idm_status_t idm_status
;
2690 if ((nvrc
= nvlist_alloc(&cfg_nv
, NV_UNIQUE_NAME
, KM_NOSLEEP
)) != 0) {
2691 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2694 if ((nvrc
= nvlist_add_uint64(cfg_nv
, "MaxRecvDataSegmentLength",
2695 max_dataseglen_target
)) != 0) {
2696 kvrc
= idm_nvstat_to_kvstat(nvrc
);
2700 kvrc
= idm_declare_key_values(ict
->ict_ic
, cfg_nv
,
2701 lsm
->icl_response_nvlist
);
2703 nvlist_free(cfg_nv
);
2705 idm_kvstat_to_error(kvrc
, &error_class
, &error_detail
);
2706 if (error_class
== ISCSI_STATUS_CLASS_SUCCESS
) {
2707 idm_status
= IDM_STATUS_SUCCESS
;
2709 SET_LOGIN_ERROR(ict
, error_class
, error_detail
);
2710 idm_status
= IDM_STATUS_FAIL
;
2712 return (idm_status
);
2716 iscsit_fold_name(char *name
, size_t *buflen
)
2721 int flag
= U8_TEXTPREP_NFKC
;
2722 size_t inlen
, outlen
, coff
;
2727 /* Check for one of the supported name types */
2728 if (strncasecmp(name
, SNS_EUI
".", strlen(SNS_EUI
) + 1) == 0) {
2730 *buflen
= SNS_EUI_U8_LEN_MAX
+ 1;
2731 flag
|= U8_TEXTPREP_TOUPPER
;
2732 } else if (strncasecmp(name
, SNS_IQN
".", strlen(SNS_IQN
) + 1) == 0) {
2734 *buflen
= SNS_IQN_U8_LEN_MAX
+ 1;
2735 flag
|= U8_TEXTPREP_TOLOWER
;
2736 } else if (strncasecmp(name
, SNS_NAA
".", strlen(SNS_NAA
) + 1) == 0) {
2738 *buflen
= SNS_NAA_U8_LEN_MAX
+ 1;
2739 flag
|= U8_TEXTPREP_TOUPPER
;
2744 ret
= kmem_zalloc(*buflen
, KM_SLEEP
);
2746 inlen
= strlen(name
) - coff
;
2747 outlen
= *buflen
- coff
;
2749 /* Fold the case and normalize string */
2750 if (u8_textprep_str(name
+ coff
, &inlen
, ret
+ coff
, &outlen
, flag
,
2751 U8_UNICODE_320
, &errnum
) == (size_t)-1) {
2752 kmem_free(ret
, *buflen
);
2756 /* Copy the name type prefix */
2757 bcopy(sns
, ret
, coff
);