iscsit_login.c (9586:bd5e99a50121) iscsit_login.c (9601:e0ed15140e6d)
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

--- 91 unchanged lines hidden (view full) ---

100
101static void
102login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu);
103
104static idm_status_t
105login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu);
106
107static boolean_t
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

--- 91 unchanged lines hidden (view full) ---

100
101static void
102login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu);
103
104static idm_status_t
105login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu);
106
107static boolean_t
108login_sm_is_last_response(iscsit_conn_t *ict);
108login_sm_is_last_response(idm_pdu_t *pdu);
109
110static void
111login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu);
112
113static void
109
110static void
111login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu);
112
113static void
114login_sm_send_next_response(iscsit_conn_t *ict);
114login_sm_send_next_response(iscsit_conn_t *ict, idm_pdu_t *pdu);
115
116static void
117login_sm_process_request(iscsit_conn_t *ict);
118
119static idm_status_t
120login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu);
121
122static idm_status_t
123login_sm_process_nvlist(iscsit_conn_t *ict);
124
125static idm_status_t
126login_sm_check_security(iscsit_conn_t *ict);
127
115
116static void
117login_sm_process_request(iscsit_conn_t *ict);
118
119static idm_status_t
120login_sm_req_pdu_check(iscsit_conn_t *ict, idm_pdu_t *pdu);
121
122static idm_status_t
123login_sm_process_nvlist(iscsit_conn_t *ict);
124
125static idm_status_t
126login_sm_check_security(iscsit_conn_t *ict);
127
128static void
128static idm_pdu_t *
129login_sm_build_login_response(iscsit_conn_t *ict);
130
131static void
132login_sm_ffp_actions(iscsit_conn_t *ict);
133
134static idm_status_t
135login_sm_validate_initial_parameters(iscsit_conn_t *ict);
136

--- 54 unchanged lines hidden (view full) ---

