1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * XXX TODO
27  * #includes cribbed from stmf.c -- undoubtedly only a small subset of these
28  * are actually needed.
29  */
30 #include <sys/conf.h>
31 #include <sys/file.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/scsi/scsi.h>
35 #include <sys/scsi/generic/persist.h>
36 #include <sys/byteorder.h>
37 #include <sys/nvpair.h>
38 #include <sys/door.h>
39 
40 #include <sys/stmf.h>
41 #include <sys/lpif.h>
42 #include <sys/stmf_ioctl.h>
43 #include <sys/portif.h>
44 #include <sys/pppt_ic_if.h>
45 
46 #include "pppt.h"
47 
48 /*
49  * Macros
50  */
51 
52 /* Free a struct if it was allocated */
53 #define	FREE_IF_ALLOC(m)					\
54 	do {							\
55 		if ((m)) kmem_free((m), sizeof (*(m)));		\
56 		_NOTE(CONSTCOND)				\
57 	} while (0)
58 
59 /*
60  * Macros to simplify the addition of struct fields to an nvlist.
61  * The name of the fields in the nvlist is the same as the name
62  * of the struct field.
63  *
64  * These macros require an int rc and a "done:" return retval label;
65  * they assume that the nvlist is named "nvl".
66  */
67 #define	NVLIST_ADD_FIELD(type, structure, field)			\
68 	do {								\
69 		rc = nvlist_add_##type(nvl, #field, structure->field);  \
70 		if (rc) goto done;					\
71 		_NOTE(CONSTCOND)					\
72 	} while (0)
73 
74 /* use this macro when the array is defined as part of the struct */
75 #define	NVLIST_ADD_ARRAY(type, structure, field)			\
76 	do {								\
77 		rc = nvlist_add_##type##_array(nvl, #field,		\
78 		    structure->field, sizeof (structure->field));	\
79 		if (rc) goto done;					\
80 		_NOTE(CONSTCOND)					\
81 	} while (0)
82 
83 /*
84  * use this macro when the array field is a ptr or you need to explictly
85  * call out the size.
86  */
87 #define	NVLIST_ADD_ARRAY_LEN(type, structure, field, len)		\
88 	do {								\
89 		rc = nvlist_add_##type##_array(nvl, #field,		\
90 		    structure->field, len);				\
91 		if (rc) goto done;					\
92 		_NOTE(CONSTCOND)					\
93 	} while (0)
94 
95 #define	NVLIST_ADD_DEVID(structure, field)				\
96 	do {								\
97 		rc = stmf_ic_scsi_devid_desc_marshal(nvl, #field,	\
98 		    structure->field);					\
99 		if (rc) goto done;					\
100 		_NOTE(CONSTCOND)					\
101 	} while (0)
102 
103 #define	NVLIST_ADD_RPORT(structure, field)				\
104 	do {								\
105 		rc = stmf_ic_remote_port_marshal(nvl, #field,		\
106 		    structure->field);					\
107 		if (rc) goto done;					\
108 		_NOTE(CONSTCOND)					\
109 	} while (0)
110 
111 #define	NVLIST_ADD_FIELD_UINT8(structure, field)			\
112 	NVLIST_ADD_FIELD(structure, field, uint8)
113 
114 /*
115  * Macros to simplify the extraction of struct fields from an nvlist.
116  * The name of the fields in the nvlist is the same as the name
117  * of the struct field.
118  *
119  * Requires an int rc and a "done:" return retval label.
120  * Assumes that the nvlist is named "nvl".
121  *
122  * Sample usage: NVLIST_LOOKUP_FIELD(uint8, structname, fieldname);
123  */
124 #define	NVLIST_LOOKUP_FIELD(type, structure, field)			\
125 	do {								\
126 		rc = nvlist_lookup_##type(nvl, #field,			\
127 		    &(structure->field));				\
128 		if (rc) { 						\
129 			stmf_ic_nvlookup_warn(__func__, #field);	\
130 			goto done;					\
131 		}							\
132 		_NOTE(CONSTCOND)					\
133 	} while (0)
134 
135 /*
136  * Look up a field which gets stored into a structure bit field.
137  * The type passed is a uint type which can hold the largest value
138  * in the bit field.
139  *
140  * Requires an int rc and a "done:" return retval label.
141  * Assumes that the nvlist is named "nvl".
142  *
143  * Sample usage: NVLIST_LOOKUP_BIT_FIELD(uint8, structname, fieldname);
144  */
145 #define	NVLIST_LOOKUP_BIT_FIELD(type, structure, field)			\
146 	do {								\
147 		type##_t tmp;						\
148 		rc = nvlist_lookup_##type(nvl, #field, &tmp);		\
149 		if (rc) { 						\
150 			stmf_ic_nvlookup_warn(__func__, #field);	\
151 			goto done;					\
152 		}							\
153 		structure->field = tmp;					\
154 		_NOTE(CONSTCOND)					\
155 	} while (0)
156 
157 /*
158  * Look up a boolean field which gets stored into a structure bit field.
159  *
160  * Requires an int rc and a "done:" return retval label.
161  * Assumes that the nvlist is named "nvl".
162  */
163 #define	NVLIST_LOOKUP_BIT_FIELD_BOOLEAN(structure, field)		\
164 	do {								\
165 		boolean_t tmp;						\
166 		rc = nvlist_lookup_boolean_value(nvl, #field, &tmp);	\
167 		if (rc) { 						\
168 			stmf_ic_nvlookup_warn(__func__, #field);	\
169 			goto done;					\
170 		}							\
171 		structure->field = (tmp ?  1 : 0);			\
172 		_NOTE(CONSTCOND)					\
173 	} while (0)
174 
175 /* shorthand  for nvlist_lookup_pairs() args */
176 #define	NV_PAIR(type, strct, field) #field, DATA_TYPE_##type, &(strct->field)
177 
178 /* number of times to retry the upcall to transmit */
179 #define	STMF_MSG_TRANSMIT_RETRY	    3
180 
181 /*
182  * How was the message constructed?
183  *
184  * We need to know this when we free the message in order to
185  * determine what to do with pointers in the message:
186  *
187  * - messages which were unmarshaled from an nvlist may point to
188  *   memory within that nvlist; this memory should not be freed since
189  *   it will be deallocated when we free the nvlist.
190  *
191  * - messages which built using a constructor (alloc) function may
192  *   point to memory which was explicitly allocated by the constructor;
193  *   it should be freed when the message is freed.
194  *
195  */
196 typedef enum {
197 	STMF_CONSTRUCTOR = 0,
198 	STMF_UNMARSHAL
199 } stmf_ic_msg_construction_method_t;
200 
201 
202 /*
203  * Function prototypes.
204  */
205 
206 /*
207  * Helpers for msg_alloc routines, used when the msg payload is
208  * the same for multiple types of messages.
209  */
210 static stmf_ic_msg_t *stmf_ic_reg_dereg_lun_msg_alloc(
211     stmf_ic_msg_type_t msg_type, uint8_t *lun_id,
212     char *lu_provider_name, uint16_t cb_arg_len,
213     uint8_t *cb_arg, stmf_ic_msgid_t msgid);
214 
215 static stmf_ic_msg_t *stmf_ic_session_create_destroy_msg_alloc(
216     stmf_ic_msg_type_t msg_type,
217     stmf_scsi_session_t *session,
218     stmf_ic_msgid_t msgid);
219 
220 static stmf_ic_msg_t *stmf_ic_echo_request_reply_msg_alloc(
221     stmf_ic_msg_type_t msg_type,
222     uint32_t data_len,
223     uint8_t *data,
224     stmf_ic_msgid_t msgid);
225 
226 /*
227  * Msg free routines.
228  */
229 static void stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m,
230     stmf_ic_msg_construction_method_t cmethod);
231 static void stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m,
232     stmf_ic_msg_construction_method_t cmethod);
233 static void stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m,
234     stmf_ic_msg_construction_method_t cmethod);
235 static void stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m,
236     stmf_ic_msg_construction_method_t cmethod);
237 static void stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m,
238     stmf_ic_msg_construction_method_t cmethod);
239 static void stmf_ic_scsi_data_xfer_done_msg_free(
240     stmf_ic_scsi_data_xfer_done_msg_t *m,
241     stmf_ic_msg_construction_method_t cmethod);
242 static void stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m,
243     stmf_ic_msg_construction_method_t cmethod);
244 static void stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m,
245     stmf_ic_msg_construction_method_t cmethod);
246 static void stmf_ic_status_msg_free(stmf_ic_status_msg_t *m,
247     stmf_ic_msg_construction_method_t cmethod);
248 static void stmf_ic_session_create_destroy_msg_free(
249     stmf_ic_session_create_destroy_msg_t *m,
250     stmf_ic_msg_construction_method_t cmethod);
251 static void stmf_ic_echo_request_reply_msg_free(
252     stmf_ic_echo_request_reply_msg_t *m,
253     stmf_ic_msg_construction_method_t cmethod);
254 
255 /*
256  * Marshaling routines.
257  */
258 static nvlist_t *stmf_ic_msg_marshal(stmf_ic_msg_t *msg);
259 static int stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg);
260 static int stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg);
261 static int stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg);
262 static int stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg);
263 static int stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg);
264 static int stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg);
265 static int stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg);
266 static int stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg);
267 static int stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg);
268 static int stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg);
269 static int stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg);
270 static int stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl,
271 	char *sdid_name, scsi_devid_desc_t *sdid);
272 static int stmf_ic_remote_port_marshal(nvlist_t *parent_nvl,
273 	char *rport_name, stmf_remote_port_t *rport);
274 
275 /*
276  * Unmarshaling routines.
277  */
278 static stmf_ic_msg_t *stmf_ic_msg_unmarshal(nvlist_t *nvl);
279 static void *stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl);
280 static void *stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl);
281 static void *stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl);
282 static void *stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl);
283 static void *stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl);
284 static void *stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl);
285 static void *stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl);
286 static void *stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl);
287 static void *stmf_ic_status_msg_unmarshal(nvlist_t *nvl);
288 static void *stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl);
289 static void *stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl);
290 static scsi_devid_desc_t *stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
291     nvlist_t *nvl, char *field_name);
292 static scsi_devid_desc_t *stmf_ic_scsi_devid_desc_unmarshal(
293     nvlist_t *nvl_devid);
294 static uint8_t *stmf_ic_uint8_array_unmarshal(nvlist_t *nvl, char *field_name,
295 	uint64_t len, uint8_t *buf);
296 static char *stmf_ic_string_unmarshal(nvlist_t *nvl, char *field_name);
297 static stmf_remote_port_t *stmf_ic_lookup_remote_port_and_unmarshal(
298 	nvlist_t *nvl, char *field_name);
299 static stmf_remote_port_t *stmf_ic_remote_port_unmarshal(nvlist_t *nvl);
300 
301 /*
302  * Transmit and recieve routines.
303  */
304 stmf_ic_msg_status_t stmf_ic_transmit(char *buf, size_t size);
305 
306 /*
307  * Utilities.
308  */
309 static stmf_ic_msg_t *stmf_ic_alloc_msg_header(stmf_ic_msg_type_t msg_type,
310 	stmf_ic_msgid_t msgid);
311 static size_t sizeof_scsi_devid_desc(int ident_length);
312 static char *stmf_ic_strdup(char *str);
313 static scsi_devid_desc_t *scsi_devid_desc_dup(scsi_devid_desc_t *did);
314 static stmf_remote_port_t *remote_port_dup(stmf_remote_port_t *rport);
315 static void scsi_devid_desc_free(scsi_devid_desc_t *did);
316 static inline void stmf_ic_nvlookup_warn(const char *func, char *field);
317 
318 /*
319  * Send a message out over the interconnect, in the process marshalling
320  * the arguments.
321  *
322  * After being sent, the message is freed.
323  */
324 stmf_ic_msg_status_t
stmf_ic_tx_msg(stmf_ic_msg_t * msg)325 stmf_ic_tx_msg(stmf_ic_msg_t *msg)
326 {
327 	size_t size = 0;
328 	nvlist_t *nvl = NULL;
329 	char *buf = NULL;
330 	int err = 0;
331 	stmf_ic_msg_status_t status = STMF_IC_MSG_SUCCESS;
332 
333 	nvl = stmf_ic_msg_marshal(msg);
334 	if (!nvl) {
335 		cmn_err(CE_WARN, "stmf_ic_tx_msg: marshal failed");
336 		status = STMF_IC_MSG_INTERNAL_ERROR;
337 		goto done;
338 	}
339 
340 	err = nvlist_size(nvl, &size, NV_ENCODE_XDR);
341 	if (err) {
342 		status = STMF_IC_MSG_INTERNAL_ERROR;
343 		goto done;
344 	}
345 
346 	buf = kmem_alloc(size, KM_SLEEP);
347 	err = nvlist_pack(nvl, &buf, &size, NV_ENCODE_XDR, 0);
348 	if (err) {
349 		status = STMF_IC_MSG_INTERNAL_ERROR;
350 		goto done;
351 	}
352 
353 	/* push the bits out on the wire */
354 
355 	status = stmf_ic_transmit(buf, size);
356 
357 done:
358 	nvlist_free(nvl);
359 
360 	if (buf)
361 		kmem_free(buf, size);
362 
363 	stmf_ic_msg_free(msg);
364 
365 
366 	return (status);
367 }
368 
369 /*
370  * Pass the command to the daemon for transmission to the other node.
371  */
372 stmf_ic_msg_status_t
stmf_ic_transmit(char * buf,size_t size)373 stmf_ic_transmit(char *buf, size_t size)
374 {
375 	int i;
376 	int rc;
377 	door_arg_t arg;
378 	door_handle_t door;
379 	uint32_t result;
380 
381 	mutex_enter(&pppt_global.global_door_lock);
382 	if (pppt_global.global_door == NULL) {
383 		/* daemon not listening */
384 		mutex_exit(&pppt_global.global_door_lock);
385 		return (STMF_IC_MSG_INTERNAL_ERROR);
386 	}
387 	door = pppt_global.global_door;
388 	door_ki_hold(door);
389 	mutex_exit(&pppt_global.global_door_lock);
390 
391 	arg.data_ptr = buf;
392 	arg.data_size = size;
393 	arg.desc_ptr = NULL;
394 	arg.desc_num = 0;
395 	arg.rbuf = (char *)&result;
396 	arg.rsize = sizeof (result);
397 	/*
398 	 * Retry a few times if there is a shortage of threads to
399 	 * service the upcall. This shouldn't happen unless a large
400 	 * number of initiators issue commands at once.
401 	 */
402 	for (i = 0; i < STMF_MSG_TRANSMIT_RETRY; i++) {
403 		rc = door_ki_upcall(door, &arg);
404 		if (rc != EAGAIN)
405 			break;
406 		delay(hz);
407 	}
408 	door_ki_rele(door);
409 	if (rc != 0) {
410 		cmn_err(CE_WARN,
411 		    "stmf_ic_transmit door_ki_upcall failed %d", rc);
412 		return (STMF_IC_MSG_INTERNAL_ERROR);
413 	}
414 	if (result != 0) {
415 		/* XXX Just warn for now */
416 		cmn_err(CE_WARN,
417 		    "stmf_ic_transmit bad result from daemon %d", result);
418 	}
419 
420 	return (STMF_IC_MSG_SUCCESS);
421 }
422 
423 /*
424  * This is a low-level upcall which is called when a message has
425  * been received on the interconnect.
426  *
427  * The caller is responsible for freeing the buffer which is passed in.
428  */
429 /*ARGSUSED*/
430 void
stmf_ic_rx_msg(char * buf,size_t len)431 stmf_ic_rx_msg(char *buf, size_t len)
432 {
433 	nvlist_t *nvl = NULL;
434 	stmf_ic_msg_t *m = NULL;
435 	stmf_ic_echo_request_reply_msg_t *icerr;
436 	stmf_ic_msg_t *echo_msg;
437 	int rc = 0;
438 
439 	rc = nvlist_unpack(buf, len, &nvl, 0);
440 	if (rc) {
441 		cmn_err(CE_WARN, "stmf_ic_rx_msg: unpack failed");
442 		return;
443 	}
444 
445 	m = stmf_ic_msg_unmarshal(nvl);
446 	if (m == NULL) {
447 		cmn_err(CE_WARN, "stmf_ic_rx_msg: unmarshal failed");
448 		nvlist_free(nvl);
449 		return;
450 	}
451 
452 	switch (m->icm_msg_type) {
453 
454 	case STMF_ICM_REGISTER_PROXY_PORT:
455 	case STMF_ICM_DEREGISTER_PROXY_PORT:
456 	case STMF_ICM_SCSI_CMD:
457 	case STMF_ICM_SCSI_DATA_XFER_DONE:
458 	case STMF_ICM_SESSION_CREATE:
459 	case STMF_ICM_SESSION_DESTROY:
460 		/*
461 		 * These messages are all received by pppt.
462 		 * Currently, pppt will parse the message for type
463 		 */
464 		(void) pppt_msg_rx(m);
465 		break;
466 
467 	case STMF_ICM_LUN_ACTIVE:
468 	case STMF_ICM_REGISTER_LUN:
469 	case STMF_ICM_DEREGISTER_LUN:
470 	case STMF_ICM_SCSI_DATA:
471 	case STMF_ICM_SCSI_STATUS:
472 		/*
473 		 * These messages are all received by stmf.
474 		 * Currently, stmf will parse the message for type
475 		 */
476 		(void) stmf_msg_rx(m);
477 		break;
478 
479 	case STMF_ICM_ECHO_REQUEST:
480 		icerr = m->icm_msg;
481 		echo_msg = stmf_ic_echo_reply_msg_alloc(icerr->icerr_datalen,
482 		    icerr->icerr_data, 0);
483 		if (echo_msg != NULL) {
484 			(void) stmf_ic_tx_msg(echo_msg);
485 		}
486 		stmf_ic_msg_free(m);
487 		break;
488 
489 	case STMF_ICM_ECHO_REPLY:
490 		stmf_ic_msg_free(m);
491 		break;
492 
493 	case STMF_ICM_R2T:
494 		/*
495 		 * XXX currently not supported
496 		 */
497 		stmf_ic_msg_free(m);
498 		break;
499 
500 	case STMF_ICM_STATUS:
501 		(void) stmf_msg_rx(m);
502 		break;
503 
504 	default:
505 		ASSERT(0);
506 	}
507 }
508 
509 /*
510  * IC message allocation routines.
511  */
512 
513 stmf_ic_msg_t *
stmf_ic_reg_port_msg_alloc(scsi_devid_desc_t * port_id,uint16_t relative_port_id,uint16_t cb_arg_len,uint8_t * cb_arg,stmf_ic_msgid_t msgid)514 stmf_ic_reg_port_msg_alloc(
515     scsi_devid_desc_t *port_id,
516     uint16_t relative_port_id,
517     uint16_t cb_arg_len,
518     uint8_t *cb_arg,
519     stmf_ic_msgid_t msgid)
520 {
521 	stmf_ic_msg_t *icm = NULL;
522 	stmf_ic_reg_port_msg_t *icrp = NULL;
523 
524 	icm = stmf_ic_alloc_msg_header(STMF_ICM_REGISTER_PROXY_PORT, msgid);
525 	icrp = (stmf_ic_reg_port_msg_t *)kmem_zalloc(sizeof (*icrp), KM_SLEEP);
526 	icm->icm_msg = (void *)icrp;
527 
528 	icrp->icrp_port_id = scsi_devid_desc_dup(port_id);
529 	icrp->icrp_relative_port_id = relative_port_id;
530 
531 	if (cb_arg_len) {
532 		icrp->icrp_cb_arg_len = cb_arg_len;
533 		icrp->icrp_cb_arg = cb_arg;
534 	}
535 
536 	return (icm);
537 }
538 
539 stmf_ic_msg_t *
stmf_ic_dereg_port_msg_alloc(scsi_devid_desc_t * port_id,uint16_t cb_arg_len,uint8_t * cb_arg,stmf_ic_msgid_t msgid)540 stmf_ic_dereg_port_msg_alloc(
541     scsi_devid_desc_t *port_id,
542     uint16_t cb_arg_len,
543     uint8_t *cb_arg,
544     stmf_ic_msgid_t msgid)
545 {
546 	stmf_ic_msg_t *icm = NULL;
547 	stmf_ic_dereg_port_msg_t *icdp = NULL;
548 
549 	icm = stmf_ic_alloc_msg_header(STMF_ICM_DEREGISTER_PROXY_PORT, msgid);
550 	icdp = (stmf_ic_dereg_port_msg_t *)kmem_zalloc(sizeof (*icdp),
551 	    KM_SLEEP);
552 	icm->icm_msg = (void *)icdp;
553 
554 	icdp->icdp_port_id = scsi_devid_desc_dup(port_id);
555 
556 	if (cb_arg_len) {
557 		icdp->icdp_cb_arg_len = cb_arg_len;
558 		icdp->icdp_cb_arg = cb_arg;
559 	}
560 
561 	return (icm);
562 }
563 
564 
565 stmf_ic_msg_t *
stmf_ic_reg_lun_msg_alloc(uint8_t * lun_id,char * lu_provider_name,uint16_t cb_arg_len,uint8_t * cb_arg,stmf_ic_msgid_t msgid)566 stmf_ic_reg_lun_msg_alloc(
567     uint8_t *lun_id,
568     char *lu_provider_name,
569     uint16_t cb_arg_len,
570     uint8_t *cb_arg,
571     stmf_ic_msgid_t msgid)
572 {
573 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_REGISTER_LUN, lun_id,
574 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
575 }
576 
577 stmf_ic_msg_t *
stmf_ic_lun_active_msg_alloc(uint8_t * lun_id,char * lu_provider_name,uint16_t cb_arg_len,uint8_t * cb_arg,stmf_ic_msgid_t msgid)578 stmf_ic_lun_active_msg_alloc(
579     uint8_t *lun_id,
580     char *lu_provider_name,
581     uint16_t cb_arg_len,
582     uint8_t *cb_arg,
583     stmf_ic_msgid_t msgid)
584 {
585 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_LUN_ACTIVE, lun_id,
586 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
587 }
588 
589 stmf_ic_msg_t *
stmf_ic_dereg_lun_msg_alloc(uint8_t * lun_id,char * lu_provider_name,uint16_t cb_arg_len,uint8_t * cb_arg,stmf_ic_msgid_t msgid)590 stmf_ic_dereg_lun_msg_alloc(
591     uint8_t *lun_id,
592     char *lu_provider_name,
593     uint16_t cb_arg_len,
594     uint8_t *cb_arg,
595     stmf_ic_msgid_t msgid)
596 {
597 	return (stmf_ic_reg_dereg_lun_msg_alloc(STMF_ICM_DEREGISTER_LUN, lun_id,
598 	    lu_provider_name, cb_arg_len, cb_arg, msgid));
599 }
600 
601 /*
602  * Guts of lun register/deregister/active alloc routines.
603  */
604 static stmf_ic_msg_t *
stmf_ic_reg_dereg_lun_msg_alloc(stmf_ic_msg_type_t msg_type,uint8_t * lun_id,char * lu_provider_name,uint16_t cb_arg_len,uint8_t * cb_arg,stmf_ic_msgid_t msgid)605 stmf_ic_reg_dereg_lun_msg_alloc(
606     stmf_ic_msg_type_t msg_type,
607     uint8_t *lun_id,
608     char *lu_provider_name,
609     uint16_t cb_arg_len,
610     uint8_t *cb_arg,
611     stmf_ic_msgid_t msgid)
612 {
613 	stmf_ic_msg_t *icm = NULL;
614 	stmf_ic_reg_dereg_lun_msg_t *icrl = NULL;
615 
616 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
617 	icrl = (stmf_ic_reg_dereg_lun_msg_t *)
618 	    kmem_zalloc(sizeof (*icrl), KM_SLEEP);
619 	icm->icm_msg = (void *)icrl;
620 
621 	icrl->icrl_lu_provider_name = stmf_ic_strdup(lu_provider_name);
622 
623 	bcopy(lun_id, icrl->icrl_lun_id, sizeof (icrl->icrl_lun_id));
624 
625 	if (cb_arg_len) {
626 		icrl->icrl_cb_arg_len = cb_arg_len;
627 		icrl->icrl_cb_arg = cb_arg;
628 	}
629 
630 	return (icm);
631 }
632 
633 stmf_ic_msg_t *
stmf_ic_scsi_cmd_msg_alloc(stmf_ic_msgid_t task_msgid,scsi_task_t * task,uint32_t immed_data_len,uint8_t * immed_data,stmf_ic_msgid_t msgid)634 stmf_ic_scsi_cmd_msg_alloc(
635     stmf_ic_msgid_t task_msgid,
636     scsi_task_t *task,
637     uint32_t immed_data_len,
638     uint8_t *immed_data,
639     stmf_ic_msgid_t msgid)
640 {
641 	stmf_ic_msg_t *icm = NULL;
642 	stmf_ic_scsi_cmd_msg_t *icsc = NULL;
643 	scsi_devid_desc_t *ini_devid = task->task_session->ss_rport_id;
644 	scsi_devid_desc_t *tgt_devid = task->task_lport->lport_id;
645 	stmf_remote_port_t *rport = task->task_session->ss_rport;
646 
647 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_CMD, msgid);
648 	icsc = (stmf_ic_scsi_cmd_msg_t *)kmem_zalloc(sizeof (*icsc), KM_SLEEP);
649 	icm->icm_msg = (void *)icsc;
650 
651 	icsc->icsc_task_msgid = task_msgid;
652 	icsc->icsc_ini_devid = scsi_devid_desc_dup(ini_devid);
653 	icsc->icsc_tgt_devid = scsi_devid_desc_dup(tgt_devid);
654 	icsc->icsc_rport = remote_port_dup(rport);
655 	icsc->icsc_session_id = task->task_session->ss_session_id;
656 
657 	if (!task->task_mgmt_function && task->task_lu->lu_id) {
658 		bcopy(task->task_lu->lu_id->ident,
659 		    icsc->icsc_lun_id, sizeof (icsc->icsc_lun_id));
660 	}
661 
662 	bcopy(task->task_lun_no, icsc->icsc_task_lun_no,
663 	    sizeof (icsc->icsc_task_lun_no));
664 
665 	icsc->icsc_task_expected_xfer_length = task->task_expected_xfer_length;
666 	if (task->task_cdb_length) {
667 		ASSERT(task->task_mgmt_function == TM_NONE);
668 		icsc->icsc_task_cdb_length = task->task_cdb_length;
669 		icsc->icsc_task_cdb =
670 		    (uint8_t *)kmem_zalloc(task->task_cdb_length, KM_SLEEP);
671 		bcopy(task->task_cdb, icsc->icsc_task_cdb,
672 		    task->task_cdb_length);
673 	}
674 
675 	icsc->icsc_task_flags = task->task_flags;
676 	icsc->icsc_task_priority = task->task_priority;
677 	icsc->icsc_task_mgmt_function = task->task_mgmt_function;
678 
679 	icsc->icsc_immed_data_len = immed_data_len;
680 	icsc->icsc_immed_data = immed_data;
681 
682 	return (icm);
683 }
684 
685 stmf_ic_msg_t *
stmf_ic_scsi_data_msg_alloc(stmf_ic_msgid_t task_msgid,uint64_t session_id,uint8_t * lun_id,uint64_t data_len,uint8_t * data,stmf_ic_msgid_t msgid)686 stmf_ic_scsi_data_msg_alloc(
687     stmf_ic_msgid_t task_msgid,
688     uint64_t session_id,
689     uint8_t *lun_id,
690     uint64_t data_len,
691     uint8_t *data,
692     stmf_ic_msgid_t msgid)
693 {
694 	stmf_ic_msg_t *icm = NULL;
695 	stmf_ic_scsi_data_msg_t *icsd = NULL;
696 
697 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA, msgid);
698 	icsd = (stmf_ic_scsi_data_msg_t *)kmem_zalloc(sizeof (*icsd), KM_SLEEP);
699 	icm->icm_msg = (void *)icsd;
700 
701 	icsd->icsd_task_msgid = task_msgid;
702 	icsd->icsd_session_id = session_id;
703 	bcopy(lun_id, icsd->icsd_lun_id, sizeof (icsd->icsd_lun_id));
704 	icsd->icsd_data_len = data_len;
705 	icsd->icsd_data = data;
706 
707 	return (icm);
708 }
709 
710 stmf_ic_msg_t *
stmf_ic_scsi_data_xfer_done_msg_alloc(stmf_ic_msgid_t task_msgid,uint64_t session_id,stmf_status_t status,stmf_ic_msgid_t msgid)711 stmf_ic_scsi_data_xfer_done_msg_alloc(
712     stmf_ic_msgid_t task_msgid,
713     uint64_t session_id,
714     stmf_status_t status,
715     stmf_ic_msgid_t msgid)
716 {
717 	stmf_ic_msg_t *icm = NULL;
718 	stmf_ic_scsi_data_xfer_done_msg_t *icsx = NULL;
719 
720 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_DATA_XFER_DONE, msgid);
721 	icsx = (stmf_ic_scsi_data_xfer_done_msg_t *)kmem_zalloc(
722 	    sizeof (*icsx), KM_SLEEP);
723 	icm->icm_msg = (void *)icsx;
724 
725 	icsx->icsx_task_msgid = task_msgid;
726 	icsx->icsx_session_id = session_id;
727 	icsx->icsx_status = status;
728 
729 	return (icm);
730 }
731 
732 stmf_ic_msg_t *
stmf_ic_scsi_status_msg_alloc(stmf_ic_msgid_t task_msgid,uint64_t session_id,uint8_t * lun_id,uint8_t response,uint8_t status,uint8_t flags,uint32_t resid,uint8_t sense_len,uint8_t * sense,stmf_ic_msgid_t msgid)733 stmf_ic_scsi_status_msg_alloc(
734     stmf_ic_msgid_t task_msgid,
735     uint64_t session_id,
736     uint8_t *lun_id,
737     uint8_t response,
738     uint8_t status,
739     uint8_t flags,
740     uint32_t resid,
741     uint8_t sense_len,
742     uint8_t *sense,
743     stmf_ic_msgid_t msgid)
744 {
745 	stmf_ic_msg_t *icm = NULL;
746 	stmf_ic_scsi_status_msg_t *icss = NULL;
747 
748 	icm = stmf_ic_alloc_msg_header(STMF_ICM_SCSI_STATUS, msgid);
749 	icss = (stmf_ic_scsi_status_msg_t *)kmem_zalloc(sizeof (*icss),
750 	    KM_SLEEP);
751 	icm->icm_msg = (void *)icss;
752 
753 	icss->icss_task_msgid = task_msgid;
754 	icss->icss_session_id = session_id;
755 	bcopy(lun_id, icss->icss_lun_id, sizeof (icss->icss_lun_id));
756 	icss->icss_response = response;
757 	icss->icss_status = status;
758 	icss->icss_flags = flags;
759 	icss->icss_resid = resid;
760 	icss->icss_sense_len = sense_len;
761 	icss->icss_sense = sense;
762 
763 	return (icm);
764 }
765 
766 stmf_ic_msg_t *
stmf_ic_r2t_msg_alloc(stmf_ic_msgid_t task_msgid,uint64_t session_id,uint32_t offset,uint32_t length,stmf_ic_msgid_t msgid)767 stmf_ic_r2t_msg_alloc(
768     stmf_ic_msgid_t task_msgid,
769     uint64_t session_id,
770     uint32_t offset,
771     uint32_t length,
772     stmf_ic_msgid_t msgid)
773 {
774 	stmf_ic_msg_t *icm = NULL;
775 	stmf_ic_r2t_msg_t *icrt = NULL;
776 
777 	icm = stmf_ic_alloc_msg_header(STMF_ICM_R2T, msgid);
778 	icrt = (stmf_ic_r2t_msg_t *)kmem_zalloc(sizeof (*icrt), KM_SLEEP);
779 	icm->icm_msg = (void *)icrt;
780 
781 	icrt->icrt_task_msgid = task_msgid;
782 	icrt->icrt_session_id = session_id;
783 	icrt->icrt_offset = offset;
784 	icrt->icrt_length = length;
785 
786 	return (icm);
787 }
788 
789 stmf_ic_msg_t *
stmf_ic_status_msg_alloc(stmf_status_t status,stmf_ic_msg_type_t msg_type,stmf_ic_msgid_t msgid)790 stmf_ic_status_msg_alloc(
791     stmf_status_t status,
792     stmf_ic_msg_type_t msg_type,
793     stmf_ic_msgid_t msgid)
794 {
795 	stmf_ic_msg_t *icm = NULL;
796 	stmf_ic_status_msg_t *ics = NULL;
797 
798 	icm = stmf_ic_alloc_msg_header(STMF_ICM_STATUS, msgid);
799 	ics = (stmf_ic_status_msg_t *)kmem_zalloc(sizeof (*ics), KM_SLEEP);
800 	icm->icm_msg = (void *)ics;
801 
802 	ics->ics_status = status;
803 	ics->ics_msg_type = msg_type;
804 	ics->ics_msgid = msgid;		/* XXX same as msgid in header */
805 
806 	return (icm);
807 }
808 
809 stmf_ic_msg_t *
stmf_ic_session_create_msg_alloc(stmf_scsi_session_t * session,stmf_ic_msgid_t msgid)810 stmf_ic_session_create_msg_alloc(
811     stmf_scsi_session_t *session,
812     stmf_ic_msgid_t msgid)
813 {
814 	return (stmf_ic_session_create_destroy_msg_alloc(
815 	    STMF_ICM_SESSION_CREATE, session, msgid));
816 }
817 
818 stmf_ic_msg_t *
stmf_ic_session_destroy_msg_alloc(stmf_scsi_session_t * session,stmf_ic_msgid_t msgid)819 stmf_ic_session_destroy_msg_alloc(
820     stmf_scsi_session_t *session,
821     stmf_ic_msgid_t msgid)
822 {
823 	return (stmf_ic_session_create_destroy_msg_alloc(
824 	    STMF_ICM_SESSION_DESTROY, session, msgid));
825 }
826 
827 /*
828  * Guts of session create/destroy routines.
829  */
830 static stmf_ic_msg_t *
stmf_ic_session_create_destroy_msg_alloc(stmf_ic_msg_type_t msg_type,stmf_scsi_session_t * session,stmf_ic_msgid_t msgid)831 stmf_ic_session_create_destroy_msg_alloc(
832     stmf_ic_msg_type_t msg_type,
833     stmf_scsi_session_t *session,
834     stmf_ic_msgid_t msgid)
835 {
836 	stmf_ic_msg_t *icm = NULL;
837 	stmf_ic_session_create_destroy_msg_t *icscd = NULL;
838 	scsi_devid_desc_t *ini_devid = session->ss_rport_id;
839 	scsi_devid_desc_t *tgt_devid = session->ss_lport->lport_id;
840 
841 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
842 	icscd = (stmf_ic_session_create_destroy_msg_t *)
843 	    kmem_zalloc(sizeof (*icscd), KM_SLEEP);
844 	icm->icm_msg = (void *)icscd;
845 
846 	icscd->icscd_session_id = session->ss_session_id;
847 	icscd->icscd_ini_devid = scsi_devid_desc_dup(ini_devid);
848 	icscd->icscd_tgt_devid = scsi_devid_desc_dup(tgt_devid);
849 	icscd->icscd_rport = remote_port_dup(session->ss_rport);
850 
851 	return (icm);
852 }
853 
854 stmf_ic_msg_t *
stmf_ic_echo_request_msg_alloc(uint32_t data_len,uint8_t * data,stmf_ic_msgid_t msgid)855 stmf_ic_echo_request_msg_alloc(
856     uint32_t data_len,
857     uint8_t *data,
858     stmf_ic_msgid_t msgid)
859 {
860 	return (stmf_ic_echo_request_reply_msg_alloc(
861 	    STMF_ICM_ECHO_REQUEST, data_len, data, msgid));
862 }
863 
864 stmf_ic_msg_t *
stmf_ic_echo_reply_msg_alloc(uint32_t data_len,uint8_t * data,stmf_ic_msgid_t msgid)865 stmf_ic_echo_reply_msg_alloc(
866     uint32_t data_len,
867     uint8_t *data,
868     stmf_ic_msgid_t msgid)
869 {
870 	return (stmf_ic_echo_request_reply_msg_alloc(
871 	    STMF_ICM_ECHO_REPLY, data_len, data, msgid));
872 }
873 
874 
875 static stmf_ic_msg_t *
stmf_ic_echo_request_reply_msg_alloc(stmf_ic_msg_type_t msg_type,uint32_t data_len,uint8_t * data,stmf_ic_msgid_t msgid)876 stmf_ic_echo_request_reply_msg_alloc(
877     stmf_ic_msg_type_t msg_type,
878     uint32_t data_len,
879     uint8_t *data,
880     stmf_ic_msgid_t msgid)
881 {
882 	stmf_ic_msg_t *icm = NULL;
883 	stmf_ic_echo_request_reply_msg_t *icerr = NULL;
884 
885 	icm = stmf_ic_alloc_msg_header(msg_type, msgid);
886 	icerr = kmem_zalloc(sizeof (*icerr), KM_SLEEP);
887 	icm->icm_msg = (void *)icerr;
888 
889 	icerr->icerr_data = data;
890 	icerr->icerr_datalen = data_len;
891 
892 	return (icm);
893 }
894 
895 /*
896  * msg free routines.
897  */
898 void
stmf_ic_msg_free(stmf_ic_msg_t * msg)899 stmf_ic_msg_free(stmf_ic_msg_t *msg)
900 {
901 	stmf_ic_msg_construction_method_t cmethod =
902 	    (msg->icm_nvlist ? STMF_UNMARSHAL : STMF_CONSTRUCTOR);
903 
904 	switch (msg->icm_msg_type) {
905 	case STMF_ICM_REGISTER_PROXY_PORT:
906 		stmf_ic_reg_port_msg_free(
907 		    (stmf_ic_reg_port_msg_t *)msg->icm_msg, cmethod);
908 		break;
909 
910 	case STMF_ICM_DEREGISTER_PROXY_PORT:
911 		stmf_ic_dereg_port_msg_free(
912 		    (stmf_ic_dereg_port_msg_t *)msg->icm_msg, cmethod);
913 		break;
914 
915 	case STMF_ICM_LUN_ACTIVE:
916 	case STMF_ICM_REGISTER_LUN:
917 	case STMF_ICM_DEREGISTER_LUN:
918 		stmf_ic_reg_dereg_lun_msg_free(
919 		    (stmf_ic_reg_dereg_lun_msg_t *)msg->icm_msg, cmethod);
920 		break;
921 
922 	case STMF_ICM_SCSI_CMD:
923 		stmf_ic_scsi_cmd_msg_free(
924 		    (stmf_ic_scsi_cmd_msg_t *)msg->icm_msg, cmethod);
925 		break;
926 
927 	case STMF_ICM_SCSI_DATA:
928 		stmf_ic_scsi_data_msg_free(
929 		    (stmf_ic_scsi_data_msg_t *)msg->icm_msg, cmethod);
930 		break;
931 
932 	case STMF_ICM_SCSI_DATA_XFER_DONE:
933 		stmf_ic_scsi_data_xfer_done_msg_free(
934 		    (stmf_ic_scsi_data_xfer_done_msg_t *)msg->icm_msg, cmethod);
935 		break;
936 
937 	case STMF_ICM_SCSI_STATUS:
938 		stmf_ic_scsi_status_msg_free(
939 		    (stmf_ic_scsi_status_msg_t *)msg->icm_msg, cmethod);
940 		break;
941 
942 	case STMF_ICM_R2T:
943 		stmf_ic_r2t_msg_free(
944 		    (stmf_ic_r2t_msg_t *)msg->icm_msg, cmethod);
945 		break;
946 
947 	case STMF_ICM_STATUS:
948 		stmf_ic_status_msg_free(
949 		    (stmf_ic_status_msg_t *)msg->icm_msg, cmethod);
950 		break;
951 
952 	case STMF_ICM_SESSION_CREATE:
953 	case STMF_ICM_SESSION_DESTROY:
954 		stmf_ic_session_create_destroy_msg_free(
955 		    (stmf_ic_session_create_destroy_msg_t *)msg->icm_msg,
956 		    cmethod);
957 		break;
958 
959 	case STMF_ICM_ECHO_REQUEST:
960 	case STMF_ICM_ECHO_REPLY:
961 		stmf_ic_echo_request_reply_msg_free(
962 		    (stmf_ic_echo_request_reply_msg_t *)msg->icm_msg, cmethod);
963 		break;
964 
965 	case STMF_ICM_MAX_MSG_TYPE:
966 		ASSERT(0);
967 		break;
968 
969 	default:
970 		ASSERT(0);
971 	}
972 
973 	nvlist_free(msg->icm_nvlist);
974 
975 	kmem_free(msg, sizeof (*msg));
976 }
977 
978 /*ARGSUSED*/
979 static void
stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t * m,stmf_ic_msg_construction_method_t cmethod)980 stmf_ic_reg_port_msg_free(stmf_ic_reg_port_msg_t *m,
981     stmf_ic_msg_construction_method_t cmethod)
982 {
983 	scsi_devid_desc_free(m->icrp_port_id);
984 
985 	kmem_free(m, sizeof (*m));
986 }
987 
988 
989 /*ARGSUSED*/
990 static void
stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t * m,stmf_ic_msg_construction_method_t cmethod)991 stmf_ic_dereg_port_msg_free(stmf_ic_dereg_port_msg_t *m,
992     stmf_ic_msg_construction_method_t cmethod)
993 {
994 	scsi_devid_desc_free(m->icdp_port_id);
995 
996 	kmem_free(m, sizeof (*m));
997 }
998 
999 
1000 /*
1001  * Works for both reg_lun_msg and dereg_lun_msg, since the message
1002  * payload is the same.
1003  */
1004 static void
stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1005 stmf_ic_reg_dereg_lun_msg_free(stmf_ic_reg_dereg_lun_msg_t *m,
1006     stmf_ic_msg_construction_method_t cmethod)
1007 {
1008 	if (cmethod == STMF_CONSTRUCTOR) {
1009 		kmem_free(m->icrl_lu_provider_name,
1010 		    strlen(m->icrl_lu_provider_name) + 1);
1011 	}
1012 
1013 	kmem_free(m, sizeof (*m));
1014 }
1015 
1016 static void
stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1017 stmf_ic_scsi_cmd_msg_free(stmf_ic_scsi_cmd_msg_t *m,
1018     stmf_ic_msg_construction_method_t cmethod)
1019 {
1020 	scsi_devid_desc_free(m->icsc_ini_devid);
1021 	scsi_devid_desc_free(m->icsc_tgt_devid);
1022 	stmf_remote_port_free(m->icsc_rport);
1023 	if ((cmethod == STMF_CONSTRUCTOR) && m->icsc_task_cdb) {
1024 		kmem_free(m->icsc_task_cdb, m->icsc_task_cdb_length);
1025 	}
1026 
1027 	kmem_free(m, sizeof (*m));
1028 
1029 }
1030 
1031 /*ARGSUSED*/
1032 static void
stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1033 stmf_ic_scsi_data_msg_free(stmf_ic_scsi_data_msg_t *m,
1034     stmf_ic_msg_construction_method_t cmethod)
1035 {
1036 	kmem_free(m, sizeof (*m));
1037 }
1038 
1039 /*ARGSUSED*/
1040 static void
stmf_ic_scsi_data_xfer_done_msg_free(stmf_ic_scsi_data_xfer_done_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1041 stmf_ic_scsi_data_xfer_done_msg_free(stmf_ic_scsi_data_xfer_done_msg_t *m,
1042     stmf_ic_msg_construction_method_t cmethod)
1043 {
1044 	kmem_free(m, sizeof (*m));
1045 }
1046 
1047 /*ARGSUSED*/
1048 static void
stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1049 stmf_ic_scsi_status_msg_free(stmf_ic_scsi_status_msg_t *m,
1050     stmf_ic_msg_construction_method_t cmethod)
1051 {
1052 	kmem_free(m, sizeof (*m));
1053 }
1054 
1055 /*ARGSUSED*/
1056 static void
stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1057 stmf_ic_r2t_msg_free(stmf_ic_r2t_msg_t *m,
1058     stmf_ic_msg_construction_method_t cmethod)
1059 {
1060 	kmem_free(m, sizeof (*m));
1061 }
1062 
1063 /*ARGSUSED*/
1064 static void
stmf_ic_status_msg_free(stmf_ic_status_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1065 stmf_ic_status_msg_free(stmf_ic_status_msg_t *m,
1066     stmf_ic_msg_construction_method_t cmethod)
1067 {
1068 	kmem_free(m, sizeof (*m));
1069 }
1070 
1071 /*
1072  * Works for both session_create and session_destroy msgs, since the message
1073  * payload is the same.
1074  */
1075 /*ARGSUSED*/
1076 static void
stmf_ic_session_create_destroy_msg_free(stmf_ic_session_create_destroy_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1077 stmf_ic_session_create_destroy_msg_free(stmf_ic_session_create_destroy_msg_t *m,
1078     stmf_ic_msg_construction_method_t cmethod)
1079 {
1080 	scsi_devid_desc_free(m->icscd_ini_devid);
1081 	scsi_devid_desc_free(m->icscd_tgt_devid);
1082 	stmf_remote_port_free(m->icscd_rport);
1083 
1084 	kmem_free(m, sizeof (*m));
1085 }
1086 
1087 /*ARGSUSED*/
1088 static void
stmf_ic_echo_request_reply_msg_free(stmf_ic_echo_request_reply_msg_t * m,stmf_ic_msg_construction_method_t cmethod)1089 stmf_ic_echo_request_reply_msg_free(stmf_ic_echo_request_reply_msg_t *m,
1090     stmf_ic_msg_construction_method_t cmethod)
1091 {
1092 	kmem_free(m, sizeof (*m));
1093 }
1094 
1095 
1096 /*
1097  * Marshaling routines.
1098  */
1099 
1100 static nvlist_t *
stmf_ic_msg_marshal(stmf_ic_msg_t * msg)1101 stmf_ic_msg_marshal(stmf_ic_msg_t *msg)
1102 {
1103 	nvlist_t *nvl = NULL;
1104 	int rc = 0;
1105 
1106 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
1107 	if (rc)
1108 		goto done;
1109 
1110 	NVLIST_ADD_FIELD(uint8, msg, icm_msg_type);
1111 	NVLIST_ADD_FIELD(uint64, msg, icm_msgid);
1112 
1113 	switch (msg->icm_msg_type) {
1114 	case STMF_ICM_REGISTER_PROXY_PORT:
1115 		rc = stmf_ic_reg_port_msg_marshal(nvl, msg->icm_msg);
1116 		break;
1117 
1118 
1119 	case STMF_ICM_DEREGISTER_PROXY_PORT:
1120 		rc = stmf_ic_dereg_port_msg_marshal(nvl, msg->icm_msg);
1121 		break;
1122 
1123 	case STMF_ICM_LUN_ACTIVE:
1124 	case STMF_ICM_REGISTER_LUN:
1125 	case STMF_ICM_DEREGISTER_LUN:
1126 		rc = stmf_ic_reg_dereg_lun_msg_marshal(nvl, msg->icm_msg);
1127 		break;
1128 
1129 	case STMF_ICM_SCSI_CMD:
1130 		rc = stmf_ic_scsi_cmd_msg_marshal(nvl, msg->icm_msg);
1131 		break;
1132 
1133 	case STMF_ICM_SCSI_DATA:
1134 		rc = stmf_ic_scsi_data_msg_marshal(nvl, msg->icm_msg);
1135 		break;
1136 
1137 	case STMF_ICM_SCSI_DATA_XFER_DONE:
1138 		rc = stmf_ic_scsi_data_xfer_done_msg_marshal(nvl, msg->icm_msg);
1139 		break;
1140 
1141 	case STMF_ICM_SCSI_STATUS:
1142 		rc = stmf_ic_scsi_status_msg_marshal(nvl, msg->icm_msg);
1143 		break;
1144 
1145 	case STMF_ICM_R2T:
1146 		rc = stmf_ic_r2t_msg_marshal(nvl, msg->icm_msg);
1147 		break;
1148 
1149 	case STMF_ICM_STATUS:
1150 		rc = stmf_ic_status_msg_marshal(nvl, msg->icm_msg);
1151 		break;
1152 
1153 	case STMF_ICM_SESSION_CREATE:
1154 	case STMF_ICM_SESSION_DESTROY:
1155 		rc = stmf_ic_session_create_destroy_msg_marshal(nvl,
1156 		    msg->icm_msg);
1157 		break;
1158 
1159 	case STMF_ICM_ECHO_REQUEST:
1160 	case STMF_ICM_ECHO_REPLY:
1161 		rc = stmf_ic_echo_request_reply_msg_marshal(nvl,
1162 		    msg->icm_msg);
1163 		break;
1164 
1165 	case STMF_ICM_MAX_MSG_TYPE:
1166 		ASSERT(0);
1167 		break;
1168 
1169 	default:
1170 		ASSERT(0);
1171 	}
1172 
1173 done:
1174 	if (!rc)
1175 		return (nvl);
1176 
1177 	nvlist_free(nvl);
1178 
1179 	return (NULL);
1180 }
1181 
1182 
1183 static int
stmf_ic_reg_port_msg_marshal(nvlist_t * nvl,void * msg)1184 stmf_ic_reg_port_msg_marshal(nvlist_t *nvl, void *msg)
1185 {
1186 	stmf_ic_reg_port_msg_t *m = (stmf_ic_reg_port_msg_t *)msg;
1187 	int rc = 0;
1188 
1189 	NVLIST_ADD_DEVID(m, icrp_port_id);
1190 	NVLIST_ADD_FIELD(uint16, m, icrp_relative_port_id);
1191 
1192 	NVLIST_ADD_FIELD(uint16, m, icrp_cb_arg_len);
1193 	/* only add the callback arg if necessary */
1194 	if (m->icrp_cb_arg_len) {
1195 		NVLIST_ADD_ARRAY_LEN(uint8, m, icrp_cb_arg, m->icrp_cb_arg_len);
1196 	}
1197 
1198 done:
1199 	return (rc);
1200 }
1201 
1202 static int
stmf_ic_dereg_port_msg_marshal(nvlist_t * nvl,void * msg)1203 stmf_ic_dereg_port_msg_marshal(nvlist_t *nvl, void *msg)
1204 {
1205 	stmf_ic_dereg_port_msg_t *m = (stmf_ic_dereg_port_msg_t *)msg;
1206 	int rc = 0;
1207 
1208 	NVLIST_ADD_DEVID(m, icdp_port_id);
1209 	NVLIST_ADD_FIELD(uint16, m, icdp_cb_arg_len);
1210 
1211 	/* only add the callback arg if necessary */
1212 	if (m->icdp_cb_arg_len) {
1213 		NVLIST_ADD_ARRAY_LEN(uint8, m, icdp_cb_arg, m->icdp_cb_arg_len);
1214 	}
1215 
1216 done:
1217 	return (rc);
1218 }
1219 
1220 /*
1221  * Handles STMF_ICM_LUN_ACTIVE, STMF_ICM_REGISTER_LUN and
1222  * STMF_ICM_DEREGISTER_LUN;
1223  * msg payload is the same for all.
1224  */
1225 static int
stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t * nvl,void * msg)1226 stmf_ic_reg_dereg_lun_msg_marshal(nvlist_t *nvl, void *msg)
1227 {
1228 	stmf_ic_reg_dereg_lun_msg_t *m = (stmf_ic_reg_dereg_lun_msg_t *)msg;
1229 	int rc = 0;
1230 
1231 	NVLIST_ADD_ARRAY(uint8, m, icrl_lun_id);
1232 	NVLIST_ADD_FIELD(string, m, icrl_lu_provider_name);
1233 	NVLIST_ADD_FIELD(uint16, m, icrl_cb_arg_len);
1234 
1235 	/* only add the callback arg if necessary */
1236 	if (m->icrl_cb_arg_len) {
1237 		NVLIST_ADD_ARRAY_LEN(uint8, m, icrl_cb_arg, m->icrl_cb_arg_len);
1238 	}
1239 
1240 done:
1241 	return (rc);
1242 }
1243 
1244 static int
stmf_ic_scsi_cmd_msg_marshal(nvlist_t * nvl,void * msg)1245 stmf_ic_scsi_cmd_msg_marshal(nvlist_t *nvl, void *msg)
1246 {
1247 	stmf_ic_scsi_cmd_msg_t *m = (stmf_ic_scsi_cmd_msg_t *)msg;
1248 	int rc = 0;
1249 
1250 	NVLIST_ADD_FIELD(uint64, m, icsc_task_msgid);
1251 	NVLIST_ADD_DEVID(m, icsc_ini_devid);
1252 	NVLIST_ADD_DEVID(m, icsc_tgt_devid);
1253 	NVLIST_ADD_RPORT(m, icsc_rport);
1254 	NVLIST_ADD_ARRAY(uint8, m, icsc_lun_id);
1255 	NVLIST_ADD_FIELD(uint64, m, icsc_session_id);
1256 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_lun_no, 8);
1257 	NVLIST_ADD_FIELD(uint32, m, icsc_task_expected_xfer_length);
1258 	NVLIST_ADD_FIELD(uint16, m, icsc_task_cdb_length);
1259 	/*
1260 	 * icsc_task_cdb_length may be zero in the case of a task
1261 	 * management function.
1262 	 */
1263 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_task_cdb, m->icsc_task_cdb_length);
1264 	NVLIST_ADD_FIELD(uint8, m, icsc_task_flags);
1265 	NVLIST_ADD_FIELD(uint8, m, icsc_task_priority);
1266 	NVLIST_ADD_FIELD(uint8, m, icsc_task_mgmt_function);
1267 
1268 	NVLIST_ADD_FIELD(uint32, m, icsc_immed_data_len);
1269 	/* only add immediate data if necessary */
1270 	if (m->icsc_immed_data_len) {
1271 		NVLIST_ADD_ARRAY_LEN(uint8, m, icsc_immed_data,
1272 		    m->icsc_immed_data_len);
1273 	}
1274 
1275 done:
1276 	return (rc);
1277 }
1278 
1279 static int
stmf_ic_scsi_data_msg_marshal(nvlist_t * nvl,void * msg)1280 stmf_ic_scsi_data_msg_marshal(nvlist_t *nvl, void *msg)
1281 {
1282 	stmf_ic_scsi_data_msg_t *m = (stmf_ic_scsi_data_msg_t *)msg;
1283 	int rc = 0;
1284 
1285 	NVLIST_ADD_FIELD(uint64, m, icsd_task_msgid);
1286 	NVLIST_ADD_FIELD(uint64, m, icsd_session_id);
1287 	NVLIST_ADD_ARRAY(uint8, m, icsd_lun_id);
1288 	NVLIST_ADD_FIELD(uint64, m, icsd_data_len);
1289 	NVLIST_ADD_ARRAY_LEN(uint8, m, icsd_data, m->icsd_data_len);
1290 
1291 done:
1292 	return (rc);
1293 }
1294 
1295 static int
stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t * nvl,void * msg)1296 stmf_ic_scsi_data_xfer_done_msg_marshal(nvlist_t *nvl, void *msg)
1297 {
1298 	stmf_ic_scsi_data_xfer_done_msg_t *m =
1299 	    (stmf_ic_scsi_data_xfer_done_msg_t *)msg;
1300 	int rc = 0;
1301 
1302 	NVLIST_ADD_FIELD(uint64, m, icsx_task_msgid);
1303 	NVLIST_ADD_FIELD(uint64, m, icsx_session_id);
1304 	NVLIST_ADD_FIELD(uint64, m, icsx_status);
1305 
1306 done:
1307 	return (rc);
1308 }
1309 
1310 static int
stmf_ic_scsi_status_msg_marshal(nvlist_t * nvl,void * msg)1311 stmf_ic_scsi_status_msg_marshal(nvlist_t *nvl, void *msg)
1312 {
1313 	stmf_ic_scsi_status_msg_t *m = (stmf_ic_scsi_status_msg_t *)msg;
1314 	int rc = 0;
1315 
1316 	NVLIST_ADD_FIELD(uint64, m, icss_task_msgid);
1317 	NVLIST_ADD_FIELD(uint64, m, icss_session_id);
1318 	NVLIST_ADD_ARRAY(uint8, m, icss_lun_id);
1319 	NVLIST_ADD_FIELD(uint8, m, icss_response);
1320 	NVLIST_ADD_FIELD(uint8, m, icss_status);
1321 	NVLIST_ADD_FIELD(uint8, m, icss_flags);
1322 	NVLIST_ADD_FIELD(uint32, m, icss_resid);
1323 
1324 	NVLIST_ADD_FIELD(uint8, m, icss_sense_len);
1325 
1326 	if (m->icss_sense_len)
1327 		NVLIST_ADD_ARRAY_LEN(uint8, m, icss_sense, m->icss_sense_len);
1328 
1329 done:
1330 	return (rc);
1331 }
1332 
1333 static int
stmf_ic_r2t_msg_marshal(nvlist_t * nvl,void * msg)1334 stmf_ic_r2t_msg_marshal(nvlist_t *nvl, void *msg)
1335 {
1336 	stmf_ic_r2t_msg_t *m = (stmf_ic_r2t_msg_t *)msg;
1337 	int rc = 0;
1338 
1339 	NVLIST_ADD_FIELD(uint64, m, icrt_task_msgid);
1340 	NVLIST_ADD_FIELD(uint64, m, icrt_session_id);
1341 	NVLIST_ADD_FIELD(uint32, m, icrt_offset);
1342 	NVLIST_ADD_FIELD(uint32, m, icrt_length);
1343 
1344 done:
1345 	return (rc);
1346 }
1347 
1348 static int
stmf_ic_status_msg_marshal(nvlist_t * nvl,void * msg)1349 stmf_ic_status_msg_marshal(nvlist_t *nvl, void *msg)
1350 {
1351 	stmf_ic_status_msg_t *m = (stmf_ic_status_msg_t *)msg;
1352 	int rc = 0;
1353 
1354 	NVLIST_ADD_FIELD(uint8, m, ics_msg_type);
1355 	NVLIST_ADD_FIELD(uint64, m, ics_msgid);
1356 	NVLIST_ADD_FIELD(uint8, m, ics_status);
1357 
1358 done:
1359 	return (rc);
1360 }
1361 
1362 static int
stmf_ic_session_create_destroy_msg_marshal(nvlist_t * nvl,void * msg)1363 stmf_ic_session_create_destroy_msg_marshal(nvlist_t *nvl, void *msg)
1364 {
1365 	stmf_ic_session_create_destroy_msg_t *m =
1366 	    (stmf_ic_session_create_destroy_msg_t *)msg;
1367 	int rc = 0;
1368 
1369 	NVLIST_ADD_DEVID(m, icscd_ini_devid);
1370 	NVLIST_ADD_DEVID(m, icscd_tgt_devid);
1371 	NVLIST_ADD_RPORT(m, icscd_rport);
1372 	NVLIST_ADD_FIELD(uint64, m, icscd_session_id);
1373 
1374 done:
1375 	return (rc);
1376 }
1377 
1378 static int
stmf_ic_echo_request_reply_msg_marshal(nvlist_t * nvl,void * msg)1379 stmf_ic_echo_request_reply_msg_marshal(nvlist_t *nvl, void *msg)
1380 {
1381 	stmf_ic_echo_request_reply_msg_t *m = msg;
1382 	int rc = 0;
1383 
1384 	NVLIST_ADD_FIELD(uint32, m, icerr_datalen);
1385 	if (m->icerr_datalen)
1386 		NVLIST_ADD_ARRAY_LEN(uint8, m, icerr_data, m->icerr_datalen);
1387 
1388 done:
1389 	return (rc);
1390 }
1391 
1392 /*
1393  * Allocate a new nvlist representing the scsi_devid_desc and add it
1394  * to the nvlist.
1395  */
1396 static int
stmf_ic_scsi_devid_desc_marshal(nvlist_t * parent_nvl,char * sdid_name,scsi_devid_desc_t * sdid)1397 stmf_ic_scsi_devid_desc_marshal(nvlist_t *parent_nvl,
1398 	char *sdid_name,
1399 	scsi_devid_desc_t *sdid)
1400 {
1401 	int rc = 0;
1402 	nvlist_t *nvl = NULL;
1403 
1404 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
1405 	if (rc)
1406 		goto done;
1407 
1408 	NVLIST_ADD_FIELD(uint8, sdid, protocol_id);
1409 	NVLIST_ADD_FIELD(uint8, sdid, code_set);
1410 	NVLIST_ADD_FIELD(uint8, sdid, piv);
1411 	NVLIST_ADD_FIELD(uint8, sdid, association);
1412 	NVLIST_ADD_FIELD(uint8, sdid, ident_type);
1413 	NVLIST_ADD_FIELD(uint8, sdid, ident_length);
1414 
1415 	rc = nvlist_add_uint8_array(nvl, "ident", sdid->ident,
1416 	    sdid->ident_length);
1417 	if (rc)
1418 		goto done;
1419 
1420 	rc = nvlist_add_nvlist(parent_nvl, sdid_name, nvl);
1421 done:
1422 	if (nvl) {
1423 		nvlist_free(nvl);
1424 	}
1425 	return (rc);
1426 }
1427 
1428 /*
1429  * Allocate a new nvlist representing the stmf_remote_port and add it
1430  * to the nvlist.
1431  */
1432 static int
stmf_ic_remote_port_marshal(nvlist_t * parent_nvl,char * rport_name,stmf_remote_port_t * rport)1433 stmf_ic_remote_port_marshal(nvlist_t *parent_nvl, char *rport_name,
1434 	stmf_remote_port_t *rport) {
1435 
1436 	int rc = 0;
1437 	nvlist_t *nvl = NULL;
1438 
1439 	rc = nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP);
1440 	if (rc)
1441 		goto done;
1442 
1443 	NVLIST_ADD_FIELD(uint16, rport, rport_tptid_sz);
1444 	rc = nvlist_add_uint8_array(nvl, "rport_tptid",
1445 	    (uint8_t *)rport->rport_tptid, rport->rport_tptid_sz);
1446 	if (rc)
1447 		goto done;
1448 
1449 	rc = nvlist_add_nvlist(parent_nvl, rport_name, nvl);
1450 done:
1451 	if (nvl) {
1452 		nvlist_free(nvl);
1453 	}
1454 	return (rc);
1455 }
1456 
1457 /*
1458  * Unmarshaling routines.
1459  */
1460 
1461 static stmf_ic_msg_t *
stmf_ic_msg_unmarshal(nvlist_t * nvl)1462 stmf_ic_msg_unmarshal(nvlist_t *nvl)
1463 {
1464 	stmf_ic_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1465 	uint8_t msg_type;
1466 	int rc = 0;
1467 
1468 	/*
1469 	 * We'd like to do this:
1470 	 *
1471 	 *   NVLIST_LOOKUP_FIELD(uint8, m, icm_msg_type);
1472 	 *
1473 	 * but the fact that msg type is an enum causes type problems.
1474 	 */
1475 	rc = nvlist_lookup_uint8(nvl, "icm_msg_type", &msg_type);
1476 	if (rc) {
1477 		stmf_ic_nvlookup_warn(__func__, "icm_msg_type");
1478 		goto done;
1479 	}
1480 
1481 	m->icm_msg_type = msg_type;
1482 	m->icm_nvlist = nvl;
1483 
1484 	NVLIST_LOOKUP_FIELD(uint64, m, icm_msgid);
1485 
1486 	switch (m->icm_msg_type) {
1487 
1488 	case STMF_ICM_REGISTER_PROXY_PORT:
1489 		m->icm_msg = stmf_ic_reg_port_msg_unmarshal(nvl);
1490 		break;
1491 
1492 
1493 	case STMF_ICM_DEREGISTER_PROXY_PORT:
1494 		m->icm_msg = stmf_ic_dereg_port_msg_unmarshal(nvl);
1495 		break;
1496 
1497 	case STMF_ICM_LUN_ACTIVE:
1498 	case STMF_ICM_REGISTER_LUN:
1499 	case STMF_ICM_DEREGISTER_LUN:
1500 		m->icm_msg = stmf_ic_reg_dereg_lun_msg_unmarshal(nvl);
1501 		break;
1502 
1503 	case STMF_ICM_SCSI_CMD:
1504 		m->icm_msg = stmf_ic_scsi_cmd_msg_unmarshal(nvl);
1505 		break;
1506 
1507 	case STMF_ICM_SCSI_DATA:
1508 		m->icm_msg = stmf_ic_scsi_data_msg_unmarshal(nvl);
1509 		break;
1510 
1511 	case STMF_ICM_SCSI_DATA_XFER_DONE:
1512 		m->icm_msg = stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvl);
1513 		break;
1514 
1515 	case STMF_ICM_SCSI_STATUS:
1516 		m->icm_msg = stmf_ic_scsi_status_msg_unmarshal(nvl);
1517 		break;
1518 
1519 	case STMF_ICM_R2T:
1520 		m->icm_msg = stmf_ic_r2t_msg_unmarshal(nvl);
1521 		break;
1522 
1523 	case STMF_ICM_STATUS:
1524 		m->icm_msg = stmf_ic_status_msg_unmarshal(nvl);
1525 		break;
1526 
1527 	case STMF_ICM_SESSION_CREATE:
1528 	case STMF_ICM_SESSION_DESTROY:
1529 		m->icm_msg = stmf_ic_session_create_destroy_msg_unmarshal(nvl);
1530 		break;
1531 
1532 	case STMF_ICM_ECHO_REQUEST:
1533 	case STMF_ICM_ECHO_REPLY:
1534 		m->icm_msg = stmf_ic_echo_request_reply_msg_unmarshal(nvl);
1535 		break;
1536 
1537 	case STMF_ICM_MAX_MSG_TYPE:
1538 		ASSERT(0);
1539 		break;
1540 
1541 	default:
1542 		ASSERT(0);
1543 	}
1544 
1545 done:
1546 
1547 	if (!m->icm_msg) {
1548 		kmem_free(m, sizeof (*m));
1549 		return (NULL);
1550 	}
1551 
1552 	return (m);
1553 }
1554 
1555 static void *
stmf_ic_reg_port_msg_unmarshal(nvlist_t * nvl)1556 stmf_ic_reg_port_msg_unmarshal(nvlist_t *nvl)
1557 {
1558 	nvlist_t *nvl_port_id = NULL;
1559 	int rc = 0;
1560 	stmf_ic_reg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1561 
1562 	rc = nvlist_lookup_nvlist(nvl, "icrp_port_id", &nvl_port_id);
1563 	if (rc) {
1564 		stmf_ic_nvlookup_warn(__func__, "icrp_port_id nvl");
1565 		rc = ENOMEM; /* XXX */
1566 		goto done;
1567 	}
1568 
1569 	m->icrp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id);
1570 	if (m->icrp_port_id == NULL) {
1571 		stmf_ic_nvlookup_warn(__func__, "icrp_port_id");
1572 		rc = ENOMEM; /* XXX */
1573 		goto done;
1574 	}
1575 
1576 	NVLIST_LOOKUP_FIELD(uint16, m, icrp_relative_port_id);
1577 	NVLIST_LOOKUP_FIELD(uint16, m, icrp_cb_arg_len);
1578 
1579 	if (m->icrp_cb_arg_len) {
1580 		m->icrp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
1581 		    "icrp_cb_arg", m->icrp_cb_arg_len, NULL);
1582 		if (m->icrp_cb_arg == NULL) {
1583 			stmf_ic_nvlookup_warn(__func__, "icrp_cb_arg");
1584 			rc = ENOMEM; /* XXX */
1585 			goto done;
1586 		}
1587 	}
1588 
1589 done:
1590 	if (!rc)
1591 		return (m);
1592 
1593 	stmf_ic_reg_port_msg_free(m, STMF_UNMARSHAL);
1594 
1595 	return (NULL);
1596 }
1597 
1598 /*
1599  * XXX largely the same as stmf_ic_reg_port_msg_unmarshal()
1600  * Common stuff should be factored out.  Type issues may make this
1601  * painful.
1602  */
1603 static void *
stmf_ic_dereg_port_msg_unmarshal(nvlist_t * nvl)1604 stmf_ic_dereg_port_msg_unmarshal(nvlist_t *nvl)
1605 {
1606 	nvlist_t *nvl_port_id = NULL;
1607 	int rc = 0;
1608 	stmf_ic_dereg_port_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1609 
1610 	rc = nvlist_lookup_nvlist(nvl, "icdp_port_id", &nvl_port_id);
1611 	if (rc) {
1612 		stmf_ic_nvlookup_warn(__func__, "icdp_port_id nvl");
1613 		goto done;
1614 	}
1615 
1616 	m->icdp_port_id = stmf_ic_scsi_devid_desc_unmarshal(nvl_port_id);
1617 	if (m->icdp_port_id == NULL) {
1618 		stmf_ic_nvlookup_warn(__func__, "icdp_port_id");
1619 		rc = ENOMEM; /* XXX */
1620 		goto done;
1621 	}
1622 
1623 	NVLIST_LOOKUP_FIELD(uint16, m, icdp_cb_arg_len);
1624 
1625 	if (m->icdp_cb_arg_len) {
1626 		m->icdp_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
1627 		    "icdp_cb_arg", m->icdp_cb_arg_len, NULL);
1628 		if (m->icdp_cb_arg == NULL) {
1629 			stmf_ic_nvlookup_warn(__func__, "icdp_cb_arg");
1630 			rc = ENOMEM; /* XXX */
1631 			goto done;
1632 		}
1633 	}
1634 
1635 done:
1636 	if (!rc)
1637 		return (m);
1638 
1639 	stmf_ic_dereg_port_msg_free(m, STMF_UNMARSHAL);
1640 
1641 	return (NULL);
1642 }
1643 
1644 static void *
stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t * nvl)1645 stmf_ic_reg_dereg_lun_msg_unmarshal(nvlist_t *nvl)
1646 {
1647 	int rc = 0;
1648 	stmf_ic_reg_dereg_lun_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1649 
1650 	if (! stmf_ic_uint8_array_unmarshal(nvl, "icrl_lun_id",
1651 	    sizeof (m->icrl_lun_id), m->icrl_lun_id)) {
1652 		stmf_ic_nvlookup_warn(__func__, "icrl_lun_id");
1653 		rc = ENOMEM; /* XXX */
1654 		goto done;
1655 	}
1656 
1657 	m->icrl_lu_provider_name = stmf_ic_string_unmarshal(nvl,
1658 	    "icrl_lu_provider_name");
1659 
1660 	if (!m->icrl_lu_provider_name) {
1661 		stmf_ic_nvlookup_warn(__func__, "icrl_lu_provider_name");
1662 		rc = ENOMEM; /* XXX */
1663 		goto done;
1664 	}
1665 
1666 	NVLIST_LOOKUP_FIELD(uint16, m, icrl_cb_arg_len);
1667 
1668 	if (m->icrl_cb_arg_len) {
1669 		m->icrl_cb_arg = stmf_ic_uint8_array_unmarshal(nvl,
1670 		    "icrl_cb_arg", m->icrl_cb_arg_len, NULL);
1671 		if (m->icrl_cb_arg == NULL) {
1672 			stmf_ic_nvlookup_warn(__func__, "icrl_cb_arg");
1673 			rc = ENOMEM; /* XXX */
1674 			goto done;
1675 		}
1676 	}
1677 
1678 done:
1679 	if (!rc)
1680 		return (m);
1681 
1682 	stmf_ic_reg_dereg_lun_msg_free(m, STMF_UNMARSHAL);
1683 
1684 	return (NULL);
1685 }
1686 
1687 static void *
stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t * nvl)1688 stmf_ic_scsi_cmd_msg_unmarshal(nvlist_t *nvl)
1689 {
1690 	int rc = 0;
1691 	stmf_ic_scsi_cmd_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1692 
1693 	if (nvlist_lookup_pairs(nvl, 0,
1694 	    NV_PAIR(UINT64, m, icsc_task_msgid),
1695 	    NV_PAIR(UINT64, m, icsc_session_id),
1696 	    NV_PAIR(UINT32, m, icsc_task_expected_xfer_length),
1697 	    NV_PAIR(UINT16, m, icsc_task_cdb_length),
1698 	    NV_PAIR(UINT8, m, icsc_task_flags),
1699 	    NV_PAIR(UINT8, m, icsc_task_mgmt_function),
1700 	    NV_PAIR(UINT32, m, icsc_immed_data_len),
1701 	    NULL) != 0) {
1702 		stmf_ic_nvlookup_warn(__func__, "icsc_task_msgid and friends");
1703 		rc = ENOMEM; /* XXX need something better */
1704 		goto done;
1705 	}
1706 
1707 	m->icsc_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1708 	    nvl, "icsc_ini_devid");
1709 	if (m->icsc_ini_devid == NULL) {
1710 		stmf_ic_nvlookup_warn(__func__, "icsc_ini_devid");
1711 		rc = ENOMEM;
1712 		goto done;
1713 	}
1714 
1715 	m->icsc_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1716 	    nvl, "icsc_tgt_devid");
1717 	if (m->icsc_tgt_devid == NULL) {
1718 		stmf_ic_nvlookup_warn(__func__, "icsc_tgt_devid");
1719 		rc = ENOMEM;
1720 		goto done;
1721 	}
1722 
1723 	m->icsc_rport = stmf_ic_lookup_remote_port_and_unmarshal(
1724 	    nvl, "icsc_rport");
1725 	if (m->icsc_rport == NULL) {
1726 		stmf_ic_nvlookup_warn(__func__, "icsc_rport");
1727 		rc = ENOMEM;
1728 		goto done;
1729 	}
1730 
1731 	/* icsc_lun_id */
1732 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_lun_id",
1733 	    sizeof (m->icsc_lun_id), m->icsc_lun_id)) {
1734 		stmf_ic_nvlookup_warn(__func__, "icsc_lun_id");
1735 		rc = ENOMEM;
1736 		goto done;
1737 	}
1738 
1739 	/* icsc_task_lun_no */
1740 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsc_task_lun_no",
1741 	    sizeof (m->icsc_task_lun_no), m->icsc_task_lun_no)) {
1742 		stmf_ic_nvlookup_warn(__func__, "icsc_task_lun_no");
1743 		rc = ENOMEM;
1744 		goto done;
1745 	}
1746 
1747 	/* icsc_task_cdb */
1748 	if (m->icsc_task_cdb_length) {
1749 		m->icsc_task_cdb = stmf_ic_uint8_array_unmarshal(nvl,
1750 		    "icsc_task_cdb", m->icsc_task_cdb_length, NULL);
1751 		if (!m->icsc_task_cdb) {
1752 			stmf_ic_nvlookup_warn(__func__, "icsc_task_cdb");
1753 			rc = ENOMEM;
1754 			goto done;
1755 		}
1756 	}
1757 
1758 	/* immediate data, if there is any */
1759 	if (m->icsc_immed_data_len) {
1760 		m->icsc_immed_data = stmf_ic_uint8_array_unmarshal(nvl,
1761 		    "icsc_immed_data", m->icsc_immed_data_len, NULL);
1762 		if (!m->icsc_immed_data) {
1763 			stmf_ic_nvlookup_warn(__func__, "icsc_immed_data");
1764 			rc = ENOMEM;
1765 			goto done;
1766 		}
1767 	}
1768 
1769 done:
1770 	if (!rc)
1771 		return (m);
1772 
1773 	stmf_ic_scsi_cmd_msg_free(m, STMF_UNMARSHAL);
1774 
1775 	return (NULL);
1776 }
1777 
1778 static void *
stmf_ic_scsi_data_msg_unmarshal(nvlist_t * nvl)1779 stmf_ic_scsi_data_msg_unmarshal(nvlist_t *nvl)
1780 {
1781 	int rc = 0;
1782 	stmf_ic_scsi_data_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1783 
1784 	if (nvlist_lookup_pairs(nvl, 0,
1785 	    NV_PAIR(UINT64, m, icsd_task_msgid),
1786 	    NV_PAIR(UINT64, m, icsd_session_id),
1787 	    NV_PAIR(UINT64, m, icsd_data_len),
1788 	    NULL) != 0) {
1789 		stmf_ic_nvlookup_warn(__func__, "icsd_task_msgid and friends");
1790 		rc = ENOMEM; /* XXX need something better */
1791 		goto done;
1792 	}
1793 
1794 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icsd_lun_id",
1795 	    sizeof (m->icsd_lun_id), m->icsd_lun_id)) {
1796 		stmf_ic_nvlookup_warn(__func__, "icsd_lun_id");
1797 		rc = ENOMEM;
1798 		goto done;
1799 	}
1800 
1801 	m->icsd_data = stmf_ic_uint8_array_unmarshal(nvl, "icsd_data",
1802 	    m->icsd_data_len, NULL);
1803 	if (!m->icsd_data) {
1804 		stmf_ic_nvlookup_warn(__func__, "icsd_data");
1805 		rc = ENOMEM;
1806 		goto done;
1807 	}
1808 
1809 done:
1810 	if (!rc)
1811 		return (m);
1812 
1813 	stmf_ic_scsi_data_msg_free(m, STMF_UNMARSHAL);
1814 
1815 	return (NULL);
1816 }
1817 
1818 static void *
stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t * nvl)1819 stmf_ic_scsi_data_xfer_done_msg_unmarshal(nvlist_t *nvl)
1820 {
1821 	int rc = 0;
1822 	stmf_ic_scsi_data_xfer_done_msg_t *m =
1823 	    kmem_zalloc(sizeof (*m), KM_SLEEP);
1824 
1825 	if (nvlist_lookup_pairs(nvl, 0,
1826 	    NV_PAIR(UINT64, m, icsx_task_msgid),
1827 	    NV_PAIR(UINT64, m, icsx_session_id),
1828 	    NV_PAIR(UINT64, m, icsx_status),
1829 	    NULL) != 0) {
1830 		stmf_ic_nvlookup_warn(__func__, "icsx_task_msgid and friends");
1831 		rc = ENOMEM; /* XXX need something better */
1832 		goto done;
1833 	}
1834 
1835 done:
1836 	if (!rc)
1837 		return (m);
1838 
1839 	stmf_ic_scsi_data_xfer_done_msg_free(m, STMF_UNMARSHAL);
1840 
1841 	return (NULL);
1842 }
1843 
1844 static void *
stmf_ic_scsi_status_msg_unmarshal(nvlist_t * nvl)1845 stmf_ic_scsi_status_msg_unmarshal(nvlist_t *nvl)
1846 {
1847 	int rc = 0;
1848 	stmf_ic_scsi_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1849 
1850 	if (nvlist_lookup_pairs(nvl, 0,
1851 	    NV_PAIR(UINT64, m, icss_task_msgid),
1852 	    NV_PAIR(UINT64, m, icss_session_id),
1853 	    NV_PAIR(UINT8, m, icss_response),
1854 	    NV_PAIR(UINT8, m, icss_status),
1855 	    NV_PAIR(UINT8, m, icss_flags),
1856 	    NV_PAIR(UINT32, m, icss_resid),
1857 	    NV_PAIR(UINT8, m, icss_sense_len),
1858 	    NULL) != 0) {
1859 		stmf_ic_nvlookup_warn(__func__, "icss_task_msgid and friends");
1860 		rc = ENOMEM; /* XXX need something better */
1861 		goto done;
1862 	}
1863 
1864 	if (!stmf_ic_uint8_array_unmarshal(nvl, "icss_lun_id",
1865 	    sizeof (m->icss_lun_id), m->icss_lun_id)) {
1866 		stmf_ic_nvlookup_warn(__func__, "icss_lun_id");
1867 		rc = ENOMEM;
1868 		goto done;
1869 	}
1870 
1871 	if (m->icss_sense_len) {
1872 		m->icss_sense = stmf_ic_uint8_array_unmarshal(nvl, "icss_sense",
1873 		    m->icss_sense_len, NULL);
1874 		if (!m->icss_sense) {
1875 			stmf_ic_nvlookup_warn(__func__, "icss_sense");
1876 			rc = ENOMEM;
1877 			goto done;
1878 		}
1879 	}
1880 done:
1881 	if (!rc)
1882 		return (m);
1883 
1884 	stmf_ic_scsi_status_msg_free(m, STMF_UNMARSHAL);
1885 
1886 	return (NULL);
1887 }
1888 
1889 static void *
stmf_ic_r2t_msg_unmarshal(nvlist_t * nvl)1890 stmf_ic_r2t_msg_unmarshal(nvlist_t *nvl)
1891 {
1892 	int rc = 0;
1893 	stmf_ic_r2t_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
1894 
1895 	if (nvlist_lookup_pairs(nvl, 0,
1896 	    NV_PAIR(UINT64, m, icrt_task_msgid),
1897 	    NV_PAIR(UINT64, m, icrt_session_id),
1898 	    NV_PAIR(UINT32, m, icrt_offset),
1899 	    NV_PAIR(UINT32, m, icrt_length),
1900 	    NULL) != 0) {
1901 		stmf_ic_nvlookup_warn(__func__, "icrt_task_msgid and friends");
1902 		rc = ENOMEM; /* XXX need something better */
1903 		goto done;
1904 	}
1905 
1906 done:
1907 	if (!rc)
1908 		return (m);
1909 
1910 	stmf_ic_r2t_msg_free(m, STMF_UNMARSHAL);
1911 
1912 	return (NULL);
1913 }
1914 
1915 static void *
stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t * nvl)1916 stmf_ic_session_create_destroy_msg_unmarshal(nvlist_t *nvl)
1917 {
1918 	int rc = 0;
1919 	stmf_ic_session_create_destroy_msg_t *m = kmem_zalloc(sizeof (*m),
1920 	    KM_SLEEP);
1921 
1922 	if (nvlist_lookup_pairs(nvl, 0,
1923 	    NV_PAIR(UINT64, m, icscd_session_id),
1924 	    NULL) != 0) {
1925 		stmf_ic_nvlookup_warn(__func__, "icsd_session_id");
1926 		rc = ENOMEM; /* XXX need something better */
1927 		goto done;
1928 	}
1929 
1930 	m->icscd_ini_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1931 	    nvl, "icscd_ini_devid");
1932 	if (m->icscd_ini_devid == NULL) {
1933 		stmf_ic_nvlookup_warn(__func__, "icsd_ini_devid");
1934 		rc = ENOMEM;
1935 		goto done;
1936 	}
1937 
1938 	m->icscd_tgt_devid = stmf_ic_lookup_scsi_devid_desc_and_unmarshal(
1939 	    nvl, "icscd_tgt_devid");
1940 	if (m->icscd_tgt_devid == NULL) {
1941 		stmf_ic_nvlookup_warn(__func__, "icsd_tgt_devid");
1942 		rc = ENOMEM;
1943 		goto done;
1944 	}
1945 
1946 	m->icscd_rport = stmf_ic_lookup_remote_port_and_unmarshal(
1947 	    nvl, "icscd_rport");
1948 	if (m->icscd_rport == NULL) {
1949 		stmf_ic_nvlookup_warn(__func__, "icscd_rport");
1950 		rc = ENOMEM;
1951 		goto done;
1952 	}
1953 
1954 done:
1955 	if (!rc)
1956 		return (m);
1957 
1958 	stmf_ic_session_create_destroy_msg_free(m, STMF_UNMARSHAL);
1959 
1960 	return (NULL);
1961 }
1962 
1963 static void *
stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t * nvl)1964 stmf_ic_echo_request_reply_msg_unmarshal(nvlist_t *nvl)
1965 {
1966 	int rc = 0;
1967 	stmf_ic_echo_request_reply_msg_t *m = kmem_zalloc(sizeof (*m),
1968 	    KM_SLEEP);
1969 
1970 	if (nvlist_lookup_pairs(nvl, 0,
1971 	    NV_PAIR(UINT32, m, icerr_datalen),
1972 	    NULL) != 0) {
1973 		stmf_ic_nvlookup_warn(__func__, "icerr_datalen");
1974 		rc = ENOMEM; /* XXX need something better */
1975 		goto done;
1976 	}
1977 
1978 	/* immediate data, if there is any */
1979 	if (m->icerr_datalen) {
1980 		m->icerr_data = stmf_ic_uint8_array_unmarshal(nvl,
1981 		    "icerr_data", m->icerr_datalen, NULL);
1982 		if (!m->icerr_data) {
1983 			stmf_ic_nvlookup_warn(__func__, "icerr_data");
1984 			rc = ENOMEM;
1985 			goto done;
1986 		}
1987 	}
1988 
1989 done:
1990 	if (!rc)
1991 		return (m);
1992 
1993 	stmf_ic_echo_request_reply_msg_free(m, STMF_UNMARSHAL);
1994 
1995 	return (NULL);
1996 }
1997 
1998 static void *
stmf_ic_status_msg_unmarshal(nvlist_t * nvl)1999 stmf_ic_status_msg_unmarshal(nvlist_t *nvl)
2000 {
2001 	int rc = 0;
2002 	stmf_ic_status_msg_t *m = kmem_zalloc(sizeof (*m), KM_SLEEP);
2003 
2004 	if (nvlist_lookup_pairs(nvl, 0,
2005 	    NV_PAIR(UINT8, m, ics_msg_type),
2006 	    NV_PAIR(UINT64, m, ics_msgid),
2007 	    NV_PAIR(UINT8, m, ics_status),
2008 	    NULL) != 0) {
2009 		stmf_ic_nvlookup_warn(__func__, "ics_msg_type and friends");
2010 		rc = ENOMEM; /* XXX need something better */
2011 		goto done;
2012 	}
2013 
2014 done:
2015 	if (!rc)
2016 		return (m);
2017 
2018 	kmem_free(m, sizeof (*m));
2019 	return (NULL);
2020 }
2021 
2022 
2023 static scsi_devid_desc_t *
stmf_ic_lookup_scsi_devid_desc_and_unmarshal(nvlist_t * nvl,char * field_name)2024 stmf_ic_lookup_scsi_devid_desc_and_unmarshal(nvlist_t *nvl, char *field_name)
2025 {
2026 	nvlist_t *nvl_devid = NULL;
2027 	scsi_devid_desc_t *did = NULL;
2028 	int rc;
2029 
2030 	rc = nvlist_lookup_nvlist(nvl, field_name, &nvl_devid);
2031 	if (rc) {
2032 		goto done;
2033 	}
2034 
2035 	did = stmf_ic_scsi_devid_desc_unmarshal(nvl_devid);
2036 
2037 done:
2038 	return (did);
2039 }
2040 
2041 
2042 static scsi_devid_desc_t *
stmf_ic_scsi_devid_desc_unmarshal(nvlist_t * nvl)2043 stmf_ic_scsi_devid_desc_unmarshal(nvlist_t *nvl)
2044 {
2045 	scsi_devid_desc_t *sdid = NULL;
2046 	uint8_t ident_length = 0;
2047 	size_t sdid_size;
2048 	int rc = 0;
2049 
2050 	/*
2051 	 * we get the ident_length first, since that's the only
2052 	 * variable-sized field in the struct.
2053 	 */
2054 	rc = nvlist_lookup_uint8(nvl, "ident_length", &ident_length);
2055 	if (rc)
2056 		goto done;
2057 
2058 	sdid_size = sizeof_scsi_devid_desc(ident_length);
2059 	sdid = kmem_zalloc(sdid_size, KM_SLEEP);
2060 
2061 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, protocol_id);
2062 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, code_set);
2063 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, piv);
2064 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, association);
2065 	NVLIST_LOOKUP_BIT_FIELD(uint8, sdid, ident_type);
2066 
2067 	sdid->ident_length = ident_length;
2068 
2069 	if (!stmf_ic_uint8_array_unmarshal(nvl, "ident",
2070 	    sdid->ident_length, sdid->ident)) {
2071 		rc = ENOMEM; /* XXX */
2072 		goto done;
2073 	}
2074 
2075 done:
2076 	if (!rc)
2077 		return (sdid);
2078 
2079 	kmem_free(sdid, sdid_size);
2080 
2081 	return (NULL);
2082 }
2083 
2084 static stmf_remote_port_t *
stmf_ic_lookup_remote_port_and_unmarshal(nvlist_t * nvl,char * field_name)2085 stmf_ic_lookup_remote_port_and_unmarshal(nvlist_t *nvl, char *field_name)
2086 {
2087 	nvlist_t *nvl_rport = NULL;
2088 
2089 	if (nvlist_lookup_nvlist(nvl, field_name, &nvl_rport) != 0)
2090 		return (NULL);
2091 
2092 	return (stmf_ic_remote_port_unmarshal(nvl_rport));
2093 }
2094 
2095 static stmf_remote_port_t *
stmf_ic_remote_port_unmarshal(nvlist_t * nvl)2096 stmf_ic_remote_port_unmarshal(nvlist_t *nvl)
2097 {
2098 	stmf_remote_port_t *rport = NULL;
2099 	uint16_t rport_tptid_sz = 0;
2100 	int rc = 0;
2101 
2102 	rc = nvlist_lookup_uint16(nvl, "rport_tptid_sz", &rport_tptid_sz);
2103 	if (rc || rport_tptid_sz < sizeof (scsi_transport_id_t))
2104 		return (NULL);
2105 
2106 	rport = stmf_remote_port_alloc(rport_tptid_sz);
2107 	if (!stmf_ic_uint8_array_unmarshal(nvl, "rport_tptid", rport_tptid_sz,
2108 	    (uint8_t *)rport->rport_tptid)) {
2109 		stmf_remote_port_free(rport);
2110 		rport = NULL;
2111 	}
2112 	return (rport);
2113 }
2114 
2115 /*
2116  * Unmarshal a uint8_t array.
2117  *
2118  * Takes a buf argument:
2119  *
2120  * - if non-null, the array contents are copied into the buf,
2121  *   and we return a pointer to the buffer.
2122  *
2123  * - if null, we return a pointer to the unmarshaled data, which
2124  *   resides in the nvlist.
2125  *
2126  * Returns NULL on failure.
2127  */
2128 static uint8_t *
stmf_ic_uint8_array_unmarshal(nvlist_t * nvl,char * field_name,uint64_t len,uint8_t * buf)2129 stmf_ic_uint8_array_unmarshal(
2130     nvlist_t *nvl,
2131     char *field_name,
2132     uint64_t len,
2133     uint8_t *buf)	/* non-NULL: copy array into buf */
2134 {
2135 	uint8_t *array = NULL;
2136 	uint_t actual_len;
2137 	int rc = 0;
2138 
2139 	rc = nvlist_lookup_uint8_array(nvl, field_name, &array, &actual_len);
2140 	if (rc) {
2141 		return (NULL);
2142 	}
2143 
2144 	if (len != actual_len) {
2145 		cmn_err(CE_WARN,
2146 		    "stmf_ic_uint8_array_unmarshal: wrong len (%d != %d)",
2147 		    (int)len, actual_len);
2148 		return (NULL);
2149 	}
2150 
2151 	if (buf) {
2152 		/* preallocated buf, copy in */
2153 		bcopy(array, buf, len);
2154 	} else {
2155 		/* return a pointer to the underlying array in the nvlist */
2156 		buf = array;
2157 	}
2158 
2159 	return (buf);
2160 }
2161 
2162 /*
2163  * Unmarshal a string.
2164  *
2165  * Returns NULL on failure.
2166  */
2167 static char *
stmf_ic_string_unmarshal(nvlist_t * nvl,char * field_name)2168 stmf_ic_string_unmarshal(
2169     nvlist_t *nvl,
2170     char *field_name)
2171 {
2172 	char *s = NULL;
2173 	int rc = 0;
2174 
2175 	rc = nvlist_lookup_string(nvl, field_name, &s);
2176 	if (rc) {
2177 		return (NULL);
2178 	}
2179 
2180 	return (s);
2181 }
2182 
2183 /*
2184  * Utility routines.
2185  */
2186 
2187 static stmf_ic_msg_t *
stmf_ic_alloc_msg_header(stmf_ic_msg_type_t msg_type,stmf_ic_msgid_t msgid)2188 stmf_ic_alloc_msg_header(
2189     stmf_ic_msg_type_t msg_type,
2190     stmf_ic_msgid_t msgid)
2191 {
2192 	stmf_ic_msg_t *icm;
2193 
2194 	icm = (stmf_ic_msg_t *)kmem_zalloc(sizeof (*icm), KM_SLEEP);
2195 	icm->icm_msg_type = msg_type;
2196 	icm->icm_msgid = msgid;
2197 
2198 	return (icm);
2199 }
2200 
2201 static size_t
sizeof_scsi_devid_desc(int ident_length)2202 sizeof_scsi_devid_desc(int ident_length)
2203 {
2204 	int num_ident_elems;
2205 	size_t size;
2206 
2207 	ASSERT(ident_length > 0);
2208 
2209 	/*
2210 	 * Need to account for the fact that there's
2211 	 * already a single element in scsi_devid_desc_t.
2212 	 *
2213 	 * XXX would really like to have a way to determine the
2214 	 * sizeof (struct scsi_devid_desc.ident[0]), but
2215 	 * it's not clear that can be done.
2216 	 * Thus, this code relies on the knowledge of the type of
2217 	 * that field.
2218 	 */
2219 	num_ident_elems = ident_length - 1;
2220 	size = sizeof (scsi_devid_desc_t) +
2221 	    (num_ident_elems * sizeof (uint8_t));
2222 
2223 	return (size);
2224 }
2225 
2226 
2227 /*
2228  * Duplicate the scsi_devid_desc_t.
2229  */
2230 static scsi_devid_desc_t *
scsi_devid_desc_dup(scsi_devid_desc_t * did)2231 scsi_devid_desc_dup(scsi_devid_desc_t *did)
2232 {
2233 	scsi_devid_desc_t *dup;
2234 	size_t dup_size;
2235 
2236 	ASSERT(did->ident_length > 0);
2237 
2238 	dup_size = sizeof_scsi_devid_desc(did->ident_length);
2239 	dup = (scsi_devid_desc_t *)kmem_zalloc(dup_size, KM_SLEEP);
2240 	bcopy(did, dup, dup_size);
2241 	return (dup);
2242 }
2243 
2244 /*
2245  * May be called with a null pointer.
2246  */
2247 static void
scsi_devid_desc_free(scsi_devid_desc_t * did)2248 scsi_devid_desc_free(scsi_devid_desc_t *did)
2249 {
2250 	if (!did)
2251 		return;
2252 
2253 	kmem_free(did, sizeof_scsi_devid_desc(did->ident_length));
2254 }
2255 
2256 /*
2257  * Duplicate the stmf_remote_port_t.
2258  */
2259 static stmf_remote_port_t *
remote_port_dup(stmf_remote_port_t * rport)2260 remote_port_dup(stmf_remote_port_t *rport)
2261 {
2262 	stmf_remote_port_t *dup = NULL;
2263 	if (rport) {
2264 		dup = stmf_remote_port_alloc(rport->rport_tptid_sz);
2265 		bcopy(rport->rport_tptid, dup->rport_tptid,
2266 		    rport->rport_tptid_sz);
2267 	}
2268 	return (dup);
2269 }
2270 
2271 /*
2272  * Helper functions, returns NULL if no memory.
2273  */
2274 static char *
stmf_ic_strdup(char * str)2275 stmf_ic_strdup(char *str)
2276 {
2277 	char *copy;
2278 
2279 	ASSERT(str);
2280 
2281 	copy = kmem_zalloc(strlen(str) + 1, KM_SLEEP);
2282 	(void) strcpy(copy, str);
2283 	return (copy);
2284 }
2285 
2286 static inline void
stmf_ic_nvlookup_warn(const char * func,char * field)2287 stmf_ic_nvlookup_warn(const char *func, char *field)
2288 {
2289 	cmn_err(CE_WARN, "%s: nvlist lookup of %s failed", func, field);
2290 }
2291