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