191
192idm_status_t
193iscsit_login_sm_init(iscsit_conn_t *ict)
194{
195 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
196
197 bzero(lsm, sizeof (iscsit_conn_login_t));
198
129login_sm_build_login_response(iscsit_conn_t *ict);
130
131static void
132login_sm_ffp_actions(iscsit_conn_t *ict);
133
134static idm_status_t
135login_sm_validate_initial_parameters(iscsit_conn_t *ict);
136

--- 54 unchanged lines hidden (view full) ---

191
192idm_status_t
193iscsit_login_sm_init(iscsit_conn_t *ict)
194{
195 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
196
197 bzero(lsm, sizeof (iscsit_conn_login_t));
198
199 /* initialize the response pdu */
200 ict->ict_login_sm.icl_login_resp =
201 idm_pdu_alloc(sizeof (iscsi_hdr_t), 0);
202 if (ict->ict_login_sm.icl_login_resp == NULL) {
203 return (IDM_STATUS_FAIL);
204 }
205 idm_pdu_init(ict->ict_login_sm.icl_login_resp,
206 ict->ict_ic, ict, login_resp_complete_cb);
207 lsm->icl_login_resp->isp_flags |= IDM_PDU_LOGIN_TX;
208
209 (void) nvlist_alloc(&lsm->icl_negotiated_values, NV_UNIQUE_NAME,
210 KM_SLEEP);
211
212 /*
213 * Hold connection until the login state machine completes
214 */
215 iscsit_conn_hold(ict);
216

--- 40 unchanged lines hidden (view full) ---

257 return (IDM_STATUS_SUCCESS);
258}
259
260static void
261login_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status)
262{
263 iscsit_conn_t *ict = pdu->isp_private;
264
199 (void) nvlist_alloc(&lsm->icl_negotiated_values, NV_UNIQUE_NAME,
200 KM_SLEEP);
201
202 /*
203 * Hold connection until the login state machine completes
204 */
205 iscsit_conn_hold(ict);
206

--- 40 unchanged lines hidden (view full) ---

247 return (IDM_STATUS_SUCCESS);
248}
249
250static void
251login_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status)
252{
253 iscsit_conn_t *ict = pdu->isp_private;
254
265 ASSERT(ict->ict_login_sm.icl_login_resp == pdu);
266 /*
255 /*
267 * The icl_login_resp response buffer should only ever be used
268 * during the LOGIN phase.
256 * Check that this is a login pdu
269 */
270 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0);
257 */
258 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0);
259 idm_pdu_free(pdu);
271
272 if ((status != IDM_STATUS_SUCCESS) ||
273 (ict->ict_login_sm.icl_login_resp_err_class != 0)) {
260
261 if ((status != IDM_STATUS_SUCCESS) ||
262 (ict->ict_login_sm.icl_login_resp_err_class != 0)) {
263 /*
264 * Transport or login error occurred.
265 */
274 iscsit_login_sm_event(ict, ILE_LOGIN_ERROR, NULL);
266 iscsit_login_sm_event(ict, ILE_LOGIN_ERROR, NULL);
275 } else if (login_sm_is_last_response(ict) == B_TRUE) {
276 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_COMPLETE, NULL);
277 }
267 }
268 iscsit_conn_rele(ict);
278}
279
280void
281iscsit_login_sm_fini(iscsit_conn_t *ict)
282{
283 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
284
285 mutex_enter(&lsm->icl_mutex);
286 list_destroy(&lsm->icl_pdu_list);
287 list_destroy(&lsm->icl_login_events);
269}
270
271void
272iscsit_login_sm_fini(iscsit_conn_t *ict)
273{
274 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
275
276 mutex_enter(&lsm->icl_mutex);
277 list_destroy(&lsm->icl_pdu_list);
278 list_destroy(&lsm->icl_login_events);
288 mutex_exit(&lsm->icl_mutex);
289 mutex_destroy(&lsm->icl_mutex);
290
291 kmem_free(lsm->icl_login_resp_tmpl, sizeof (iscsi_login_rsp_hdr_t));
279
280 kmem_free(lsm->icl_login_resp_tmpl, sizeof (iscsi_login_rsp_hdr_t));
292 idm_pdu_free(lsm->icl_login_resp);
293
294 /* clean up the login response idm text buffer */
295 if (lsm->icl_login_resp_itb != NULL) {
296 idm_itextbuf_free(lsm->icl_login_resp_itb);
297 lsm->icl_login_resp_itb = NULL;
298 }
299
300 nvlist_free(lsm->icl_negotiated_values);
281
282 /* clean up the login response idm text buffer */
283 if (lsm->icl_login_resp_itb != NULL) {
284 idm_itextbuf_free(lsm->icl_login_resp_itb);
285 lsm->icl_login_resp_itb = NULL;
286 }
287
288 nvlist_free(lsm->icl_negotiated_values);
301 iscsit_conn_rele(ict);
289 mutex_destroy(&lsm->icl_mutex);
302}
303
304void
305iscsit_login_sm_event(iscsit_conn_t *ict, iscsit_login_event_t event,
306 idm_pdu_t *pdu)
307{
308 /*
309 * This is a bit ugly but if we're already in ILS_LOGIN_ERROR

--- 11 unchanged lines hidden (view full) ---

321}
322void
323iscsit_login_sm_event_locked(iscsit_conn_t *ict, iscsit_login_event_t event,
324 idm_pdu_t *pdu)
325{
326 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
327 login_event_ctx_t *ctx;
328
290}
291
292void
293iscsit_login_sm_event(iscsit_conn_t *ict, iscsit_login_event_t event,
294 idm_pdu_t *pdu)
295{
296 /*
297 * This is a bit ugly but if we're already in ILS_LOGIN_ERROR

--- 11 unchanged lines hidden (view full) ---

309}
310void
311iscsit_login_sm_event_locked(iscsit_conn_t *ict, iscsit_login_event_t event,
312 idm_pdu_t *pdu)
313{
314 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
315 login_event_ctx_t *ctx;
316
317 ASSERT(mutex_owned(&lsm->icl_mutex));
329 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
330
331 ctx->le_ctx_event = event;
332 ctx->le_pdu = pdu;
333
334 list_insert_tail(&lsm->icl_login_events, ctx);
335
336 /*

--- 47 unchanged lines hidden (view full) ---

384}
385
386static void
387login_sm_complete(void *ict_void)
388{
389 iscsit_conn_t *ict = ict_void;
390
391 /*
318 ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
319
320 ctx->le_ctx_event = event;
321 ctx->le_pdu = pdu;
322
323 list_insert_tail(&lsm->icl_login_events, ctx);
324
325 /*

--- 47 unchanged lines hidden (view full) ---

373}
374
375static void
376login_sm_complete(void *ict_void)
377{
378 iscsit_conn_t *ict = ict_void;
379
380 /*
392 * State machine has run to completion, release state machine resources
381 * State machine has run to completion, resources
382 * will be cleaned up when connection is destroyed.
393 */
383 */
394 iscsit_login_sm_fini(ict);
384 iscsit_conn_rele(ict);
395}
396
397static void
398login_sm_event_dispatch(iscsit_conn_login_t *lsm, iscsit_conn_t *ict,
399 login_event_ctx_t *ctx)
400{
401 idm_pdu_t *pdu = ctx->le_pdu; /* Only valid for some events */
402

--- 4 unchanged lines hidden (view full) ---

407 (void *)ict,
408 iscsit_ile_name[ctx->le_ctx_event], ctx->le_ctx_event);
409
410 /* State independent actions */
411 switch (ctx->le_ctx_event) {
412 case ILE_LOGIN_RCV:
413 /* Perform basic sanity checks on the header */
414 if (login_sm_req_pdu_check(ict, pdu) != IDM_STATUS_SUCCESS) {
385}
386
387static void
388login_sm_event_dispatch(iscsit_conn_login_t *lsm, iscsit_conn_t *ict,
389 login_event_ctx_t *ctx)
390{
391 idm_pdu_t *pdu = ctx->le_pdu; /* Only valid for some events */
392

--- 4 unchanged lines hidden (view full) ---

397 (void *)ict,
398 iscsit_ile_name[ctx->le_ctx_event], ctx->le_ctx_event);
399
400 /* State independent actions */
401 switch (ctx->le_ctx_event) {
402 case ILE_LOGIN_RCV:
403 /* Perform basic sanity checks on the header */
404 if (login_sm_req_pdu_check(ict, pdu) != IDM_STATUS_SUCCESS) {
405 idm_pdu_t *rpdu;
406
415 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
416 ISCSI_LOGIN_STATUS_INVALID_REQUEST);
417 /*
418 * If we haven't processed any PDU's yet then use
419 * this one as a template for the response
420 */
421 if (ict->ict_login_sm.icl_login_resp_tmpl->opcode == 0)
422 login_sm_handle_initial_login(ict, pdu);
407 SET_LOGIN_ERROR(ict, ISCSI_STATUS_CLASS_INITIATOR_ERR,
408 ISCSI_LOGIN_STATUS_INVALID_REQUEST);
409 /*
410 * If we haven't processed any PDU's yet then use
411 * this one as a template for the response
412 */
413 if (ict->ict_login_sm.icl_login_resp_tmpl->opcode == 0)
414 login_sm_handle_initial_login(ict, pdu);
423 login_sm_build_login_response(ict);
424 login_sm_send_next_response(ict);
415 rpdu = login_sm_build_login_response(ict);
416 login_sm_send_next_response(ict, rpdu);
425 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
426 kmem_free(ctx, sizeof (*ctx));
427 return;
428 }
429 break;
430 default:
431 break;
432 }

