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