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