--- 112 unchanged lines hidden (view full) ---

545 default:
546 ASSERT(0);
547 }
548}
549
550static void
551login_sm_responding(iscsit_conn_t *ict, login_event_ctx_t *ctx)
552{
417 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
418 kmem_free(ctx, sizeof (*ctx));
419 return;
420 }
421 break;
422 default:
423 break;
424 }

--- 112 unchanged lines hidden (view full) ---

537 default:
538 ASSERT(0);
539 }
540}
541
542static void
543login_sm_responding(iscsit_conn_t *ict, login_event_ctx_t *ctx)
544{
553 idm_pdu_t *pdu;
545 idm_pdu_t *pdu, *rpdu;
554
555 switch (ctx->le_ctx_event) {
556 case ILE_LOGIN_RCV:
557 pdu = ctx->le_pdu;
558 /*
559 * We should only be in "responding" state if we have not
560 * sent the last PDU of a multi-PDU login response sequence.
561 * In that case we expect this received PDU to be an
562 * acknowledgement from the initiator (login PDU with C
563 * bit cleared and no data). If it's the acknowledgement
564 * we are expecting then we send the next PDU in the login
565 * response sequence. Otherwise it's a protocol error and
566 * the login fails.
567 */
568 if (login_sm_validate_ack(ict, pdu) == IDM_STATUS_SUCCESS) {
546
547 switch (ctx->le_ctx_event) {
548 case ILE_LOGIN_RCV:
549 pdu = ctx->le_pdu;
550 /*
551 * We should only be in "responding" state if we have not
552 * sent the last PDU of a multi-PDU login response sequence.
553 * In that case we expect this received PDU to be an
554 * acknowledgement from the initiator (login PDU with C
555 * bit cleared and no data). If it's the acknowledgement
556 * we are expecting then we send the next PDU in the login
557 * response sequence. Otherwise it's a protocol error and
558 * the login fails.
559 */
560 if (login_sm_validate_ack(ict, pdu) == IDM_STATUS_SUCCESS) {
569 login_sm_build_login_response(ict);
570 login_sm_send_next_response(ict);
561 rpdu = login_sm_build_login_response(ict);
562 login_sm_send_next_response(ict, rpdu);
571 } else {
572 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
573 }
574 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
575 break;
576 case ILE_LOGIN_FFP:
577 login_sm_new_state(ict, ctx, ILS_LOGIN_FFP);
578 break;

--- 111 unchanged lines hidden (view full) ---

690 }
691}
692
693static void
694login_sm_new_state(iscsit_conn_t *ict, login_event_ctx_t *ctx,
695 iscsit_login_state_t new_state)
696{
697 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
563 } else {
564 login_sm_new_state(ict, ctx, ILS_LOGIN_ERROR);
565 }
566 idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
567 break;
568 case ILE_LOGIN_FFP:
569 login_sm_new_state(ict, ctx, ILS_LOGIN_FFP);
570 break;

--- 111 unchanged lines hidden (view full) ---

682 }
683}
684
685static void
686login_sm_new_state(iscsit_conn_t *ict, login_event_ctx_t *ctx,
687 iscsit_login_state_t new_state)
688{
689 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
690 idm_pdu_t *rpdu;
698
699 /*
700 * Validate new state
701 */
702 ASSERT(new_state != ILS_UNDEFINED);
703 ASSERT3U(new_state, <, ILS_MAX_STATE);
704
705 new_state = (new_state < ILS_MAX_STATE) ?

--- 19 unchanged lines hidden (view full) ---

725 case ILS_LOGIN_WAITING:
726 /* Do nothing, waiting for more login PDU's */
727 break;
728 case ILS_LOGIN_PROCESSING:
729 /* All login PDU's received, process login request */
730 login_sm_process_request(ict);
731 break;
732 case ILS_LOGIN_RESPONDING:
691
692 /*
693 * Validate new state
694 */
695 ASSERT(new_state != ILS_UNDEFINED);
696 ASSERT3U(new_state, <, ILS_MAX_STATE);
697
698 new_state = (new_state < ILS_MAX_STATE) ?

--- 19 unchanged lines hidden (view full) ---

718 case ILS_LOGIN_WAITING:
719 /* Do nothing, waiting for more login PDU's */
720 break;
721 case ILS_LOGIN_PROCESSING:
722 /* All login PDU's received, process login request */
723 login_sm_process_request(ict);
724 break;
725 case ILS_LOGIN_RESPONDING:
733 login_sm_send_next_response(ict);
726 rpdu = login_sm_build_login_response(ict);
727 login_sm_send_next_response(ict, rpdu);
734 break;
735 case ILS_LOGIN_RESPONDED:
736 /* clean up the login response idm text buffer */
737 if (lsm->icl_login_resp_itb != NULL) {
738 idm_itextbuf_free(lsm->icl_login_resp_itb);
739 lsm->icl_login_resp_itb = NULL;
740 }
741 break;
742 case ILS_LOGIN_FFP:
743 login_sm_ffp_actions(ict);
744 break;
745 case ILS_LOGIN_DONE:
746 case ILS_LOGIN_ERROR:
728 break;
729 case ILS_LOGIN_RESPONDED:
730 /* clean up the login response idm text buffer */
731 if (lsm->icl_login_resp_itb != NULL) {
732 idm_itextbuf_free(lsm->icl_login_resp_itb);
733 lsm->icl_login_resp_itb = NULL;
734 }
735 break;
736 case ILS_LOGIN_FFP:
737 login_sm_ffp_actions(ict);
738 break;
739 case ILS_LOGIN_DONE:
740 case ILS_LOGIN_ERROR:
747 /* Free login SM resources */
741 /*
742 * Flag the terminal state for the dispatcher
743 */
748 lsm->icl_login_complete = B_TRUE;
749 break;
750 case ILS_LOGIN_INIT: /* Initial state, can't return */
751 default:
752 ASSERT(0);
753 /*NOTREACHED*/
754 }
755}
756
757/*ARGSUSED*/
758static void
759login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu)
760{
761 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
744 lsm->icl_login_complete = B_TRUE;
745 break;
746 case ILS_LOGIN_INIT: /* Initial state, can't return */
747 default:
748 ASSERT(0);
749 /*NOTREACHED*/
750 }
751}
752
753/*ARGSUSED*/
754static void
755login_sm_send_ack(iscsit_conn_t *ict, idm_pdu_t *pdu)
756{
757 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
758 idm_pdu_t *lack;
762
759
763 ASSERT((lsm->icl_login_resp->isp_flags & IDM_PDU_LOGIN_TX) != 0);
764 bcopy(lsm->icl_login_resp_tmpl,
765 lsm->icl_login_resp->isp_hdr, sizeof (iscsi_hdr_t));
766 idm_pdu_tx(lsm->icl_login_resp);
760 /*
761 * allocate the response pdu
762 */
763 lack = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0);
764 idm_pdu_init(lack, ict->ict_ic, ict, login_resp_complete_cb);
765 lack->isp_flags |= IDM_PDU_LOGIN_TX;
766
767 /*
768 * copy the response template into the response pdu
769 */
770 bcopy(lsm->icl_login_resp_tmpl, lack->isp_hdr, sizeof (iscsi_hdr_t));
771
772 iscsit_conn_hold(ict);
773 idm_pdu_tx(lack);
767}
768
769/*ARGSUSED*/
770static idm_status_t
771login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu)
772{
773 iscsi_hdr_t *ihp = pdu->isp_hdr;
774 if (ihp->flags & ISCSI_FLAG_TEXT_CONTINUE) {
775 return (IDM_STATUS_FAIL);
776 }
777 if (ntoh24(ihp->dlength) != 0) {
778 return (IDM_STATUS_FAIL);
779 }
780 return (IDM_STATUS_SUCCESS);
781}
782
783static boolean_t
774}
775
776/*ARGSUSED*/
777static idm_status_t
778login_sm_validate_ack(iscsit_conn_t *ict, idm_pdu_t *pdu)
779{
780 iscsi_hdr_t *ihp = pdu->isp_hdr;
781 if (ihp->flags & ISCSI_FLAG_TEXT_CONTINUE) {
782 return (IDM_STATUS_FAIL);
783 }
784 if (ntoh24(ihp->dlength) != 0) {
785 return (IDM_STATUS_FAIL);
786 }
787 return (IDM_STATUS_SUCCESS);
788}
789
790static boolean_t
784login_sm_is_last_response(iscsit_conn_t *ict)
791login_sm_is_last_response(idm_pdu_t *pdu)
785{
792{
786 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
787
793
788 if (lsm->icl_login_resp->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) {
794 if (pdu->isp_hdr->flags & ISCSI_FLAG_LOGIN_CONTINUE) {
789 return (B_FALSE);
790 }
791 return (B_TRUE);
792}
793
794
795static void
796login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu)

--- 64 unchanged lines hidden (view full) ---

861
862 /*
863 * StatSn, ExpCmdSn and MaxCmdSn will be set immediately before
864 * transmission
865 */
866}
867
868static void
795 return (B_FALSE);
796 }
797 return (B_TRUE);
798}
799
800
801static void
802login_sm_handle_initial_login(iscsit_conn_t *ict, idm_pdu_t *pdu)

