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