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