--- 64 unchanged lines hidden (view full) ---

867
868 /*
869 * StatSn, ExpCmdSn and MaxCmdSn will be set immediately before
870 * transmission
871 */
872}
873
874static void
869login_sm_send_next_response(iscsit_conn_t *ict)
875login_sm_send_next_response(iscsit_conn_t *ict, idm_pdu_t *pdu)
870{
876{
871 idm_pdu_t *pdu = ict->ict_login_sm.icl_login_resp;
872 iscsi_login_rsp_hdr_t *lh_resp = (iscsi_login_rsp_hdr_t *)pdu->isp_hdr;
873
877 iscsi_login_rsp_hdr_t *lh_resp = (iscsi_login_rsp_hdr_t *)pdu->isp_hdr;
878
874 /* Tell the IDM layer this PDU is part of the login phase */
879 /* Make sure this PDU is part of the login phase */
875 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0);
876
877 /*
878 * Fill in header values
879 */
880 hton24(lh_resp->dlength, pdu->isp_datalen);
881
882 /*
883 * If this is going to be the last PDU of a login response
884 * that moves us to FFP then generate the ILE_LOGIN_FFP event.
885 */
886 if (lh_resp->status_class == ISCSI_STATUS_CLASS_SUCCESS) {
887 ASSERT(ict->ict_sess != NULL);
888
889 if ((lh_resp->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
890 (ISCSI_LOGIN_NEXT_STAGE(lh_resp->flags) ==
891 ISCSI_FULL_FEATURE_PHASE) &&
892 !(lh_resp->flags & ISCSI_FLAG_LOGIN_CONTINUE)) {
880 ASSERT((pdu->isp_flags & IDM_PDU_LOGIN_TX) != 0);
881
882 /*
883 * Fill in header values
884 */
885 hton24(lh_resp->dlength, pdu->isp_datalen);
886
887 /*
888 * If this is going to be the last PDU of a login response
889 * that moves us to FFP then generate the ILE_LOGIN_FFP event.
890 */
891 if (lh_resp->status_class == ISCSI_STATUS_CLASS_SUCCESS) {
892 ASSERT(ict->ict_sess != NULL);
893
894 if ((lh_resp->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
895 (ISCSI_LOGIN_NEXT_STAGE(lh_resp->flags) ==
896 ISCSI_FULL_FEATURE_PHASE) &&
897 !(lh_resp->flags & ISCSI_FLAG_LOGIN_CONTINUE)) {
893 iscsit_login_sm_event_locked(ict, ILE_LOGIN_FFP, NULL);
898 iscsit_login_sm_event(ict, ILE_LOGIN_FFP, NULL);
894 }
899 }
900 if (login_sm_is_last_response(pdu) == B_TRUE) {
901 /*
902 * The last of a potentially mult-PDU response finished.
903 */
904 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_COMPLETE,
905 NULL);
906 }
895
907
908 iscsit_conn_hold(ict);
896 iscsit_pdu_tx(pdu);
897 } else {
898 /*
899 * If status_class != ISCSI_STATUS_CLASS_SUCCESS then
900 * StatSN is not valid and we can call idm_pdu_tx instead
901 * of iscsit_pdu_tx. This is very good thing since in
902 * some cases of login failure we may not have a session.
903 * Since iscsit_calc_rspsn grabs the session mutex while
904 * it is retrieving values for expcmdsn and maxcmdsn this
905 * would cause a panic.
906 *
907 * Since we still want a value for expcmdsn, fill in an
908 * appropriate value based on the login request before
909 * sending the response. Cmdsn/expcmdsn do not advance during
910 * login phase.
911 */
912 lh_resp->expcmdsn = htonl(ict->ict_login_sm.icl_cmdsn);
913 lh_resp->maxcmdsn = htonl(ict->ict_login_sm.icl_cmdsn + 1);
914
909 iscsit_pdu_tx(pdu);
910 } else {
911 /*
912 * If status_class != ISCSI_STATUS_CLASS_SUCCESS then
913 * StatSN is not valid and we can call idm_pdu_tx instead
914 * of iscsit_pdu_tx. This is very good thing since in
915 * some cases of login failure we may not have a session.
916 * Since iscsit_calc_rspsn grabs the session mutex while
917 * it is retrieving values for expcmdsn and maxcmdsn this
918 * would cause a panic.
919 *
920 * Since we still want a value for expcmdsn, fill in an
921 * appropriate value based on the login request before
922 * sending the response. Cmdsn/expcmdsn do not advance during
923 * login phase.
924 */
925 lh_resp->expcmdsn = htonl(ict->ict_login_sm.icl_cmdsn);
926 lh_resp->maxcmdsn = htonl(ict->ict_login_sm.icl_cmdsn + 1);
927
915 idm_pdu_tx(ict->ict_login_sm.icl_login_resp);
928 iscsit_conn_hold(ict);
929 idm_pdu_tx(pdu);
916 }
917
918}
919
920static void
921login_sm_process_request(iscsit_conn_t *ict)
922{
923 iscsit_conn_login_t *lsm = &ict->ict_login_sm;

--- 70 unchanged lines hidden (view full) ---

994 if (login_sm_process_nvlist(ict) != IDM_STATUS_SUCCESS) {
995 goto request_fail;
996 }
997
998 if (login_sm_check_security(ict) != IDM_STATUS_SUCCESS) {
999 goto request_fail;
1000 }
1001
930 }
931
932}
933
934static void
935login_sm_process_request(iscsit_conn_t *ict)
936{
937 iscsit_conn_login_t *lsm = &ict->ict_login_sm;

--- 70 unchanged lines hidden (view full) ---

1008 if (login_sm_process_nvlist(ict) != IDM_STATUS_SUCCESS) {
1009 goto request_fail;
1010 }
1011
1012 if (login_sm_check_security(ict) != IDM_STATUS_SUCCESS) {
1013 goto request_fail;
1014 }
1015
1002request_fail:
1003 login_sm_build_login_response(ict);
1016 /* clean up request_nvlist */
1017 if (lsm->icl_request_nvlist != NULL) {
1018 nvlist_free(lsm->icl_request_nvlist);
1019 lsm->icl_request_nvlist = NULL;
1020 }
1021
1022 /* convert any responses to textbuf form */
1023 ASSERT(lsm->icl_login_resp_itb == NULL);
1024 if (lsm->icl_response_nvlist) {
1025 lsm->icl_login_resp_itb = idm_nvlist_to_itextbuf(
1026 lsm->icl_response_nvlist);
1027 if (lsm->icl_login_resp_itb == NULL) {
1028 /* Still need to send the resp so continue */
1029 SET_LOGIN_ERROR(ict,
1030 ISCSI_STATUS_CLASS_TARGET_ERR,
1031 ISCSI_LOGIN_STATUS_NO_RESOURCES);
1032 }
1033 /* clean up response_nvlist */
1034 nvlist_free(lsm->icl_response_nvlist);
1035 lsm->icl_response_nvlist = NULL;
1036 }
1037
1038 /* tell the state machine to send the textbuf */
1004 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_READY, NULL);
1039 iscsit_login_sm_event(ict, ILE_LOGIN_RESP_READY, NULL);
1040 return;
1005
1041
1042request_fail:
1043
1006 /* clean up request_nvlist and response_nvlist */
1007 if (lsm->icl_request_nvlist != NULL) {
1008 nvlist_free(lsm->icl_request_nvlist);
1009 lsm->icl_request_nvlist = NULL;
1010 }
1011 if (lsm->icl_response_nvlist != NULL) {
1012 nvlist_free(lsm->icl_response_nvlist);
1013 lsm->icl_response_nvlist = NULL;

--- 888 unchanged lines hidden (view full) ---

1902 /* supply login class/detail for login errors */
1903 SET_LOGIN_ERROR(ict, error_class, error_detail);
1904 idm_status = IDM_STATUS_FAIL;
1905 }
1906
1907 return (idm_status);
1908}
1909
1044 /* clean up request_nvlist and response_nvlist */
1045 if (lsm->icl_request_nvlist != NULL) {
1046 nvlist_free(lsm->icl_request_nvlist);
1047 lsm->icl_request_nvlist = NULL;
1048 }
1049 if (lsm->icl_response_nvlist != NULL) {
1050 nvlist_free(lsm->icl_response_nvlist);
1051 lsm->icl_response_nvlist = NULL;

--- 888 unchanged lines hidden (view full) ---

1940 /* supply login class/detail for login errors */
1941 SET_LOGIN_ERROR(ict, error_class, error_detail);
1942 idm_status = IDM_STATUS_FAIL;
1943 }
1944
1945 return (idm_status);
1946}
1947
1910static void
1948static idm_pdu_t *
1911login_sm_build_login_response(iscsit_conn_t *ict)
1912{
1913 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1914 iscsi_login_rsp_hdr_t *lh;
1915 int transit, text_transit = 1;
1949login_sm_build_login_response(iscsit_conn_t *ict)
1950{
1951 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
1952 iscsi_login_rsp_hdr_t *lh;
1953 int transit, text_transit = 1;
1954 idm_pdu_t *login_resp;
1916
1917 /*
1955
1956 /*
1918 * 1. Convert response nvlist to an idm text buffer that holds
1919 * response key-value pairs.
1920 * 2. Build a PDU to transmit the first login response PDU
1921 * 3. If there is more data, wait for an ack then goto step 2.
1957 * Create a response PDU and fill it with as much of
1958 * the response text that will fit.
1922 */
1959 */
1923 ASSERT(lsm->icl_login_resp != NULL);
1924
1960
1925 if (lsm->icl_response_nvlist) {
1926 if (lsm->icl_login_resp_itb == NULL) {
1927 /* initialze the idm text buf to send pdus */
1928 lsm->icl_login_resp_itb = idm_nvlist_to_itextbuf(
1929 lsm->icl_response_nvlist);
1930 if (lsm->icl_login_resp_itb == NULL) {
1931 SET_LOGIN_ERROR(ict,
1932 ISCSI_STATUS_CLASS_TARGET_ERR,
1933 ISCSI_LOGIN_STATUS_NO_RESOURCES);
1934 /* Still need to send the resp so continue */
1935 } else {
1936 lsm->icl_login_resp_buf =
1937 idm_pdu_init_text_data(lsm->icl_login_resp,
1938 lsm->icl_login_resp_itb,
1939 ISCSI_DEFAULT_MAX_RECV_SEG_LEN,
1940 lsm->icl_login_resp_buf, &text_transit);
1941 }
1942 } else {
1943 lsm->icl_login_resp_buf = idm_pdu_init_text_data(
1944 lsm->icl_login_resp, lsm->icl_login_resp_itb,
1945 ISCSI_DEFAULT_MAX_RECV_SEG_LEN,
1946 lsm->icl_login_resp_buf, &text_transit);
1961 if (lsm->icl_login_resp_itb) {
1962 /* allocate a pdu with space for text */
1963 login_resp = idm_pdu_alloc(sizeof (iscsi_hdr_t),
1964 ISCSI_DEFAULT_MAX_RECV_SEG_LEN);
1965 /* copy a chunk of text into the pdu */
1966 lsm->icl_login_resp_buf = idm_pdu_init_text_data(
1967 login_resp, lsm->icl_login_resp_itb,
1968 ISCSI_DEFAULT_MAX_RECV_SEG_LEN,
1969 lsm->icl_login_resp_buf, &text_transit);
1970 if (text_transit) {
1971 /* text buf has been consumed */
1972 idm_itextbuf_free(lsm->icl_login_resp_itb);
1973 lsm->icl_login_resp_itb = NULL;
1974 lsm->icl_login_resp_buf = NULL;
1947 }
1948 } else {
1975 }
1976 } else {
1949 lsm->icl_login_resp->isp_data = NULL;
1950 lsm->icl_login_resp->isp_datalen = 0;
1977 /* allocate a pdu for just a header */
1978 login_resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), 0);
1951 }
1979 }
1980 /* finish initializing the pdu */
1981 idm_pdu_init(login_resp,
1982 ict->ict_ic, ict, login_resp_complete_cb);
1983 login_resp->isp_flags |= IDM_PDU_LOGIN_TX;
1952
1953 /*
1954 * Use the BHS header values from the response template
1955 */
1956 bcopy(lsm->icl_login_resp_tmpl,
1984
1985 /*
1986 * Use the BHS header values from the response template
1987 */
1988 bcopy(lsm->icl_login_resp_tmpl,
1957 lsm->icl_login_resp->isp_hdr, sizeof (iscsi_login_rsp_hdr_t));
1989 login_resp->isp_hdr, sizeof (iscsi_login_rsp_hdr_t));
1958
1990
1959 lh = (iscsi_login_rsp_hdr_t *)lsm->icl_login_resp->isp_hdr;
1991 lh = (iscsi_login_rsp_hdr_t *)login_resp->isp_hdr;
1960
1961 /* Set error class/detail */
1962 lh->status_class = lsm->icl_login_resp_err_class;
1963 lh->status_detail = lsm->icl_login_resp_err_detail;
1964 /* Set CSG, NSG and Transit */
1965 lh->flags = 0;
1966 lh->flags |= lsm->icl_login_csg << 2;
1967

--- 17 unchanged lines hidden (view full) ---

1985 }
1986
1987 /* If we are transitioning to FFP then set TSIH */
1988 if (transit && (lh->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
1989 lsm->icl_login_csg == ISCSI_FULL_FEATURE_PHASE) {
1990 lh->tsid = htons(ict->ict_sess->ist_tsih);
1991 }
1992 } else {
1992
1993 /* Set error class/detail */
1994 lh->status_class = lsm->icl_login_resp_err_class;
1995 lh->status_detail = lsm->icl_login_resp_err_detail;
1996 /* Set CSG, NSG and Transit */
1997 lh->flags = 0;
1998 lh->flags |= lsm->icl_login_csg << 2;
1999

--- 17 unchanged lines hidden (view full) ---

2017 }
2018
2019 /* If we are transitioning to FFP then set TSIH */
2020 if (transit && (lh->flags & ISCSI_FLAG_LOGIN_TRANSIT) &&
2021 lsm->icl_login_csg == ISCSI_FULL_FEATURE_PHASE) {
2022 lh->tsid = htons(ict->ict_sess->ist_tsih);
2023 }
2024 } else {
1993 lsm->icl_login_resp->isp_data = 0;
1994 lsm->icl_login_resp->isp_datalen = 0;
2025 login_resp->isp_data = 0;
2026 login_resp->isp_datalen = 0;
1995 }
2027 }
2028 return (login_resp);
1996}
1997
1998static kv_status_t
1999iscsit_handle_key(iscsit_conn_t *ict, nvpair_t *nvp, char *nvp_name)
2000{
2001 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2002 kv_status_t kvrc;
2003 const idm_kv_xlate_t *ikvx;

--- 537 unchanged lines hidden ---
2029}
2030
2031static kv_status_t
2032iscsit_handle_key(iscsit_conn_t *ict, nvpair_t *nvp, char *nvp_name)
2033{
2034 iscsit_conn_login_t *lsm = &ict->ict_login_sm;
2035 kv_status_t kvrc;
2036 const idm_kv_xlate_t *ikvx;

--- 537 unchanged lines hidden ---