Home | History | Annotate | Download | only in common
      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 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <arpa/inet.h>
     27 #include <sys/socket.h>
     28 #include <sys/types.h>
     29 #include <stdarg.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <strings.h>
     33 #include <unistd.h>
     34 #include <syslog.h>
     35 #include <errno.h>
     36 #include <wchar.h>
     37 #include <widec.h>
     38 #include <libsysevent.h>
     39 #include <sys/nvpair.h>
     40 #include <fcntl.h>
     41 #include <stdio.h>
     42 #include <time.h>
     43 #include <libdevinfo.h>
     44 #include <sys/scsi/generic/commands.h>
     45 #include <sys/scsi/generic/status.h>
     46 #include <sys/scsi/adapters/iscsi_if.h>
     47 #include <sys/iscsi_protocol.h>
     48 #include <ima.h>
     49 #include <libsun_ima.h>
     50 
     51 #define	LIBRARY_PROPERTY_IMPLEMENTATION_VERSION	L"1.0.0"
     52 #define	LIBRARY_PROPERTY_VENDOR			L"Sun Microsystems, Inc."
     53 #define	OS_DEVICE_NAME 				"/devices/iscsi"
     54 #define	LIBRARY_FILE_NAME			L"libsun_ima.so"
     55 
     56 #define	OS_DEVICE_NAME_LEN		256
     57 #define	USCSI_TIMEOUT_IN_SEC		10
     58 #define	MAX_AUTHMETHODS			10
     59 #define	NUM_SUPPORTED_AUTH_METHODS	2
     60 #define	SUN_IMA_MAX_DIGEST_ALGORITHMS	2	/* NONE and CRC 32 */
     61 #define	SUN_IMA_IP_ADDRESS_LEN		256
     62 #define	SUN_IMA_IP_PORT_LEN		64
     63 #define	SUN_IMA_MAX_RADIUS_SECRET_LEN	128
     64 #define	MAX_LONG_LONG_STRING_LEN	10
     65 #define	MAX_INQUIRY_BUFFER_LEN		0xffff
     66 #define	MAX_REPORT_LUNS_BUFFER_LEN	0xffffffff
     67 #define	MAX_READ_CAPACITY16_BUFFER_LEN	0xffffffff
     68 
     69 /* Forward declaration */
     70 #define	BOOL_PARAM			1
     71 #define	MIN_MAX_PARAM			2
     72 
     73 /* OK */
     74 #define	DISC_ADDR_OK			0
     75 /* Incorrect IP address */
     76 #define	DISC_ADDR_INTEGRITY_ERROR   	1
     77 /* Error converting text IP address to numeric binary form */
     78 #define	DISC_ADDR_IP_CONV_ERROR		2
     79 
     80 /* Currently not defined in  IMA_TARGET_DISCOVERY_METHOD enum */
     81 #define	IMA_TARGET_DISCOVERY_METHOD_UNKNOWN  0
     82 
     83 static IMA_OID		lhbaObjectId;
     84 static IMA_UINT32	pluginOwnerId;
     85 static sysevent_handle_t *shp;
     86 
     87 
     88 
     89 /*
     90  * Custom struct to allow tgpt to be specified.
     91  */
     92 typedef struct _SUN_IMA_DISC_ADDRESS_KEY
     93 {
     94 	IMA_NODE_NAME name;
     95 	IMA_ADDRESS_KEY	address;
     96 	IMA_UINT16 tpgt;
     97 } SUN_IMA_DISC_ADDRESS_KEY;
     98 
     99 /*
    100  * Custom struct to allow tgpt to be specified.
    101  */
    102 typedef struct _SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES
    103 {
    104 	IMA_UINT keyCount;
    105 	SUN_IMA_DISC_ADDRESS_KEY keys[1];
    106 } SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES;
    107 
    108 /*
    109  * Custom struct to allow tgpt to be specified.
    110  */
    111 typedef struct _SUN_IMA_DISC_ADDR_PROP_LIST
    112 {
    113 	IMA_UINT discAddrCount;
    114 	IMA_DISCOVERY_ADDRESS_PROPERTIES props[1];
    115 } SUN_IMA_DISC_ADDR_PROP_LIST;
    116 
    117 
    118 static IMA_OBJECT_VISIBILITY_FN pObjectVisibilityCallback = NULL;
    119 static IMA_OBJECT_PROPERTY_FN pObjectPropertyCallback = NULL;
    120 
    121 static IMA_STATUS getISCSINodeParameter(int paramType, IMA_OID *oid,
    122     void *pProps, uint32_t paramIndex);
    123 static IMA_STATUS setISCSINodeParameter(int paramType, IMA_OID *oid,
    124     void *pProps, uint32_t paramIndex);
    125 static IMA_STATUS setAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount,
    126     const IMA_AUTHMETHOD *pMethodList);
    127 static IMA_STATUS getAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount,
    128     IMA_AUTHMETHOD *pMethodList);
    129 
    130 static int prepare_discovery_entry(IMA_TARGET_ADDRESS discoveryAddress,
    131     entry_t *entry);
    132 static IMA_STATUS configure_discovery_method(IMA_BOOL enable,
    133     iSCSIDiscoveryMethod_t method);
    134 static IMA_STATUS get_target_oid_list(uint32_t targetListType,
    135     IMA_OID_LIST **ppList);
    136 static IMA_STATUS get_target_lun_oid_list(IMA_OID * targetOid,
    137 		iscsi_lun_list_t  **ppLunList);
    138 static int get_lun_devlink(di_devlink_t link, void *osDeviceName);
    139 static IMA_STATUS getDiscoveryAddressPropertiesList(
    140 	SUN_IMA_DISC_ADDR_PROP_LIST **ppList
    141 );
    142 static IMA_STATUS sendTargets(IMA_TARGET_ADDRESS address,
    143     SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList
    144 );
    145 
    146 static IMA_STATUS getSupportedAuthMethods(IMA_OID lhbaOid,
    147     IMA_BOOL getSettableMethods, IMA_UINT *pMethodCount,
    148     IMA_AUTHMETHOD *pMethodList);
    149 static IMA_STATUS getLuProperties(IMA_OID luId, IMA_LU_PROPERTIES *pProps);
    150 static IMA_STATUS getTargetProperties(IMA_OID targetId,
    151     IMA_TARGET_PROPERTIES *pProps);
    152 
    153 void InitLibrary();
    154 
    155 static void libSwprintf(wchar_t *wcs, const wchar_t *lpszFormat, ...)
    156 {
    157 	va_list args;
    158 	va_start(args, lpszFormat);
    159 	(void) vswprintf(wcs, OS_DEVICE_NAME_LEN - 1, lpszFormat, args);
    160 	va_end(args);
    161 }
    162 
    163 static void
    164 sysevent_handler(sysevent_t *ev)
    165 {
    166 	IMA_OID tmpOid;
    167 	IMA_BOOL becomingVisible = IMA_FALSE;
    168 	IMA_UINT i;
    169 
    170 	const char *visibility_subclasses[] = {
    171 		ESC_ISCSI_STATIC_START,
    172 		ESC_ISCSI_STATIC_END,
    173 		ESC_ISCSI_SEND_TARGETS_START,
    174 		ESC_ISCSI_SEND_TARGETS_END,
    175 		ESC_ISCSI_SLP_START,
    176 		ESC_ISCSI_SLP_END,
    177 		ESC_ISCSI_ISNS_START,
    178 		ESC_ISCSI_ISNS_END,
    179 		NULL
    180 	};
    181 
    182 	tmpOid.ownerId = pluginOwnerId;
    183 	tmpOid.objectType = IMA_OBJECT_TYPE_TARGET;
    184 	tmpOid.objectSequenceNumber = 0;
    185 
    186 	/* Make sure our event class matches what we are looking for */
    187 	if (strncmp(EC_ISCSI, sysevent_get_class_name(ev),
    188 	    strlen(EC_ISCSI)) != 0) {
    189 		return;
    190 	}
    191 
    192 
    193 	/* Check for object property changes */
    194 	if ((strncmp(ESC_ISCSI_PROP_CHANGE,
    195 	    sysevent_get_subclass_name(ev),
    196 	    strlen(ESC_ISCSI_PROP_CHANGE)) == 0)) {
    197 		if (pObjectPropertyCallback != NULL)
    198 			pObjectPropertyCallback(tmpOid);
    199 	} else {
    200 		i = 0;
    201 		while (visibility_subclasses[i] != NULL) {
    202 			if ((strncmp(visibility_subclasses[i],
    203 			    sysevent_get_subclass_name(ev),
    204 			    strlen(visibility_subclasses[i])) == 0) &&
    205 			    pObjectVisibilityCallback != NULL) {
    206 				becomingVisible = IMA_TRUE;
    207 				pObjectVisibilityCallback(becomingVisible,
    208 				    tmpOid);
    209 			}
    210 			i++;
    211 		}
    212 	}
    213 }
    214 
    215 IMA_STATUS init_sysevents() {
    216 	const char *subclass_list[] = {
    217 		ESC_ISCSI_STATIC_START,
    218 		ESC_ISCSI_STATIC_END,
    219 		ESC_ISCSI_SEND_TARGETS_START,
    220 		ESC_ISCSI_SEND_TARGETS_END,
    221 		ESC_ISCSI_SLP_START,
    222 		ESC_ISCSI_SLP_END,
    223 		ESC_ISCSI_ISNS_START,
    224 		ESC_ISCSI_ISNS_END,
    225 		ESC_ISCSI_PROP_CHANGE,
    226 	};
    227 
    228 	/* Bind event handler and create subscriber handle */
    229 	shp = sysevent_bind_handle(sysevent_handler);
    230 	if (shp == NULL) {
    231 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    232 	}
    233 
    234 	if (sysevent_subscribe_event(shp, EC_ISCSI, subclass_list, 9) != 0) {
    235 		sysevent_unbind_handle(shp);
    236 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    237 	}
    238 	return (IMA_STATUS_SUCCESS);
    239 }
    240 
    241 IMA_STATUS Initialize(IMA_UINT32 pluginOid) {
    242 	pluginOwnerId = pluginOid;
    243 	return (init_sysevents());
    244 }
    245 
    246 void Terminate() {
    247 	if (shp != NULL) {
    248 		sysevent_unsubscribe_event(shp, EC_ISCSI);
    249 	}
    250 
    251 }
    252 
    253 void InitLibrary() {
    254 }
    255 
    256 static void GetBuildTime(IMA_DATETIME* pdatetime)
    257 {
    258 	(void) memset(pdatetime, 0, sizeof (IMA_DATETIME));
    259 }
    260 
    261 /*ARGSUSED*/
    262 IMA_API IMA_STATUS IMA_GetNodeProperties(
    263 	IMA_OID nodeOid,
    264 	IMA_NODE_PROPERTIES *pProps
    265 )
    266 {
    267 	int fd;
    268 	iscsi_param_get_t pg;
    269 
    270 	pProps->runningInInitiatorMode = IMA_TRUE;
    271 	pProps->runningInTargetMode = IMA_FALSE;
    272 	pProps->nameAndAliasSettable = IMA_FALSE;
    273 
    274 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    275 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    276 		    ISCSI_DRIVER_DEVCTL, errno);
    277 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    278 	}
    279 
    280 	(void) memset(&pg, 0, sizeof (iscsi_param_get_t));
    281 	pg.g_vers = ISCSI_INTERFACE_VERSION;
    282 	pg.g_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME;
    283 
    284 	if (ioctl(fd, ISCSI_PARAM_GET, &pg) == -1) {
    285 		pProps->nameValid = IMA_FALSE;
    286 	} else {
    287 		if (strlen((char *)pg.g_value.v_name) > 0) {
    288 			(void) mbstowcs(pProps->name,
    289 			    (char *)pg.g_value.v_name,
    290 			    IMA_NODE_NAME_LEN);
    291 			pProps->nameValid = IMA_TRUE;
    292 		} else {
    293 			pProps->nameValid = IMA_FALSE;
    294 		}
    295 	}
    296 
    297 	(void) memset(&pg, 0, sizeof (iscsi_param_get_t));
    298 	pg.g_vers = ISCSI_INTERFACE_VERSION;
    299 	pg.g_param = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS;
    300 	(void) memset(pProps->alias, 0,
    301 	    sizeof (IMA_WCHAR) * IMA_NODE_ALIAS_LEN);
    302 	if (ioctl(fd, ISCSI_PARAM_GET, &pg) == -1) {
    303 		pProps->aliasValid = IMA_FALSE;
    304 	} else {
    305 		if (strlen((char *)pg.g_value.v_name) > 0) {
    306 			(void) mbstowcs(pProps->alias,
    307 			    (char *)pg.g_value.v_name,
    308 			    IMA_NODE_ALIAS_LEN);
    309 			pProps->aliasValid = IMA_TRUE;
    310 		}
    311 	}
    312 
    313 	(void) close(fd);
    314 	return (IMA_STATUS_SUCCESS);
    315 }
    316 
    317 IMA_API IMA_STATUS IMA_SetNodeName(
    318 	IMA_OID nodeOid,
    319 	const IMA_NODE_NAME newName
    320 )
    321 {
    322 	int fd;
    323 	iscsi_param_set_t ps;
    324 
    325 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    326 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    327 		    ISCSI_DRIVER_DEVCTL, errno);
    328 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    329 	}
    330 
    331 	(void) memset(&ps, 0, sizeof (iscsi_param_set_t));
    332 	ps.s_oid = nodeOid.objectSequenceNumber;
    333 	ps.s_vers = ISCSI_INTERFACE_VERSION;
    334 	ps.s_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME;
    335 	(void) wcstombs((char *)ps.s_value.v_name, newName, ISCSI_MAX_NAME_LEN);
    336 	if (ioctl(fd, ISCSI_INIT_NODE_NAME_SET, &ps)) {
    337 		syslog(LOG_USER|LOG_DEBUG,
    338 		    "ISCSI_PARAM_SET ioctl failed, errno: %d", errno);
    339 		(void) close(fd);
    340 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    341 	}
    342 
    343 	(void) close(fd);
    344 	return (IMA_STATUS_SUCCESS);
    345 }
    346 
    347 IMA_API IMA_STATUS IMA_SetNodeAlias(
    348 	IMA_OID nodeOid,
    349 	const IMA_NODE_ALIAS newAlias
    350 )
    351 {
    352 	int fd;
    353 	iscsi_param_set_t ps;
    354 
    355 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    356 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    357 		    ISCSI_DRIVER_DEVCTL, errno);
    358 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    359 	}
    360 
    361 	(void) memset(&ps, 0, sizeof (iscsi_param_set_t));
    362 	ps.s_oid = nodeOid.objectSequenceNumber;
    363 	ps.s_vers = ISCSI_INTERFACE_VERSION;
    364 	ps.s_param = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS;
    365 
    366 	/* newAlias = NULL specifies that the alias should be deleted. */
    367 	if (newAlias != NULL)
    368 		(void) wcstombs((char *)ps.s_value.v_name, newAlias,
    369 		    ISCSI_MAX_NAME_LEN);
    370 	else
    371 		(void) wcstombs((char *)ps.s_value.v_name,
    372 		    L"", ISCSI_MAX_NAME_LEN);
    373 
    374 	if (ioctl(fd, ISCSI_PARAM_SET, &ps)) {
    375 		syslog(LOG_USER|LOG_DEBUG,
    376 		    "ISCSI_PARAM_SET ioctl failed, errno: %d", errno);
    377 		(void) close(fd);
    378 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    379 	}
    380 
    381 	(void) close(fd);
    382 	return (IMA_STATUS_SUCCESS);
    383 }
    384 
    385 
    386 IMA_API IMA_STATUS IMA_GetLhbaOidList(
    387 	IMA_OID_LIST **ppList
    388 )
    389 {
    390 	/* Always return the same object ID for the lhba */
    391 	lhbaObjectId.objectType = IMA_OBJECT_TYPE_LHBA;
    392 	lhbaObjectId.ownerId = pluginOwnerId;
    393 	lhbaObjectId.objectSequenceNumber = ISCSI_INITIATOR_OID;
    394 
    395 	*ppList = (IMA_OID_LIST*)calloc(1, sizeof (IMA_OID_LIST));
    396 	if (*ppList == NULL) {
    397 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    398 	}
    399 
    400 	(*ppList)->oidCount = 1;
    401 	(void) memcpy(&(*ppList)->oids[0],
    402 	    &lhbaObjectId, sizeof (lhbaObjectId));
    403 	return (IMA_STATUS_SUCCESS);
    404 }
    405 
    406 
    407 /*
    408  * Get the discovery properties of the LHBA
    409  */
    410 /*ARGSUSED*/
    411 IMA_API IMA_STATUS IMA_GetDiscoveryProperties(
    412 	IMA_OID oid,
    413 	IMA_DISCOVERY_PROPERTIES *pProps
    414 )
    415 {
    416 	int fd;
    417 	iSCSIDiscoveryProperties_t discoveryProps;
    418 
    419 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    420 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    421 		    ISCSI_DRIVER_DEVCTL, errno);
    422 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    423 	}
    424 
    425 	(void) memset(&discoveryProps, 0, sizeof (discoveryProps));
    426 	discoveryProps.vers = ISCSI_INTERFACE_VERSION;
    427 
    428 	if (ioctl(fd, ISCSI_DISCOVERY_PROPS, &discoveryProps) != 0) {
    429 		syslog(LOG_USER|LOG_DEBUG,
    430 		    "ISCSI_DISCOVERY_PROPS ioctl failed, errno: %d", errno);
    431 		(void) close(fd);
    432 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    433 	}
    434 
    435 	pProps->iSnsDiscoverySettable = discoveryProps.iSNSDiscoverySettable;
    436 	pProps->iSnsDiscoveryEnabled = discoveryProps.iSNSDiscoveryEnabled;
    437 	/*
    438 	 * Set the iSNS discovery method - The IMA specification indicates
    439 	 * this field is valid only if iSNS discovery is enabled.
    440 	 */
    441 	if (pProps->iSnsDiscoveryEnabled == IMA_TRUE) {
    442 		switch (discoveryProps.iSNSDiscoveryMethod) {
    443 			case iSNSDiscoveryMethodStatic:
    444 				pProps->iSnsDiscoveryMethod =
    445 				    IMA_ISNS_DISCOVERY_METHOD_STATIC;
    446 				break;
    447 			case iSNSDiscoveryMethodDHCP:
    448 				pProps->iSnsDiscoveryMethod =
    449 				    IMA_ISNS_DISCOVERY_METHOD_DHCP;
    450 				break;
    451 			case iSNSDiscoveryMethodSLP:
    452 				pProps->iSnsDiscoveryMethod =
    453 				    IMA_ISNS_DISCOVERY_METHOD_SLP;
    454 				break;
    455 			default:
    456 				(void) close(fd);
    457 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    458 		}
    459 	}
    460 	(void) memcpy(pProps->iSnsHost.id.hostname,
    461 	    discoveryProps.iSNSDomainName,
    462 	    sizeof (pProps->iSnsHost.id.hostname));
    463 	pProps->slpDiscoverySettable = discoveryProps.SLPDiscoverySettable;
    464 	pProps->slpDiscoveryEnabled = discoveryProps.SLPDiscoveryEnabled;
    465 	pProps->staticDiscoverySettable =
    466 	    discoveryProps.StaticDiscoverySettable;
    467 	pProps->staticDiscoveryEnabled = discoveryProps.StaticDiscoveryEnabled;
    468 	pProps->sendTargetsDiscoverySettable =
    469 	    discoveryProps.SendTargetsDiscoverySettable;
    470 	pProps->sendTargetsDiscoveryEnabled =
    471 	    discoveryProps.SendTargetsDiscoveryEnabled;
    472 
    473 	(void) close(fd);
    474 	return (IMA_STATUS_SUCCESS);
    475 }
    476 
    477 IMA_API IMA_STATUS IMA_FreeMemory(
    478 	void *pMemory
    479 )
    480 {
    481 	if (pMemory != NULL)
    482 		free(pMemory);
    483 	return (IMA_STATUS_SUCCESS);
    484 }
    485 
    486 IMA_API IMA_STATUS IMA_GetNonSharedNodeOidList(
    487 		IMA_OID_LIST **ppList
    488 )
    489 {
    490 	if (ppList == NULL)
    491 		return (IMA_ERROR_INVALID_PARAMETER);
    492 
    493 	*ppList = (IMA_OID_LIST*) calloc(1, sizeof (IMA_OID_LIST));
    494 	if (*ppList == NULL) {
    495 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    496 	}
    497 	(*ppList)->oidCount = 0;
    498 
    499 	return (IMA_STATUS_SUCCESS);
    500 }
    501 
    502 IMA_API IMA_STATUS IMA_GetFirstBurstLengthProperties(
    503 		IMA_OID Oid,
    504 		IMA_MIN_MAX_VALUE *pProps
    505 )
    506 {
    507 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    508 	    ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH));
    509 }
    510 
    511 IMA_API IMA_STATUS IMA_GetMaxBurstLengthProperties(
    512 		IMA_OID Oid,
    513 		IMA_MIN_MAX_VALUE *pProps
    514 )
    515 {
    516 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    517 	    ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH));
    518 }
    519 
    520 IMA_API IMA_STATUS IMA_GetMaxRecvDataSegmentLengthProperties(
    521 		IMA_OID Oid,
    522 		IMA_MIN_MAX_VALUE *pProps
    523 )
    524 {
    525 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    526 	    ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH));
    527 }
    528 
    529 /*ARGSUSED*/
    530 IMA_API IMA_STATUS IMA_PluginIOCtl(
    531 		IMA_OID pluginOid,
    532 		IMA_UINT command,
    533 		const void *pInputBuffer,
    534 		IMA_UINT inputBufferLength,
    535 		void *pOutputBuffer,
    536 		IMA_UINT *pOutputBufferLength
    537 )
    538 {
    539 	return (IMA_ERROR_NOT_SUPPORTED);
    540 }
    541 
    542 IMA_API	IMA_STATUS IMA_SetFirstBurstLength(
    543 		IMA_OID lhbaId,
    544 		IMA_UINT firstBurstLength
    545 )
    546 {
    547 	IMA_MIN_MAX_VALUE mv;
    548 
    549 	mv.currentValue = firstBurstLength;
    550 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    551 	    ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH));
    552 }
    553 
    554 IMA_API	IMA_STATUS IMA_SetMaxBurstLength(
    555 		IMA_OID lhbaId,
    556 		IMA_UINT maxBurstLength
    557 )
    558 {
    559 	IMA_MIN_MAX_VALUE mv;
    560 
    561 	mv.currentValue = maxBurstLength;
    562 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    563 	    ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH));
    564 }
    565 
    566 IMA_API	IMA_STATUS IMA_SetMaxRecvDataSegmentLength(
    567 		IMA_OID lhbaId,
    568 		IMA_UINT maxRecvDataSegmentLength
    569 )
    570 {
    571 	IMA_MIN_MAX_VALUE mv;
    572 
    573 	mv.currentValue = maxRecvDataSegmentLength;
    574 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    575 	    ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH));
    576 }
    577 
    578 IMA_API	IMA_STATUS IMA_GetMaxConnectionsProperties(
    579 		IMA_OID Oid,
    580 		IMA_MIN_MAX_VALUE *pProps
    581 )
    582 {
    583 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    584 	    ISCSI_LOGIN_PARAM_MAX_CONNECTIONS));
    585 }
    586 
    587 IMA_API	IMA_STATUS IMA_SetMaxConnections(
    588 		IMA_OID lhbaId,
    589 		IMA_UINT maxConnections
    590 )
    591 {
    592 	IMA_MIN_MAX_VALUE mv;
    593 
    594 	mv.currentValue = maxConnections;
    595 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    596 	    ISCSI_LOGIN_PARAM_MAX_CONNECTIONS));
    597 }
    598 
    599 IMA_API	IMA_STATUS IMA_GetDefaultTime2RetainProperties(
    600 		IMA_OID lhbaId,
    601 		IMA_MIN_MAX_VALUE *pProps
    602 )
    603 {
    604 	return (getISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, pProps,
    605 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN));
    606 }
    607 
    608 IMA_API	IMA_STATUS IMA_SetDefaultTime2Retain(
    609 		IMA_OID lhbaId,
    610 		IMA_UINT defaultTime2Retain
    611 )
    612 {
    613 	IMA_MIN_MAX_VALUE mv;
    614 
    615 	mv.currentValue = defaultTime2Retain;
    616 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    617 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN));
    618 }
    619 
    620 IMA_API	IMA_STATUS IMA_GetDefaultTime2WaitProperties(
    621 		IMA_OID lhbaId,
    622 		IMA_MIN_MAX_VALUE *pProps
    623 )
    624 {
    625 	return (getISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, pProps,
    626 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT));
    627 }
    628 
    629 IMA_API	IMA_STATUS IMA_SetDefaultTime2Wait(
    630 		IMA_OID lhbaId,
    631 		IMA_UINT defaultTime2Wait
    632 )
    633 {
    634 	IMA_MIN_MAX_VALUE mv;
    635 
    636 	mv.currentValue = defaultTime2Wait;
    637 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    638 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT));
    639 }
    640 
    641 IMA_API	IMA_STATUS IMA_GetMaxOutstandingR2TProperties(
    642 		IMA_OID Oid,
    643 		IMA_MIN_MAX_VALUE *pProps
    644 )
    645 {
    646 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    647 	    ISCSI_LOGIN_PARAM_OUTSTANDING_R2T));
    648 }
    649 
    650 IMA_API	IMA_STATUS IMA_SetMaxOutstandingR2T(
    651 		IMA_OID lhbaId,
    652 		IMA_UINT maxOutstandingR2T
    653 )
    654 {
    655 	IMA_MIN_MAX_VALUE mv;
    656 
    657 	mv.currentValue = maxOutstandingR2T;
    658 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    659 	    ISCSI_LOGIN_PARAM_OUTSTANDING_R2T));
    660 }
    661 
    662 
    663 IMA_API	IMA_STATUS IMA_GetErrorRecoveryLevelProperties(
    664 		IMA_OID Oid,
    665 		IMA_MIN_MAX_VALUE *pProps
    666 )
    667 {
    668 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    669 	    ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL));
    670 }
    671 
    672 IMA_API	IMA_STATUS IMA_SetErrorRecoveryLevel(
    673 		IMA_OID Oid,
    674 		IMA_UINT errorRecoveryLevel
    675 )
    676 {
    677 	IMA_MIN_MAX_VALUE mv;
    678 
    679 	mv.currentValue = errorRecoveryLevel;
    680 	return (setISCSINodeParameter(MIN_MAX_PARAM, &Oid, &mv,
    681 	    ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL));
    682 }
    683 
    684 IMA_API	IMA_STATUS IMA_GetInitialR2TProperties(
    685 		IMA_OID Oid,
    686 		IMA_BOOL_VALUE *pProps
    687 )
    688 {
    689 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    690 	    ISCSI_LOGIN_PARAM_INITIAL_R2T));
    691 }
    692 
    693 IMA_API	IMA_STATUS IMA_SetInitialR2T(
    694 		IMA_OID Oid,
    695 		IMA_BOOL initialR2T
    696 )
    697 {
    698 	IMA_BOOL_VALUE bv;
    699 
    700 	bv.currentValue = initialR2T;
    701 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    702 	    ISCSI_LOGIN_PARAM_INITIAL_R2T));
    703 }
    704 
    705 
    706 IMA_API	IMA_STATUS IMA_GetImmediateDataProperties(
    707 		IMA_OID Oid,
    708 		IMA_BOOL_VALUE *pProps
    709 )
    710 {
    711 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    712 	    ISCSI_LOGIN_PARAM_IMMEDIATE_DATA));
    713 }
    714 
    715 IMA_API	IMA_STATUS IMA_SetImmediateData(
    716 		IMA_OID Oid,
    717 		IMA_BOOL immediateData
    718 )
    719 {
    720 	IMA_BOOL_VALUE bv;
    721 
    722 	bv.currentValue = immediateData;
    723 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    724 	    ISCSI_LOGIN_PARAM_IMMEDIATE_DATA));
    725 }
    726 
    727 IMA_API	IMA_STATUS IMA_GetDataPduInOrderProperties(
    728 		IMA_OID Oid,
    729 		IMA_BOOL_VALUE *pProps
    730 )
    731 {
    732 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    733 	    ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER));
    734 }
    735 
    736 IMA_API	IMA_STATUS IMA_SetDataPduInOrder(
    737 		IMA_OID Oid,
    738 		IMA_BOOL dataPduInOrder
    739 )
    740 {
    741 	IMA_BOOL_VALUE bv;
    742 
    743 	bv.currentValue = dataPduInOrder;
    744 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    745 	    ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER));
    746 }
    747 
    748 IMA_API	IMA_STATUS IMA_GetDataSequenceInOrderProperties(
    749 		IMA_OID Oid,
    750 		IMA_BOOL_VALUE *pProps
    751 )
    752 {
    753 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    754 	    ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER));
    755 }
    756 
    757 IMA_API	IMA_STATUS IMA_SetDataSequenceInOrder(
    758 		IMA_OID Oid,
    759 		IMA_BOOL dataSequenceInOrder
    760 )
    761 {
    762 	IMA_BOOL_VALUE bv;
    763 
    764 	bv.currentValue = dataSequenceInOrder;
    765 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    766 	    ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER));
    767 }
    768 
    769 
    770 /*ARGSUSED*/
    771 IMA_API	IMA_STATUS IMA_SetStatisticsCollection(
    772 		IMA_OID Oid,
    773 		IMA_BOOL enableStatisticsCollection
    774 )
    775 {
    776 	return (IMA_ERROR_NOT_SUPPORTED);
    777 }
    778 
    779 
    780 /*ARGSUSED*/
    781 IMA_API	IMA_STATUS IMA_GetDiscoveryAddressOidList(
    782 		IMA_OID Oid,
    783 		IMA_OID_LIST **ppList
    784 )
    785 {
    786 	int fd, i, addr_list_size;
    787 	iscsi_addr_list_t *idlp, al_info;
    788 
    789 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    790 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    791 		    ISCSI_DRIVER_DEVCTL, errno);
    792 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    793 	}
    794 
    795 	(void) memset(&al_info, 0, sizeof (al_info));
    796 	al_info.al_vers = ISCSI_INTERFACE_VERSION;
    797 	al_info.al_in_cnt = 0;
    798 
    799 	/*
    800 	 * Issue ioctl to obtain the number of targets.
    801 	 */
    802 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
    803 		syslog(LOG_USER|LOG_DEBUG,
    804 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d",
    805 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    806 		(void) close(fd);
    807 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    808 	}
    809 
    810 	addr_list_size = sizeof (iscsi_addr_list_t);
    811 	if (al_info.al_out_cnt > 1) {
    812 		addr_list_size += (sizeof (iscsi_addr_list_t) *
    813 		    al_info.al_out_cnt - 1);
    814 	}
    815 
    816 	idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size);
    817 	if (idlp == NULL) {
    818 		(void) close(fd);
    819 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    820 	}
    821 
    822 	idlp->al_vers = ISCSI_INTERFACE_VERSION;
    823 	idlp->al_in_cnt = al_info.al_out_cnt;
    824 	/* Issue the same ioctl again to obtain the OIDs. */
    825 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) {
    826 		syslog(LOG_USER|LOG_DEBUG,
    827 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
    828 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    829 		free(idlp);
    830 		(void) close(fd);
    831 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    832 	}
    833 
    834 	*ppList = (IMA_OID_LIST *)calloc(1, sizeof (IMA_OID_LIST) +
    835 	    idlp->al_out_cnt * sizeof (IMA_OID));
    836 	if (*ppList == NULL) {
    837 		free(idlp);
    838 		(void) close(fd);
    839 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    840 	}
    841 	(*ppList)->oidCount = idlp->al_out_cnt;
    842 
    843 	for (i = 0; i < idlp->al_out_cnt; i++) {
    844 		(*ppList)->oids[i].objectType =
    845 		    IMA_OBJECT_TYPE_DISCOVERY_ADDRESS;
    846 		(*ppList)->oids[i].ownerId = pluginOwnerId;
    847 		(*ppList)->oids[i].objectSequenceNumber =
    848 		    idlp->al_addrs[i].a_oid;
    849 	}
    850 
    851 	free(idlp);
    852 	(void) close(fd);
    853 
    854 	return (IMA_STATUS_SUCCESS);
    855 }
    856 
    857 
    858 /* ARGSUSED */
    859 IMA_API	IMA_STATUS IMA_GetStaticDiscoveryTargetOidList(
    860 		IMA_OID Oid,
    861 		IMA_OID_LIST **ppList
    862 )
    863 {
    864 	if (Oid.objectType == IMA_OBJECT_TYPE_PNP) {
    865 		return (IMA_ERROR_OBJECT_NOT_FOUND);
    866 	}
    867 
    868 	return (get_target_oid_list(ISCSI_STATIC_TGT_OID_LIST, ppList));
    869 }
    870 
    871 /* ARGSUSED */
    872 IMA_API	IMA_STATUS IMA_GetTargetOidList(
    873 		IMA_OID Oid,
    874 		IMA_OID_LIST **ppList
    875 )
    876 {
    877 	return (get_target_oid_list(ISCSI_TGT_PARAM_OID_LIST, ppList));
    878 }
    879 
    880 /*ARGSUSED*/
    881 IMA_API	IMA_STATUS IMA_SetIsnsDiscovery(
    882 		IMA_OID phbaId,
    883 		IMA_BOOL enableIsnsDiscovery,
    884 		IMA_ISNS_DISCOVERY_METHOD discoveryMethod,
    885 		const IMA_HOST_ID *iSnsHost
    886 )
    887 {
    888 	/* XXX need to set discovery Method and domaineName */
    889 	return (configure_discovery_method(enableIsnsDiscovery,
    890 	    iSCSIDiscoveryMethodISNS));
    891 }
    892 
    893 
    894 /* ARGSUSED */
    895 IMA_API	IMA_STATUS IMA_SetSlpDiscovery(
    896 		IMA_OID phbaId,
    897 		IMA_BOOL enableSlpDiscovery
    898 )
    899 {
    900 	return (configure_discovery_method(enableSlpDiscovery,
    901 	    iSCSIDiscoveryMethodSLP));
    902 }
    903 
    904 
    905 /* ARGSUSED */
    906 IMA_API	IMA_STATUS IMA_SetStaticDiscovery(
    907 		IMA_OID phbaId,
    908 		IMA_BOOL enableStaticDiscovery
    909 )
    910 {
    911 	return (configure_discovery_method(enableStaticDiscovery,
    912 	    iSCSIDiscoveryMethodStatic));
    913 }
    914 
    915 /* ARGSUSED */
    916 IMA_API	IMA_STATUS IMA_SetSendTargetsDiscovery(
    917 		IMA_OID phbaId,
    918 		IMA_BOOL enableSendTargetsDiscovery
    919 )
    920 {
    921 	return (configure_discovery_method(enableSendTargetsDiscovery,
    922 	    iSCSIDiscoveryMethodSendTargets));
    923 }
    924 
    925 /*ARGSUSED*/
    926 IMA_API IMA_STATUS IMA_RemoveDiscoveryAddress(
    927 		IMA_OID	discoveryAddressOid
    928 )
    929 {
    930 	int status, fd, i, addr_list_size;
    931 	iscsi_addr_list_t *idlp, al_info;
    932 	iscsi_addr_t *matched_addr = NULL;
    933 	entry_t	entry;
    934 
    935 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    936 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    937 		    ISCSI_DRIVER_DEVCTL, errno);
    938 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    939 	}
    940 
    941 	(void) memset(&al_info, 0, sizeof (al_info));
    942 	al_info.al_vers = ISCSI_INTERFACE_VERSION;
    943 	al_info.al_in_cnt = 0;
    944 
    945 	/*
    946 	 * Issue ioctl to obtain the number of discovery address.
    947 	 */
    948 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
    949 		syslog(LOG_USER|LOG_DEBUG,
    950 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d",
    951 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    952 		(void) close(fd);
    953 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    954 	}
    955 
    956 	if (al_info.al_out_cnt == 0) {
    957 		return (IMA_ERROR_OBJECT_NOT_FOUND);
    958 	}
    959 
    960 	addr_list_size = sizeof (iscsi_addr_list_t);
    961 	if (al_info.al_out_cnt > 1) {
    962 		addr_list_size += (sizeof (iscsi_addr_list_t) *
    963 		    al_info.al_out_cnt - 1);
    964 	}
    965 
    966 	idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size);
    967 	if (idlp == NULL) {
    968 		(void) close(fd);
    969 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    970 	}
    971 
    972 	idlp->al_vers = ISCSI_INTERFACE_VERSION;
    973 	idlp->al_in_cnt = al_info.al_out_cnt;
    974 
    975 	/* Issue the same ioctl again to obtain the OIDs. */
    976 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) {
    977 		syslog(LOG_USER|LOG_DEBUG,
    978 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
    979 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    980 		free(idlp);
    981 		(void) close(fd);
    982 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    983 	}
    984 
    985 	for (i = 0; i < idlp->al_out_cnt; i++) {
    986 		if (discoveryAddressOid.objectSequenceNumber !=
    987 		    idlp->al_addrs[i].a_oid)
    988 			continue;
    989 		matched_addr = &(idlp->al_addrs[i]);
    990 	}
    991 
    992 	if (matched_addr == NULL) {
    993 		return (IMA_ERROR_OBJECT_NOT_FOUND);
    994 	}
    995 
    996 
    997 	(void) memset(&entry, 0, sizeof (entry_t));
    998 	entry.e_vers = ISCSI_INTERFACE_VERSION;
    999 	entry.e_oid  = discoveryAddressOid.objectSequenceNumber;
   1000 	if (matched_addr->a_addr.i_insize == sizeof (struct in_addr)) {
   1001 		bcopy(&matched_addr->a_addr.i_addr.in4,
   1002 		    &entry.e_u.u_in4, sizeof (entry.e_u.u_in4));
   1003 		entry.e_insize = sizeof (struct in_addr);
   1004 	} else if (matched_addr->a_addr.i_insize == sizeof (struct in6_addr)) {
   1005 		bcopy(&matched_addr->a_addr.i_addr.in6,
   1006 		    &entry.e_u.u_in6, sizeof (entry.e_u.u_in6));
   1007 		entry.e_insize = sizeof (struct in6_addr);
   1008 	} else {
   1009 		/* Should not happen */
   1010 		syslog(LOG_USER|LOG_DEBUG,
   1011 		    "ISCSI_STATIC_GET returned bad address");
   1012 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1013 	}
   1014 
   1015 	entry.e_port = matched_addr->a_port;
   1016 	entry.e_tpgt = 0;
   1017 	entry.e_oid = discoveryAddressOid.objectSequenceNumber;
   1018 
   1019 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_CLEAR, &entry)) {
   1020 		status = errno;
   1021 		(void) close(fd);
   1022 		syslog(LOG_USER|LOG_DEBUG,
   1023 		    "ISCSI_DISCOVERY_ADDR_CLEAR ioctl failed, errno: %d",
   1024 		    errno);
   1025 		if (status == EBUSY) {
   1026 			return (IMA_ERROR_LU_IN_USE);
   1027 		} else {
   1028 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1029 		}
   1030 	}
   1031 
   1032 	free(idlp);
   1033 	(void) close(fd);
   1034 	return (IMA_STATUS_SUCCESS);
   1035 }
   1036 
   1037 
   1038 /*ARGSUSED*/
   1039 IMA_API IMA_STATUS IMA_AddDiscoveryAddress(
   1040 		IMA_OID	oid,
   1041 		const IMA_TARGET_ADDRESS discoveryAddress,
   1042 		IMA_OID	*pDiscoveryAddressOid
   1043 )
   1044 {
   1045 	entry_t	    entry;
   1046 	int	    fd;
   1047 
   1048 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1049 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1050 		    ISCSI_DRIVER_DEVCTL, errno);
   1051 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1052 	}
   1053 
   1054 	if (prepare_discovery_entry(discoveryAddress, &entry) !=
   1055 	    DISC_ADDR_OK) {
   1056 		(void) close(fd);
   1057 		return (IMA_ERROR_INVALID_PARAMETER);
   1058 	}
   1059 
   1060 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_SET, &entry)) {
   1061 		syslog(LOG_USER|LOG_DEBUG,
   1062 		    "ISCSI_DISCOVERY_ADDR_SET ioctl failed, errno: %d",
   1063 		    errno);
   1064 		(void) close(fd);
   1065 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1066 	}
   1067 
   1068 	pDiscoveryAddressOid->ownerId = pluginOwnerId;
   1069 	pDiscoveryAddressOid->objectType = IMA_OBJECT_TYPE_DISCOVERY_ADDRESS;
   1070 	pDiscoveryAddressOid->objectSequenceNumber = entry.e_oid;
   1071 
   1072 	(void) close(fd);
   1073 	return (IMA_STATUS_SUCCESS);
   1074 }
   1075 
   1076 IMA_API IMA_STATUS IMA_GetStaticDiscoveryTargetProperties(
   1077 		IMA_OID	staticTargetOid,
   1078 		IMA_STATIC_DISCOVERY_TARGET_PROPERTIES *pProps
   1079 )
   1080 {
   1081 	char static_target_addr_str[SUN_IMA_IP_ADDRESS_LEN];
   1082 	char static_target_addr_port_str[SUN_IMA_IP_ADDRESS_LEN];
   1083 	int af, fd, status;
   1084 	iscsi_static_property_t prop;
   1085 	/* LINTED */
   1086 	IMA_HOST_ID *host;
   1087 
   1088 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1089 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1090 		    ISCSI_DRIVER_DEVCTL, errno);
   1091 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1092 	}
   1093 
   1094 	(void) memset(&prop, 0, sizeof (iscsi_static_property_t));
   1095 	prop.p_vers = ISCSI_INTERFACE_VERSION;
   1096 	prop.p_oid = (uint32_t)staticTargetOid.objectSequenceNumber;
   1097 	if (ioctl(fd, ISCSI_STATIC_GET, &prop) != 0) {
   1098 		status = errno;
   1099 		(void) close(fd);
   1100 		syslog(LOG_USER|LOG_DEBUG,
   1101 		    "ISCSI_STATIC_GET ioctl failed, errno: %d", status);
   1102 		if (status == ENOENT) {
   1103 			return (IMA_ERROR_OBJECT_NOT_FOUND);
   1104 
   1105 		} else {
   1106 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1107 		}
   1108 	}
   1109 	(void) close(fd);
   1110 
   1111 	(void) mbstowcs(pProps->staticTarget.targetName, (char *)prop.p_name,
   1112 	    sizeof (pProps->staticTarget.targetName)/sizeof (IMA_WCHAR));
   1113 
   1114 	if (prop.p_addr_list.al_addrs[0].a_addr.i_insize ==
   1115 	    sizeof (struct in_addr)) {
   1116 		/* IPv4 */
   1117 		af = AF_INET;
   1118 	} else if (prop.p_addr_list.al_addrs[0].a_addr.i_insize ==
   1119 	    sizeof (struct in6_addr)) {
   1120 		/* IPv6 */
   1121 		af = AF_INET6;
   1122 	} else {
   1123 		/* Should not happen */
   1124 		syslog(LOG_USER|LOG_DEBUG,
   1125 		    "ISCSI_STATIC_GET returned bad address");
   1126 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1127 	}
   1128 
   1129 	if (inet_ntop(af, &prop.p_addr_list.al_addrs[0].a_addr.i_addr,
   1130 	    static_target_addr_str, sizeof (static_target_addr_str)) == NULL) {
   1131 		/* Should not happen */
   1132 		syslog(LOG_USER|LOG_DEBUG,
   1133 		    "ISCSI_STATIC_GET returned address that cannot "
   1134 		    "be inet_ntop");
   1135 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1136 	} else {
   1137 		if (af == AF_INET) {
   1138 			(void) snprintf(static_target_addr_port_str,
   1139 			    SUN_IMA_IP_ADDRESS_LEN,
   1140 			    "%s:%ld",
   1141 			    static_target_addr_str,
   1142 			    prop.p_addr_list.al_addrs[0].a_port);
   1143 		} else {
   1144 			(void) snprintf(static_target_addr_port_str,
   1145 			    SUN_IMA_IP_ADDRESS_LEN,
   1146 			    "[%s]:%ld",
   1147 			    static_target_addr_str,
   1148 			    prop.p_addr_list.al_addrs[0].a_port);
   1149 		}
   1150 		host = &pProps->staticTarget.targetAddress.hostnameIpAddress;
   1151 		(void) mbstowcs(pProps->staticTarget.
   1152 		    targetAddress.hostnameIpAddress.
   1153 		    id.hostname, static_target_addr_port_str,
   1154 		    sizeof (host->id.hostname) / sizeof (IMA_WCHAR));
   1155 	}
   1156 
   1157 	return (IMA_STATUS_SUCCESS);
   1158 }
   1159 
   1160 /*ARGSUSED*/
   1161 IMA_API IMA_STATUS IMA_GetDiscoveryAddressProperties(
   1162 		IMA_OID	discoveryAddressOid,
   1163 		IMA_DISCOVERY_ADDRESS_PROPERTIES *pProps
   1164 )
   1165 {
   1166 	int fd;
   1167 	int i;
   1168 	int addr_list_size;
   1169 	iscsi_addr_list_t *idlp, al_info;
   1170 	iscsi_addr_t *matched_addr = NULL;
   1171 	/* LINTED */
   1172 	IMA_TARGET_ADDRESS *addr;
   1173 
   1174 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1175 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1176 		    ISCSI_DRIVER_DEVCTL, errno);
   1177 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1178 	}
   1179 
   1180 	(void) memset(&al_info, 0, sizeof (al_info));
   1181 	al_info.al_vers = ISCSI_INTERFACE_VERSION;
   1182 	al_info.al_in_cnt = 0;
   1183 
   1184 	/*
   1185 	 * Issue ioctl to obtain the number of discovery addresses.
   1186 	 */
   1187 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
   1188 		(void) close(fd);
   1189 		syslog(LOG_USER|LOG_DEBUG,
   1190 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d",
   1191 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
   1192 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1193 	}
   1194 
   1195 	if (al_info.al_out_cnt == 0) {
   1196 		return (IMA_ERROR_OBJECT_NOT_FOUND);
   1197 	}
   1198 
   1199 	addr_list_size = sizeof (iscsi_addr_list_t);
   1200 	if (al_info.al_out_cnt > 1) {
   1201 		addr_list_size += (sizeof (iscsi_addr_list_t) *
   1202 		    al_info.al_out_cnt - 1);
   1203 	}
   1204 
   1205 	idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size);
   1206 	if (idlp == NULL) {
   1207 		(void) close(fd);
   1208 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   1209 	}
   1210 
   1211 	idlp->al_vers = ISCSI_INTERFACE_VERSION;
   1212 	idlp->al_in_cnt = al_info.al_out_cnt;
   1213 
   1214 	/* Issue the same ioctl again to obtain the OIDs. */
   1215 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) {
   1216 		free(idlp);
   1217 		(void) close(fd);
   1218 		syslog(LOG_USER|LOG_DEBUG,
   1219 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
   1220 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
   1221 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1222 	}
   1223 
   1224 	for (i = 0; i < idlp->al_out_cnt; i++) {
   1225 		if (discoveryAddressOid.objectSequenceNumber !=
   1226 		    idlp->al_addrs[i].a_oid)
   1227 			continue;
   1228 		matched_addr = &(idlp->al_addrs[i]);
   1229 	}
   1230 
   1231 	if (matched_addr == NULL) {
   1232 		return (IMA_ERROR_OBJECT_NOT_FOUND);
   1233 	}
   1234 
   1235 	if (matched_addr->a_addr.i_insize == sizeof (struct in_addr)) {
   1236 		pProps->discoveryAddress.hostnameIpAddress.id.
   1237 		    ipAddress.ipv4Address = IMA_TRUE;
   1238 	} else if (matched_addr->a_addr.i_insize == sizeof (struct in6_addr)) {
   1239 		pProps->discoveryAddress.hostnameIpAddress.id.
   1240 		    ipAddress.ipv4Address = IMA_FALSE;
   1241 	} else {
   1242 		/* Should not happen */
   1243 		syslog(LOG_USER|LOG_DEBUG,
   1244 		    "ISCSI_STATIC_GET returned bad address");
   1245 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1246 	}
   1247 
   1248 	addr = &pProps->discoveryAddress;
   1249 	bcopy(&(matched_addr->a_addr.i_addr), pProps->discoveryAddress.
   1250 	    hostnameIpAddress.id.ipAddress.ipAddress,
   1251 	    sizeof (addr->hostnameIpAddress.id.ipAddress.ipAddress));
   1252 
   1253 	pProps->discoveryAddress.portNumber = matched_addr->a_port;
   1254 
   1255 	pProps->associatedLhbaOid.objectType = IMA_OBJECT_TYPE_LHBA;
   1256 	pProps->associatedLhbaOid.ownerId = pluginOwnerId;
   1257 	pProps->associatedLhbaOid.objectSequenceNumber = ISCSI_INITIATOR_OID;
   1258 
   1259 	free(idlp);
   1260 	(void) close(fd);
   1261 
   1262 	return (IMA_STATUS_SUCCESS);
   1263 }
   1264 
   1265 IMA_API IMA_STATUS IMA_RemoveStaticDiscoveryTarget(
   1266 		IMA_OID staticTargetOid
   1267 )
   1268 {
   1269 	entry_t	entry;
   1270 	int	status, fd;
   1271 
   1272 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1273 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1274 		    ISCSI_DRIVER_DEVCTL, errno);
   1275 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1276 	}
   1277 
   1278 	(void) memset(&entry, 0, sizeof (entry_t));
   1279 	entry.e_vers = ISCSI_INTERFACE_VERSION;
   1280 	entry.e_oid = (uint32_t)staticTargetOid.objectSequenceNumber;
   1281 
   1282 	if (ioctl(fd, ISCSI_STATIC_CLEAR, &entry)) {
   1283 		status = errno;
   1284 		(void) close(fd);
   1285 		syslog(LOG_USER|LOG_DEBUG,
   1286 		    "ISCSI_STATIC_CLEAR ioctl failed, errno: %d", errno);
   1287 		if (status == EBUSY) {
   1288 			return (IMA_ERROR_LU_IN_USE);
   1289 		} else {
   1290 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1291 		}
   1292 	}
   1293 
   1294 	(void) close(fd);
   1295 	return (IMA_STATUS_SUCCESS);
   1296 }
   1297 
   1298 /*ARGSUSED*/
   1299 IMA_API IMA_STATUS IMA_AddStaticDiscoveryTarget(
   1300 		IMA_OID lhbaOid,
   1301 		const IMA_STATIC_DISCOVERY_TARGET staticConfig,
   1302 		IMA_OID *pTargetOid
   1303 )
   1304 {
   1305 	char			tmp_target_str[SUN_IMA_IP_ADDRESS_LEN];
   1306 	char			target_addr_str[SUN_IMA_IP_ADDRESS_LEN];
   1307 	char			target_port_str[SUN_IMA_IP_PORT_LEN];
   1308 	iscsi_target_entry_t	target;
   1309 	int			fd;
   1310 	int			target_in_addr_size;
   1311 	int			target_port;
   1312 	union {
   1313 		struct in_addr	u_in4;
   1314 		struct in6_addr	u_in6;
   1315 	}			target_in;
   1316 
   1317 	/*
   1318 	 * staticConfig.address may come in with port number at its trailer.
   1319 	 * Parse it to separate the IP address and port number.
   1320 	 * Also translate the hostname to IP address if needed.
   1321 	 */
   1322 	(void) wcstombs(tmp_target_str,
   1323 	    staticConfig.targetAddress.hostnameIpAddress.
   1324 	    id.hostname, sizeof (tmp_target_str));
   1325 
   1326 	if (tmp_target_str[0] == '[') {
   1327 		/* IPv6 address */
   1328 		char *closeBracketPos;
   1329 		closeBracketPos = strchr(tmp_target_str, ']');
   1330 		if (!closeBracketPos) {
   1331 			return (IMA_ERROR_INVALID_PARAMETER);
   1332 		}
   1333 
   1334 		*closeBracketPos = NULL;
   1335 		(void) strlcpy(target_addr_str, &tmp_target_str[1],
   1336 		    sizeof (target_addr_str));
   1337 
   1338 		if (inet_pton(AF_INET6, target_addr_str,
   1339 		    &target_in.u_in6) != 1) {
   1340 			return (IMA_ERROR_INVALID_PARAMETER);
   1341 		}
   1342 		target_in_addr_size = sizeof (struct in6_addr);
   1343 
   1344 		/* Extract the port number */
   1345 		closeBracketPos++;
   1346 		if (*closeBracketPos == ':') {
   1347 			closeBracketPos++;
   1348 
   1349 			if (*closeBracketPos != NULL) {
   1350 				(void) strlcpy(target_port_str, closeBracketPos,
   1351 				    sizeof (target_port_str));
   1352 				target_port = atoi(target_port_str);
   1353 			} else {
   1354 				target_port = ISCSI_LISTEN_PORT;
   1355 			}
   1356 		} else {
   1357 			/* No port number specified; use default port */
   1358 			target_port = ISCSI_LISTEN_PORT;
   1359 		}
   1360 	} else {
   1361 		/* IPv4 address */
   1362 		char *colonPos;
   1363 		colonPos = strchr(tmp_target_str, ':');
   1364 		if (!colonPos) {
   1365 			/* No port number specified; use default port */
   1366 			target_port = ISCSI_LISTEN_PORT;
   1367 			(void) strlcpy(target_addr_str, tmp_target_str,
   1368 			    sizeof (target_addr_str));
   1369 		} else {
   1370 			*colonPos = NULL;
   1371 			(void) strlcpy(target_addr_str, tmp_target_str,
   1372 			    sizeof (target_addr_str));
   1373 			/* Extract the port number */
   1374 			colonPos++;
   1375 			if (*colonPos != NULL) {
   1376 				(void) strlcpy(target_port_str, colonPos,
   1377 				    sizeof (target_port_str));
   1378 				target_port = atoi(target_port_str);
   1379 			} else {
   1380 				target_port = ISCSI_LISTEN_PORT;
   1381 			}
   1382 		}
   1383 
   1384 		if (inet_pton(AF_INET, target_addr_str,
   1385 		    &target_in.u_in4) != 1) {
   1386 			return (IMA_ERROR_INVALID_PARAMETER);
   1387 		}
   1388 
   1389 		target_in_addr_size = sizeof (struct in_addr);
   1390 	}
   1391 
   1392 
   1393 	(void) memset(&target, 0, sizeof (iscsi_target_entry_t));
   1394 	target.te_entry.e_vers = ISCSI_INTERFACE_VERSION;
   1395 	target.te_entry.e_oid = ISCSI_OID_NOTSET;
   1396 	target.te_entry.e_tpgt = ISCSI_DEFAULT_TPGT;
   1397 
   1398 	(void) wcstombs((char *)target.te_name, staticConfig.targetName,
   1399 	    ISCSI_MAX_NAME_LEN);
   1400 
   1401 	target.te_entry.e_insize = target_in_addr_size;
   1402 	if (target.te_entry.e_insize == sizeof (struct in_addr)) {
   1403 		target.te_entry.e_u.u_in4.s_addr = target_in.u_in4.s_addr;
   1404 	} else if (target.te_entry.e_insize == sizeof (struct in6_addr)) {
   1405 		bcopy(target_in.u_in6.s6_addr,
   1406 		    target.te_entry.e_u.u_in6.s6_addr,
   1407 		    sizeof (struct in6_addr));
   1408 	} else {
   1409 		/* Should not happen */
   1410 		syslog(LOG_USER|LOG_DEBUG,
   1411 		    "ISCSI_STATIC_GET returned bad address");
   1412 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1413 	}
   1414 
   1415 	target.te_entry.e_port = target_port;
   1416 
   1417 	/* No target portal group specified. Default to -1. */
   1418 	target.te_entry.e_tpgt = ISCSI_DEFAULT_TPGT;
   1419 
   1420 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1421 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1422 		    ISCSI_DRIVER_DEVCTL, errno);
   1423 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1424 	}
   1425 
   1426 	if (ioctl(fd, ISCSI_STATIC_SET, &target)) {
   1427 		/*
   1428 		 * Encountered problem setting the IP address and port for
   1429 		 * the target just added.
   1430 		 */
   1431 		(void) close(fd);
   1432 		syslog(LOG_USER|LOG_DEBUG,
   1433 		    "ISCSI_STATIC_SET ioctl failed, errno: %d", errno);
   1434 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1435 	}
   1436 
   1437 	pTargetOid->objectType = IMA_OBJECT_TYPE_TARGET;
   1438 	pTargetOid->ownerId = pluginOwnerId;
   1439 	pTargetOid->objectSequenceNumber = target.te_entry.e_oid;
   1440 
   1441 	(void) close(fd);
   1442 	return (IMA_STATUS_SUCCESS);
   1443 }
   1444 
   1445 IMA_API	IMA_STATUS IMA_GetTargetProperties(
   1446 		IMA_OID targetId,
   1447 		IMA_TARGET_PROPERTIES *pProps
   1448 )
   1449 {
   1450 	return (getTargetProperties(targetId, pProps));
   1451 }
   1452 
   1453 static IMA_STATUS getTargetProperties(
   1454 		IMA_OID targetId,
   1455 		IMA_TARGET_PROPERTIES *pProps
   1456 )
   1457 {
   1458 	int		    fd;
   1459 	iscsi_property_t    prop;
   1460 
   1461 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1462 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1463 		    ISCSI_DRIVER_DEVCTL, errno);
   1464 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1465 	}
   1466 
   1467 	(void) memset(&prop, 0, sizeof (iscsi_property_t));
   1468 	prop.p_vers = ISCSI_INTERFACE_VERSION;
   1469 	prop.p_oid = (uint32_t)targetId.objectSequenceNumber;
   1470 
   1471 	if (ioctl(fd, ISCSI_TARGET_PROPS_GET, &prop) != 0) {
   1472 		(void) close(fd);
   1473 		syslog(LOG_USER|LOG_DEBUG,
   1474 		    "ISCSI_TARGET_PROPS_GET ioctl failed, errno: %d", errno);
   1475 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1476 	}
   1477 
   1478 	(void) mbstowcs(pProps->name, (char *)prop.p_name, IMA_NODE_NAME_LEN);
   1479 	(void) memset(pProps->alias, 0,
   1480 	    sizeof (IMA_WCHAR) * IMA_NODE_ALIAS_LEN);
   1481 	if (prop.p_alias_len > 0) {
   1482 		(void) mbstowcs(pProps->alias, (char *)prop.p_alias,
   1483 		    IMA_NODE_ALIAS_LEN);
   1484 	}
   1485 
   1486 	/* Initialize the discovery method to unknown method. */
   1487 	pProps->discoveryMethodFlags = IMA_TARGET_DISCOVERY_METHOD_UNKNOWN;
   1488 	if (!((prop.p_discovery & iSCSIDiscoveryMethodStatic) ^
   1489 	    iSCSIDiscoveryMethodStatic)) {
   1490 		pProps->discoveryMethodFlags |=
   1491 		    IMA_TARGET_DISCOVERY_METHOD_STATIC;
   1492 	}
   1493 
   1494 	if (!((prop.p_discovery & iSCSIDiscoveryMethodSLP) ^
   1495 	    iSCSIDiscoveryMethodSLP)) {
   1496 		pProps->discoveryMethodFlags |=	IMA_TARGET_DISCOVERY_METHOD_SLP;
   1497 	}
   1498 
   1499 	if (!((prop.p_discovery & iSCSIDiscoveryMethodISNS) ^
   1500 	    iSCSIDiscoveryMethodISNS)) {
   1501 		pProps->discoveryMethodFlags |=	iSCSIDiscoveryMethodISNS;
   1502 	}
   1503 
   1504 	if (!((prop.p_discovery & iSCSIDiscoveryMethodSendTargets) ^
   1505 	    iSCSIDiscoveryMethodSendTargets)) {
   1506 		pProps->discoveryMethodFlags |= iSCSIDiscoveryMethodSendTargets;
   1507 	}
   1508 
   1509 	(void) close(fd);
   1510 	return (IMA_STATUS_SUCCESS);
   1511 }
   1512 
   1513 /*ARGSUSED*/
   1514 IMA_API	IMA_STATUS IMA_GetTargetErrorStatistics(
   1515 		IMA_OID targetId,
   1516 		IMA_TARGET_ERROR_STATISTICS *pStats
   1517 )
   1518 {
   1519 	return (IMA_ERROR_NOT_SUPPORTED);
   1520 }
   1521 
   1522 IMA_API	IMA_STATUS IMA_GetLuOidList(
   1523 		IMA_OID oid,
   1524 		IMA_OID_LIST **ppList
   1525 )
   1526 {
   1527 	IMA_STATUS		status;
   1528 	int			i;
   1529 	iscsi_lun_list_t	*pLunList;
   1530 
   1531 	if (oid.objectType == IMA_OBJECT_TYPE_LHBA) {
   1532 		status = get_target_lun_oid_list(NULL, &pLunList);
   1533 	} else {
   1534 		status = get_target_lun_oid_list(&oid, &pLunList);
   1535 	}
   1536 
   1537 	if (!IMA_SUCCESS(status)) {
   1538 		return (status);
   1539 	}
   1540 
   1541 	*ppList = (IMA_OID_LIST *) calloc(1, (sizeof (IMA_OID_LIST) +
   1542 	    (pLunList->ll_out_cnt * sizeof (IMA_OID))));
   1543 	if (*ppList == NULL) {
   1544 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   1545 	}
   1546 	(*ppList)->oidCount = pLunList->ll_out_cnt;
   1547 	for (i = 0; i < pLunList->ll_out_cnt; i++) {
   1548 		(*ppList)->oids[i].objectType = IMA_OBJECT_TYPE_LU;
   1549 		(*ppList)->oids[i].ownerId = pluginOwnerId;
   1550 		(*ppList)->oids[i].objectSequenceNumber =
   1551 		    pLunList->ll_luns[i].l_oid;
   1552 	}
   1553 
   1554 	free(pLunList);
   1555 	return (IMA_STATUS_SUCCESS);
   1556 }
   1557 
   1558 IMA_API	IMA_STATUS IMA_GetLuOid(
   1559 		IMA_OID targetId,
   1560 		IMA_UINT64 lun,
   1561 		IMA_OID *pluId
   1562 )
   1563 {
   1564 	IMA_STATUS		status;
   1565 	int			i;
   1566 	iscsi_lun_list_t	*pLunList;
   1567 
   1568 	status = get_target_lun_oid_list(&targetId, &pLunList);
   1569 	if (!IMA_SUCCESS(status)) {
   1570 		return (status);
   1571 	}
   1572 
   1573 	for (i = 0; i < pLunList->ll_out_cnt; i++) {
   1574 		if (pLunList->ll_luns[i].l_num == lun) {
   1575 			pluId->objectType = IMA_OBJECT_TYPE_LU;
   1576 			pluId->ownerId = pluginOwnerId;
   1577 			pluId->objectSequenceNumber =
   1578 			    pLunList->ll_luns[i].l_oid;
   1579 			free(pLunList);
   1580 			return (IMA_STATUS_SUCCESS);
   1581 		}
   1582 	}
   1583 
   1584 	free(pLunList);
   1585 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   1586 }
   1587 
   1588 IMA_API	IMA_STATUS IMA_GetLuProperties(
   1589 		IMA_OID luId,
   1590 		IMA_LU_PROPERTIES *pProps
   1591 )
   1592 {
   1593 	return (getLuProperties(luId, pProps));
   1594 }
   1595 
   1596 static IMA_STATUS getLuProperties(
   1597 		IMA_OID luId,
   1598 		IMA_LU_PROPERTIES *pProps
   1599 )
   1600 {
   1601 	IMA_STATUS		status;
   1602 	iscsi_lun_list_t	*pLunList;
   1603 	int			j;
   1604 	IMA_BOOL		lunMatch = IMA_FALSE;
   1605 	int			fd;
   1606 	iscsi_lun_props_t	lun;
   1607 	di_devlink_handle_t	hdl;
   1608 
   1609 	if (luId.objectType != IMA_OBJECT_TYPE_LU) {
   1610 		return (IMA_ERROR_INCORRECT_OBJECT_TYPE);
   1611 	}
   1612 
   1613 	/*
   1614 	 * get list of lun oids for all targets
   1615 	 */
   1616 	status = get_target_lun_oid_list(NULL, &pLunList);
   1617 	if (!IMA_SUCCESS(status)) {
   1618 		return (status);
   1619 	}
   1620 	for (j = 0; j < pLunList->ll_out_cnt; j++) {
   1621 		/*
   1622 		 * for each lun, check if match is found
   1623 		 */
   1624 		if (pLunList->ll_luns[j].l_oid == luId.objectSequenceNumber) {
   1625 			/*
   1626 			 * match found, break out of lun loop
   1627 			 */
   1628 			lunMatch = IMA_TRUE;
   1629 			break;
   1630 		}
   1631 	}
   1632 
   1633 	if (lunMatch == IMA_TRUE) {
   1634 		(void) memset(&lun, 0, sizeof (iscsi_lun_props_t));
   1635 		lun.lp_vers = ISCSI_INTERFACE_VERSION;
   1636 		lun.lp_tgt_oid = pLunList->ll_luns[j].l_tgt_oid;
   1637 		lun.lp_oid = pLunList->ll_luns[j].l_oid;
   1638 	}
   1639 
   1640 	free(pLunList);
   1641 
   1642 	if (lunMatch == IMA_FALSE) {
   1643 		return (IMA_ERROR_OBJECT_NOT_FOUND);
   1644 	}
   1645 
   1646 	/*
   1647 	 * get lun properties
   1648 	 */
   1649 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1650 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1651 		    ISCSI_DRIVER_DEVCTL, errno);
   1652 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1653 	}
   1654 
   1655 	if (ioctl(fd, ISCSI_LUN_PROPS_GET, &lun)) {
   1656 		syslog(LOG_USER|LOG_DEBUG,
   1657 		    "ISCSI_LUN_PROPS_GET ioctl failed, errno: %d", errno);
   1658 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1659 	}
   1660 	(void) close(fd);
   1661 
   1662 	/*
   1663 	 * set property values
   1664 	 */
   1665 	pProps->associatedTargetOid.objectType = IMA_OBJECT_TYPE_TARGET;
   1666 	pProps->associatedTargetOid.ownerId = pluginOwnerId;
   1667 	pProps->associatedTargetOid.objectSequenceNumber = lun.lp_tgt_oid;
   1668 	pProps->targetLun = (IMA_UINT64)lun.lp_num;
   1669 	pProps->exposedToOs = IMA_TRUE;
   1670 	(void) memset(&pProps->timeExposedToOs, 0,
   1671 	    sizeof (pProps->timeExposedToOs));
   1672 
   1673 	if (lun.lp_status == LunValid) {
   1674 
   1675 		/* add minor device delimiter */
   1676 		(void) strcat(lun.lp_pathname, ":");
   1677 
   1678 		if ((strstr(lun.lp_pathname, "sd@") != NULL) ||
   1679 		    (strstr(lun.lp_pathname, "ssd@") != NULL) ||
   1680 		    (strstr(lun.lp_pathname, "disk@") != NULL)) {
   1681 			/*
   1682 			 * modify returned pathname to obtain the 2nd slice
   1683 			 * of the raw disk
   1684 			 */
   1685 			(void) strcat(lun.lp_pathname, "c,raw");
   1686 		}
   1687 
   1688 		/*
   1689 		 * Pathname returned by driver is the physical device path.
   1690 		 * This name needs to be converted to the OS device name.
   1691 		 */
   1692 		if (hdl = di_devlink_init(lun.lp_pathname, DI_MAKE_LINK)) {
   1693 			pProps->osDeviceName[0] = L'\0';
   1694 			(void) di_devlink_walk(hdl, NULL, lun.lp_pathname,
   1695 			    DI_PRIMARY_LINK, (void *)pProps->osDeviceName,
   1696 			    get_lun_devlink);
   1697 			if (pProps->osDeviceName[0] != L'\0') {
   1698 				/* OS device name synchronously made */
   1699 				pProps->osDeviceNameValid = IMA_TRUE;
   1700 			} else {
   1701 				pProps->osDeviceNameValid = IMA_FALSE;
   1702 			}
   1703 
   1704 			(void) di_devlink_fini(&hdl);
   1705 		} else {
   1706 			pProps->osDeviceNameValid = IMA_FALSE;
   1707 		}
   1708 
   1709 	} else {
   1710 		pProps->osDeviceNameValid = IMA_FALSE;
   1711 	}
   1712 
   1713 	pProps->osParallelIdsValid = IMA_FALSE;
   1714 
   1715 	return (IMA_STATUS_SUCCESS);
   1716 }
   1717 
   1718 /*ARGSUSED*/
   1719 IMA_API	IMA_STATUS IMA_GetStatisticsProperties(
   1720 		IMA_OID oid,
   1721 		IMA_STATISTICS_PROPERTIES *pProps
   1722 )
   1723 {
   1724 	return (IMA_ERROR_NOT_SUPPORTED);
   1725 }
   1726 
   1727 /*ARGSUSED*/
   1728 IMA_API	IMA_STATUS IMA_GetDeviceStatistics(
   1729 		IMA_OID luId,
   1730 		IMA_DEVICE_STATISTICS *pStats
   1731 )
   1732 {
   1733 	return (IMA_ERROR_NOT_SUPPORTED);
   1734 }
   1735 
   1736 IMA_API	IMA_STATUS IMA_LuInquiry(
   1737 	IMA_OID deviceId,
   1738 	IMA_BOOL evpd,
   1739 	IMA_BOOL cmddt,
   1740 	IMA_BYTE pageCode,
   1741 	IMA_BYTE *pOutputBuffer,
   1742 	IMA_UINT *pOutputBufferLength,
   1743 	IMA_BYTE *pSenseBuffer,
   1744 	IMA_UINT *pSenseBufferLength
   1745 )
   1746 {
   1747 	IMA_LU_PROPERTIES luProps;
   1748 	IMA_STATUS status;
   1749 	unsigned char cmdblk[CDB_GROUP0];
   1750 	IMA_UINT buflen;
   1751 	int fd;
   1752 	iscsi_uscsi_t uscsi;
   1753 
   1754 	(void) memset(&cmdblk[0], 0, CDB_GROUP0);
   1755 	cmdblk[0] = SCMD_INQUIRY;
   1756 
   1757 	if (evpd == IMA_TRUE)
   1758 		cmdblk[1] |= 0x01;
   1759 	if (cmddt == IMA_TRUE)
   1760 		cmdblk[1] |= 0x02;
   1761 
   1762 	cmdblk[2] = pageCode;
   1763 
   1764 	if (*pOutputBufferLength > MAX_INQUIRY_BUFFER_LEN) {
   1765 		buflen = MAX_INQUIRY_BUFFER_LEN;
   1766 	} else {
   1767 		buflen = *pOutputBufferLength;
   1768 	}
   1769 	cmdblk[3] = (buflen & 0xff00) >> 8;
   1770 	cmdblk[4] = (buflen & 0x00ff);
   1771 
   1772 	(void) memset(&uscsi, 0, sizeof (iscsi_uscsi_t));
   1773 	uscsi.iu_vers 	= ISCSI_INTERFACE_VERSION;
   1774 
   1775 	/* iu_oid is a session oid in the driver */
   1776 	if (deviceId.objectType == IMA_OBJECT_TYPE_TARGET) {
   1777 		uscsi.iu_oid	= deviceId.objectSequenceNumber;
   1778 		uscsi.iu_lun	= 0;
   1779 	} else {
   1780 		/*
   1781 		 * Get LU properties and associated session oid
   1782 		 * for this lun(deviceId) and put in uscsi.iu_oid
   1783 		 */
   1784 		status = getLuProperties(deviceId, &luProps);
   1785 		if (status != IMA_STATUS_SUCCESS) {
   1786 			return (status);
   1787 		}
   1788 		uscsi.iu_oid = (uint32_t)luProps.associatedTargetOid.
   1789 		    objectSequenceNumber;
   1790 		uscsi.iu_lun = luProps.targetLun;
   1791 	}
   1792 
   1793 	uscsi.iu_ucmd.uscsi_flags = USCSI_READ;
   1794 	uscsi.iu_ucmd.uscsi_timeout = USCSI_TIMEOUT_IN_SEC;
   1795 	uscsi.iu_ucmd.uscsi_bufaddr = (char *)pOutputBuffer;
   1796 	uscsi.iu_ucmd.uscsi_buflen = buflen;
   1797 	uscsi.iu_ucmd.uscsi_rqbuf = (char *)pSenseBuffer;
   1798 	uscsi.iu_ucmd.uscsi_rqlen = (pSenseBufferLength != NULL) ?
   1799 	    *pSenseBufferLength : 0;
   1800 	uscsi.iu_ucmd.uscsi_cdb = (char *)&cmdblk[0];
   1801 	uscsi.iu_ucmd.uscsi_cdblen = CDB_GROUP0;
   1802 
   1803 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1804 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1805 		    ISCSI_DRIVER_DEVCTL, errno);
   1806 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1807 	}
   1808 
   1809 	if (ioctl(fd, ISCSI_USCSI, &uscsi) != 0) {
   1810 		(void) close(fd);
   1811 		syslog(LOG_USER|LOG_DEBUG,
   1812 		    "ISCSI_TARGET_PROPS_GET ioctl failed, errno: %d", errno);
   1813 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1814 	}
   1815 
   1816 	if (uscsi.iu_ucmd.uscsi_status == STATUS_CHECK) {
   1817 		if (pSenseBufferLength != NULL) {
   1818 			*pSenseBufferLength -= uscsi.iu_ucmd.uscsi_rqresid;
   1819 		}
   1820 		return (IMA_ERROR_SCSI_STATUS_CHECK_CONDITION);
   1821 	}
   1822 
   1823 	*pOutputBufferLength = buflen - uscsi.iu_ucmd.uscsi_resid;
   1824 	return (IMA_STATUS_SUCCESS);
   1825 }
   1826 
   1827 IMA_API	IMA_STATUS IMA_LuReadCapacity(
   1828 		IMA_OID deviceId,
   1829 		IMA_UINT cdbLength,
   1830 		IMA_BYTE *pOutputBuffer,
   1831 		IMA_UINT *pOutputBufferLength,
   1832 
   1833 		IMA_BYTE *pSenseBuffer,
   1834 		IMA_UINT *pSenseBufferLength
   1835 )
   1836 {
   1837 	IMA_LU_PROPERTIES luProps;
   1838 	IMA_STATUS status;
   1839 	/* CDB_GROUP4 size is safe for both 10 and 16 byte CDBs */
   1840 	unsigned char cmdblk[CDB_GROUP4];
   1841 	IMA_UINT buflen;
   1842 	int fd;
   1843 	iscsi_uscsi_t uscsi;
   1844 
   1845 	(void) memset(&cmdblk[0], 0, CDB_GROUP4);
   1846 
   1847 	if (cdbLength == CDB_GROUP1) {
   1848 		/* Read Capacity (10) command. */
   1849 		cmdblk[0] = SCMD_READ_CAPACITY;
   1850 		buflen = *pOutputBufferLength;
   1851 	} else if (cdbLength == CDB_GROUP4) {
   1852 		/*
   1853 		 * Read Capacity (16) is a Service Action In command. One
   1854 		 * command byte (0x9E) is overloaded for multiple operations,
   1855 		 * with the second CDB byte specifying the desired operation.
   1856 		 */
   1857 		cmdblk[0] = SCMD_SVC_ACTION_IN_G4;
   1858 		cmdblk[1] = SSVC_ACTION_READ_CAPACITY_G4;
   1859 
   1860 		if (*pOutputBufferLength > MAX_READ_CAPACITY16_BUFFER_LEN) {
   1861 			buflen = MAX_READ_CAPACITY16_BUFFER_LEN;
   1862 		} else {
   1863 			buflen = *pOutputBufferLength;
   1864 		}
   1865 		cmdblk[10] = (buflen & 0xff000000) >> 24;
   1866 		cmdblk[11] = (buflen & 0x00ff0000) >> 16;
   1867 		cmdblk[12] = (buflen & 0x0000ff00) >> 8;
   1868 		cmdblk[13] = (buflen & 0x000000ff);
   1869 	} else {
   1870 		/* only 10 and 16 byte CDB are supported */
   1871 		return (IMA_ERROR_NOT_SUPPORTED);
   1872 	}
   1873 
   1874 	(void) memset(&uscsi, 0, sizeof (iscsi_uscsi_t));
   1875 	uscsi.iu_vers 	= ISCSI_INTERFACE_VERSION;
   1876 
   1877 	/* iu_oid is a session oid in the driver */
   1878 	if (deviceId.objectType == IMA_OBJECT_TYPE_TARGET) {
   1879 		uscsi.iu_oid	= deviceId.objectSequenceNumber;
   1880 		uscsi.iu_lun	= 0;
   1881 	} else {
   1882 		/*
   1883 		 * Get LU properties and associated session oid
   1884 		 * for this lun(deviceId) and put in uscsi.iu_oid
   1885 		 */
   1886 		status = getLuProperties(deviceId, &luProps);
   1887 		if (status != IMA_STATUS_SUCCESS) {
   1888 			return (status);
   1889 		}
   1890 		uscsi.iu_oid = (uint32_t)luProps.associatedTargetOid.
   1891 		    objectSequenceNumber;
   1892 		uscsi.iu_lun = luProps.targetLun;
   1893 	}
   1894 
   1895 	uscsi.iu_ucmd.uscsi_flags = USCSI_READ;
   1896 	uscsi.iu_ucmd.uscsi_timeout = USCSI_TIMEOUT_IN_SEC;
   1897 	uscsi.iu_ucmd.uscsi_bufaddr = (char *)pOutputBuffer;
   1898 	uscsi.iu_ucmd.uscsi_buflen = buflen;
   1899 	uscsi.iu_ucmd.uscsi_rqbuf = (char *)pSenseBuffer;
   1900 	uscsi.iu_ucmd.uscsi_rqlen = (pSenseBufferLength != NULL) ?
   1901 	    *pSenseBufferLength : 0;
   1902 	uscsi.iu_ucmd.uscsi_cdb = (char *)&cmdblk[0];
   1903 	uscsi.iu_ucmd.uscsi_cdblen = cdbLength;
   1904 
   1905 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1906 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1907 		    ISCSI_DRIVER_DEVCTL, errno);
   1908 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1909 	}
   1910 
   1911 	if (ioctl(fd, ISCSI_USCSI, &uscsi) != 0) {
   1912 		(void) close(fd);
   1913 		syslog(LOG_USER|LOG_DEBUG,
   1914 		    "ISCSI_TARGET_PROPS_GET ioctl failed, errno: %d", errno);
   1915 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   1916 	}
   1917 
   1918 	if (uscsi.iu_ucmd.uscsi_status == STATUS_CHECK) {
   1919 		if (pSenseBufferLength != NULL) {
   1920 			*pSenseBufferLength -= uscsi.iu_ucmd.uscsi_rqresid;
   1921 		}
   1922 		return (IMA_ERROR_SCSI_STATUS_CHECK_CONDITION);
   1923 	}
   1924 
   1925 	*pOutputBufferLength = buflen - uscsi.iu_ucmd.uscsi_resid;
   1926 	return (IMA_STATUS_SUCCESS);
   1927 }
   1928 
   1929 IMA_API	IMA_STATUS IMA_LuReportLuns(
   1930 		IMA_OID deviceId,
   1931 		IMA_BOOL sendToWellKnownLun,
   1932 		IMA_BYTE selectReport,
   1933 
   1934 		IMA_BYTE *pOutputBuffer,
   1935 		IMA_UINT *pOutputBufferLength,
   1936 
   1937 		IMA_BYTE *pSenseBuffer,
   1938 		IMA_UINT *pSenseBufferLength
   1939 )
   1940 {
   1941 	IMA_LU_PROPERTIES luProps;
   1942 	IMA_STATUS status;
   1943 	unsigned char cmdblk[CDB_GROUP5];
   1944 	IMA_UINT buflen;
   1945 	int fd;
   1946 	iscsi_uscsi_t uscsi;
   1947 
   1948 	(void) memset(&cmdblk[0], 0, CDB_GROUP5);
   1949 	cmdblk[0] = SCMD_REPORT_LUNS;
   1950 	cmdblk[2] = selectReport;
   1951 
   1952 	if (*pOutputBufferLength > MAX_REPORT_LUNS_BUFFER_LEN) {
   1953 		buflen = MAX_REPORT_LUNS_BUFFER_LEN;
   1954 	} else {
   1955 		buflen = *pOutputBufferLength;
   1956 	}
   1957 	cmdblk[6] = (buflen & 0xff000000) >> 24;
   1958 	cmdblk[7] = (buflen & 0x00ff0000) >> 16;
   1959 	cmdblk[8] = (buflen & 0x0000ff00) >> 8;
   1960 	cmdblk[9] = (buflen & 0x000000ff);
   1961 
   1962 	(void) memset(&uscsi, 0, sizeof (iscsi_uscsi_t));
   1963 	uscsi.iu_vers 	= ISCSI_INTERFACE_VERSION;
   1964 
   1965 	/* iu_oid is a session oid in the driver */
   1966 	if (deviceId.objectType == IMA_OBJECT_TYPE_TARGET) {
   1967 		if (sendToWellKnownLun == IMA_TRUE) {
   1968 			/* this optional feature is not supported now */
   1969 			return (IMA_ERROR_NOT_SUPPORTED);
   1970 		}
   1971 		uscsi.iu_oid	= deviceId.objectSequenceNumber;
   1972 		uscsi.iu_lun	= 0;
   1973 	} else {
   1974 		/*
   1975 		 * Get LU properties and associated session oid
   1976 		 * for this lun(deviceId) and put in uscsi.iu_oid
   1977 		 */
   1978 		status = getLuProperties(deviceId, &luProps);
   1979 		if (status != IMA_STATUS_SUCCESS) {
   1980 			return (status);
   1981 		}
   1982 		uscsi.iu_oid = (uint32_t)luProps.associatedTargetOid.
   1983 		    objectSequenceNumber;
   1984 		uscsi.iu_lun = luProps.targetLun;
   1985 	}
   1986 
   1987 	uscsi.iu_ucmd.uscsi_flags = USCSI_READ;
   1988 	uscsi.iu_ucmd.uscsi_timeout = USCSI_TIMEOUT_IN_SEC;
   1989 	uscsi.iu_ucmd.uscsi_bufaddr = (char *)pOutputBuffer;
   1990 	uscsi.iu_ucmd.uscsi_buflen = buflen;
   1991 	uscsi.iu_ucmd.uscsi_rqbuf = (char *)pSenseBuffer;
   1992 	uscsi.iu_ucmd.uscsi_rqlen = (pSenseBufferLength != NULL) ?
   1993 	    *pSenseBufferLength : 0;
   1994 	uscsi.iu_ucmd.uscsi_cdb = (char *)&cmdblk[0];
   1995 	uscsi.iu_ucmd.uscsi_cdblen = CDB_GROUP5;
   1996 
   1997 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   1998 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   1999 		    ISCSI_DRIVER_DEVCTL, errno);
   2000 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2001 	}
   2002 
   2003 	if (ioctl(fd, ISCSI_USCSI, &uscsi) != 0) {
   2004 		(void) close(fd);
   2005 		syslog(LOG_USER|LOG_DEBUG,
   2006 		    "ISCSI_TARGET_PROPS_GET ioctl failed, errno: %d", errno);
   2007 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2008 	}
   2009 
   2010 	if (uscsi.iu_ucmd.uscsi_status == STATUS_CHECK) {
   2011 		if (pSenseBufferLength != NULL) {
   2012 			*pSenseBufferLength -= uscsi.iu_ucmd.uscsi_rqresid;
   2013 		}
   2014 		return (IMA_ERROR_SCSI_STATUS_CHECK_CONDITION);
   2015 	}
   2016 
   2017 	*pOutputBufferLength = buflen - uscsi.iu_ucmd.uscsi_resid;
   2018 	return (IMA_STATUS_SUCCESS);
   2019 }
   2020 
   2021 /*ARGSUSED*/
   2022 IMA_API	IMA_STATUS IMA_ExposeLu(
   2023 		IMA_OID luId
   2024 )
   2025 {
   2026 	return (IMA_ERROR_NOT_SUPPORTED);
   2027 }
   2028 
   2029 /*ARGSUSED*/
   2030 IMA_API	IMA_STATUS IMA_UnexposeLu(
   2031 		IMA_OID luId
   2032 )
   2033 {
   2034 	return (IMA_ERROR_NOT_SUPPORTED);
   2035 }
   2036 
   2037 IMA_API	IMA_STATUS IMA_GetAddressKeys(
   2038 		IMA_OID targetOid,
   2039 		IMA_ADDRESS_KEYS **ppKeys
   2040 )
   2041 {
   2042 	IMA_STATUS status;
   2043 	IMA_TARGET_PROPERTIES targetProps;
   2044 	SUN_IMA_DISC_ADDR_PROP_LIST *discAddressList;
   2045 	SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList;
   2046 	int i, j, addressKeyCount = 0;
   2047 	int addressKeyIdx = 0;
   2048 
   2049 	status = getTargetProperties(targetOid, &targetProps);
   2050 	if (status != IMA_STATUS_SUCCESS) {
   2051 		return (status);
   2052 	}
   2053 
   2054 	status = getDiscoveryAddressPropertiesList(&discAddressList);
   2055 	if (status != IMA_STATUS_SUCCESS) {
   2056 		return (status);
   2057 	}
   2058 
   2059 	/* Get the number of addresses to allocate */
   2060 	for (i = 0; i < discAddressList->discAddrCount; i++) {
   2061 		(void) sendTargets(discAddressList->props[i].discoveryAddress,
   2062 		    &pList);
   2063 		for (j = 0; j < pList->keyCount; j++) {
   2064 			if (wcsncmp(pList->keys[j].name, targetProps.name,
   2065 			    wslen(pList->keys[j].name)) == 0) {
   2066 				addressKeyCount++;
   2067 			}
   2068 		}
   2069 		(void) IMA_FreeMemory(pList);
   2070 	}
   2071 
   2072 	*ppKeys = (IMA_ADDRESS_KEYS *)calloc(1, sizeof (IMA_ADDRESS_KEYS) +
   2073 	    addressKeyCount * sizeof (IMA_ADDRESS_KEY));
   2074 	if (*ppKeys == NULL) {
   2075 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   2076 	}
   2077 	(*ppKeys)->addressKeyCount = addressKeyCount;
   2078 	addressKeyIdx = 0;
   2079 
   2080 	for (i = 0; i < discAddressList->discAddrCount; i++) {
   2081 		(void) sendTargets(discAddressList->props[i].discoveryAddress,
   2082 		    &pList);
   2083 		for (j = 0; j < pList->keyCount; j++) {
   2084 			if (wcsncmp(pList->keys[j].name, targetProps.name,
   2085 			    wslen(pList->keys[j].name)) != 0) {
   2086 				continue;
   2087 			}
   2088 
   2089 			bcopy(&(pList->keys[j].address.ipAddress),
   2090 			    &((*ppKeys)->addressKeys[addressKeyIdx].
   2091 			    ipAddress), sizeof (IMA_IP_ADDRESS));
   2092 
   2093 			(*ppKeys)->addressKeys[addressKeyIdx++].portNumber =
   2094 			    pList->keys[j].address.portNumber;
   2095 
   2096 		}
   2097 		(void) IMA_FreeMemory(pList);
   2098 	}
   2099 	return (IMA_STATUS_SUCCESS);
   2100 }
   2101 
   2102 IMA_BOOL isAuthMethodValid(IMA_OID oid, IMA_AUTHMETHOD method) {
   2103 	IMA_STATUS status;
   2104 	IMA_AUTHMETHOD supportedList[MAX_AUTHMETHODS];
   2105 	IMA_UINT i, supportedCount;
   2106 	IMA_BOOL supported;
   2107 	status = getSupportedAuthMethods(oid, IMA_FALSE, &supportedCount,
   2108 			supportedList);
   2109 	if (status != IMA_STATUS_SUCCESS)
   2110 		return (IMA_FALSE);
   2111 
   2112 	supported = IMA_FALSE;
   2113 	for (i = 0; i < supportedCount; i++) {
   2114 		if (method == supportedList[i]) {
   2115 			supported = IMA_TRUE;
   2116 		}
   2117 	}
   2118 
   2119 	return (supported);
   2120 }
   2121 
   2122 IMA_BOOL isAuthMethodListValid(IMA_OID oid, const IMA_AUTHMETHOD *pMethodList,
   2123 				IMA_UINT methodCount) {
   2124 	IMA_UINT i, j;
   2125 
   2126 	if (pMethodList == NULL) {
   2127 		return (IMA_FALSE);
   2128 	}
   2129 	/* Check list for duplicates */
   2130 	for (i = 0; i < methodCount; i++) {
   2131 		for (j = i + 1; j < methodCount; j++) {
   2132 			if (pMethodList[i] == pMethodList[j]) {
   2133 				return (IMA_FALSE);
   2134 			}
   2135 		}
   2136 
   2137 		if (isAuthMethodValid(oid, pMethodList[i]) == IMA_FALSE) {
   2138 			return (IMA_FALSE);
   2139 		}
   2140 	}
   2141 	return (IMA_TRUE);
   2142 }
   2143 
   2144 IMA_API	IMA_STATUS IMA_GetSupportedAuthMethods(
   2145 		IMA_OID lhbaOid,
   2146 		IMA_BOOL getSettableMethods,
   2147 		IMA_UINT *pMethodCount,
   2148 		IMA_AUTHMETHOD *pMethodList
   2149 )
   2150 {
   2151 	return (getSupportedAuthMethods(lhbaOid, getSettableMethods,
   2152 	    pMethodCount, pMethodList));
   2153 }
   2154 
   2155 
   2156 /*ARGSUSED*/
   2157 static IMA_STATUS getSupportedAuthMethods(
   2158 		IMA_OID lhbaOid,
   2159 		IMA_BOOL getSettableMethods,
   2160 		IMA_UINT *pMethodCount,
   2161 		IMA_AUTHMETHOD *pMethodList
   2162 )
   2163 {
   2164 	if (pMethodList == NULL) {
   2165 		*pMethodCount = 0;
   2166 		return (IMA_STATUS_SUCCESS);
   2167 	}
   2168 
   2169 	*pMethodCount = NUM_SUPPORTED_AUTH_METHODS;
   2170 	if (*pMethodCount > 1) {
   2171 		pMethodList[0] = IMA_AUTHMETHOD_NONE;
   2172 		pMethodList[1] = IMA_AUTHMETHOD_CHAP;
   2173 	}
   2174 
   2175 	return (IMA_STATUS_SUCCESS);
   2176 }
   2177 
   2178 IMA_API	IMA_STATUS IMA_GetInUseInitiatorAuthMethods(
   2179 		IMA_OID		lhbaOid,
   2180 		IMA_UINT	*pMethodCount,
   2181 		IMA_AUTHMETHOD *pMethodList
   2182 )
   2183 {
   2184 	return (getAuthMethods(lhbaOid, pMethodCount, pMethodList));
   2185 }
   2186 
   2187 /*ARGSUSED*/
   2188 IMA_API	IMA_STATUS IMA_GetInitiatorAuthParms(
   2189 		IMA_OID lhbaOid,
   2190 		IMA_AUTHMETHOD method,
   2191 		IMA_INITIATOR_AUTHPARMS *pParms
   2192 )
   2193 {
   2194 	int fd;
   2195 	iscsi_chap_props_t  chap_p;
   2196 
   2197 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2198 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2199 		    ISCSI_DRIVER_DEVCTL, errno);
   2200 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2201 	}
   2202 
   2203 	(void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t));
   2204 	chap_p.c_vers = ISCSI_INTERFACE_VERSION;
   2205 	chap_p.c_oid = (uint32_t)lhbaOid.objectSequenceNumber;
   2206 
   2207 	if (method == IMA_AUTHMETHOD_CHAP) {
   2208 		if (ioctl(fd, ISCSI_CHAP_GET, &chap_p) != 0) {
   2209 			syslog(LOG_USER|LOG_DEBUG,
   2210 			"ISCSI_CHAP_GET ioctl failed, errno: %d", errno);
   2211 			(void) close(fd);
   2212 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2213 		}
   2214 	} else {
   2215 		return (IMA_ERROR_INVALID_PARAMETER);
   2216 	}
   2217 
   2218 	(void) memcpy(pParms->chapParms.name, chap_p.c_user,
   2219 	    chap_p.c_user_len);
   2220 	pParms->chapParms.nameLength = chap_p.c_user_len;
   2221 	(void) memcpy(pParms->chapParms.challengeSecret, chap_p.c_secret,
   2222 	    chap_p.c_secret_len);
   2223 	pParms->chapParms.challengeSecretLength = chap_p.c_secret_len;
   2224 
   2225 	return (IMA_STATUS_SUCCESS);
   2226 }
   2227 
   2228 IMA_API	IMA_STATUS IMA_SetInitiatorAuthMethods(
   2229 		IMA_OID lhbaOid,
   2230 		IMA_UINT methodCount,
   2231 		const IMA_AUTHMETHOD *pMethodList
   2232 )
   2233 {
   2234 	if (isAuthMethodListValid(lhbaOid, pMethodList,
   2235 	    methodCount) == IMA_FALSE)
   2236 		return (IMA_ERROR_INVALID_PARAMETER);
   2237 	return (setAuthMethods(lhbaOid, &methodCount, pMethodList));
   2238 }
   2239 
   2240 /*
   2241  * This function only sets CHAP params since we only support CHAP for now.
   2242  */
   2243 IMA_API	IMA_STATUS IMA_SetInitiatorAuthParms(
   2244 		IMA_OID lhbaOid,
   2245 		IMA_AUTHMETHOD method,
   2246 		const IMA_INITIATOR_AUTHPARMS *pParms
   2247 )
   2248 {
   2249 	int fd;
   2250 	iscsi_chap_props_t  chap_p;
   2251 
   2252 	if (method != IMA_AUTHMETHOD_CHAP)
   2253 		return (IMA_ERROR_INVALID_PARAMETER);
   2254 
   2255 	if (isAuthMethodValid(lhbaOid, method) == IMA_FALSE) {
   2256 		return (IMA_ERROR_INVALID_PARAMETER);
   2257 	}
   2258 
   2259 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2260 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2261 		    ISCSI_DRIVER_DEVCTL, errno);
   2262 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2263 	}
   2264 
   2265 	(void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t));
   2266 	chap_p.c_vers = ISCSI_INTERFACE_VERSION;
   2267 	chap_p.c_oid = (uint32_t)lhbaOid.objectSequenceNumber;
   2268 
   2269 	chap_p.c_user_len = pParms->chapParms.nameLength;
   2270 	(void) memcpy(chap_p.c_user, pParms->chapParms.name, chap_p.c_user_len);
   2271 
   2272 	chap_p.c_secret_len = pParms->chapParms.challengeSecretLength;
   2273 	(void) memcpy(chap_p.c_secret, pParms->chapParms.challengeSecret,
   2274 	    chap_p.c_secret_len);
   2275 
   2276 	if (method == IMA_AUTHMETHOD_CHAP) {
   2277 		if (ioctl(fd, ISCSI_CHAP_SET, &chap_p) != 0) {
   2278 			(void) close(fd);
   2279 			syslog(LOG_USER|LOG_DEBUG,
   2280 			    "ISCSI_CHAP_SET ioctl failed, errno: %d", errno);
   2281 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2282 		}
   2283 	}
   2284 
   2285 	return (IMA_STATUS_SUCCESS);
   2286 }
   2287 
   2288 /* A helper function to obtain iSCSI node parameters. */
   2289 static IMA_STATUS
   2290 getISCSINodeParameter(
   2291     int paramType,
   2292     IMA_OID *oid,
   2293     void *pProps,
   2294     uint32_t paramIndex
   2295 )
   2296 {
   2297 	int		    fd;
   2298 	iscsi_param_get_t   pg;
   2299 
   2300 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2301 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2302 		    ISCSI_DRIVER_DEVCTL, errno);
   2303 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2304 	}
   2305 
   2306 	(void) memset(&pg, 0, sizeof (iscsi_param_get_t));
   2307 	pg.g_vers = ISCSI_INTERFACE_VERSION;
   2308 	pg.g_oid = (uint32_t)oid->objectSequenceNumber;
   2309 	pg.g_param = paramIndex;
   2310 	pg.g_param_type = ISCSI_SESS_PARAM;
   2311 
   2312 	if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) {
   2313 		syslog(LOG_USER|LOG_DEBUG,
   2314 		    "ISCSI_PARAM_GET ioctl failed, errno: %d", errno);
   2315 		(void) close(fd);
   2316 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2317 	}
   2318 
   2319 	switch (paramType) {
   2320 		IMA_BOOL_VALUE *bp;
   2321 		IMA_MIN_MAX_VALUE *mp;
   2322 
   2323 		case MIN_MAX_PARAM:
   2324 			mp = (IMA_MIN_MAX_VALUE *)pProps;
   2325 
   2326 			mp->currentValueValid =
   2327 			    (pg.g_value.v_valid == B_TRUE) ?
   2328 			    IMA_TRUE : IMA_FALSE;
   2329 			mp->currentValue = pg.g_value.v_integer.i_current;
   2330 			mp->defaultValue = pg.g_value.v_integer.i_default;
   2331 			mp->minimumValue = pg.g_value.v_integer.i_min;
   2332 			mp->maximumValue = pg.g_value.v_integer.i_max;
   2333 			mp->incrementValue = pg.g_value.v_integer.i_incr;
   2334 			break;
   2335 
   2336 		case BOOL_PARAM:
   2337 			bp = (IMA_BOOL_VALUE *)pProps;
   2338 			bp->currentValueValid =
   2339 			    (pg.g_value.v_valid == B_TRUE) ?
   2340 			    IMA_TRUE : IMA_FALSE;
   2341 			bp->currentValue = pg.g_value.v_bool.b_current;
   2342 			bp->defaultValue = pg.g_value.v_bool.b_default;
   2343 			break;
   2344 
   2345 		default:
   2346 			break;
   2347 	}
   2348 
   2349 	(void) close(fd);
   2350 	return (IMA_STATUS_SUCCESS);
   2351 }
   2352 
   2353 /* A helper function to set iSCSI node parameters. */
   2354 static IMA_STATUS
   2355 setISCSINodeParameter(
   2356     int paramType,
   2357     IMA_OID *oid,
   2358     void *pProp,
   2359     uint32_t paramIndex
   2360 )
   2361 {
   2362 	int		    fd;
   2363 	iscsi_param_set_t   ps;
   2364 
   2365 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2366 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2367 		    ISCSI_DRIVER_DEVCTL, errno);
   2368 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2369 	}
   2370 
   2371 	(void) memset(&ps, 0, sizeof (iscsi_param_set_t));
   2372 	ps.s_vers = ISCSI_INTERFACE_VERSION;
   2373 	ps.s_oid = (uint32_t)oid->objectSequenceNumber;
   2374 	ps.s_param = paramIndex;
   2375 
   2376 	switch (paramType) {
   2377 		IMA_BOOL_VALUE *bp;
   2378 		IMA_MIN_MAX_VALUE *mp;
   2379 
   2380 		case MIN_MAX_PARAM:
   2381 			mp = (IMA_MIN_MAX_VALUE *)pProp;
   2382 			ps.s_value.v_integer = mp->currentValue;
   2383 			break;
   2384 		case BOOL_PARAM:
   2385 			bp = (IMA_BOOL_VALUE *)pProp;
   2386 			ps.s_value.v_bool =
   2387 			    (bp->currentValue == IMA_TRUE) ?
   2388 			    B_TRUE : B_FALSE;
   2389 			break;
   2390 
   2391 		default:
   2392 			break;
   2393 	}
   2394 
   2395 	if (ioctl(fd, ISCSI_PARAM_SET, &ps)) {
   2396 		int tmpErrno = errno;
   2397 		syslog(LOG_USER|LOG_DEBUG,
   2398 		    "ISCSI_PARAM_SET ioctl failed, errno: %d", errno);
   2399 		(void) close(fd);
   2400 		switch (tmpErrno) {
   2401 			case ENOTSUP :
   2402 				return (IMA_ERROR_NOT_SUPPORTED);
   2403 			default :
   2404 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2405 		}
   2406 	}
   2407 
   2408 	(void) close(fd);
   2409 	return (IMA_STATUS_SUCCESS);
   2410 }
   2411 
   2412 static int
   2413 prepare_discovery_entry(
   2414     IMA_TARGET_ADDRESS discoveryAddress,
   2415     entry_t *entry
   2416 )
   2417 {
   2418 	(void) memset(entry, 0, sizeof (entry_t));
   2419 	entry->e_vers = ISCSI_INTERFACE_VERSION;
   2420 	entry->e_oid = ISCSI_OID_NOTSET;
   2421 
   2422 	if (discoveryAddress.hostnameIpAddress.id.ipAddress.ipv4Address ==
   2423 	    IMA_FALSE) {
   2424 		bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress.ipAddress,
   2425 		    entry->e_u.u_in6.s6_addr,
   2426 		    sizeof (entry->e_u.u_in6.s6_addr));
   2427 		entry->e_insize = sizeof (struct in6_addr);
   2428 	} else {
   2429 		bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress.ipAddress,
   2430 		    &entry->e_u.u_in4.s_addr,
   2431 		    sizeof (entry->e_u.u_in4.s_addr));
   2432 		entry->e_insize = sizeof (struct in_addr);
   2433 	}
   2434 
   2435 	entry->e_port = discoveryAddress.portNumber;
   2436 	entry->e_tpgt = 0;
   2437 	return (DISC_ADDR_OK);
   2438 }
   2439 
   2440 static IMA_STATUS configure_discovery_method(
   2441     IMA_BOOL enable,
   2442     iSCSIDiscoveryMethod_t method
   2443 )
   2444 {
   2445 	int fd, status;
   2446 
   2447 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2448 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2449 		    ISCSI_DRIVER_DEVCTL, errno);
   2450 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2451 	}
   2452 
   2453 	if (enable == IMA_FALSE) {
   2454 		if (ioctl(fd, ISCSI_DISCOVERY_CLEAR, &method)) {
   2455 			status = errno;
   2456 			(void) close(fd);
   2457 			syslog(LOG_USER|LOG_DEBUG,
   2458 			    "ISCSI_DISCOVERY_CLEAR ioctl failed, errno: %d",
   2459 			    status);
   2460 			if (status == EBUSY) {
   2461 				return (IMA_ERROR_LU_IN_USE);
   2462 			} else {
   2463 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2464 			}
   2465 		}
   2466 
   2467 		(void) close(fd);
   2468 		return (IMA_STATUS_SUCCESS);
   2469 	} else {
   2470 		/* Set the discovery method */
   2471 		if (ioctl(fd, ISCSI_DISCOVERY_SET, &method)) {
   2472 			(void) close(fd);
   2473 			syslog(LOG_USER|LOG_DEBUG,
   2474 			    "ISCSI_DISCOVERY_SET ioctl failed, errno: %d",
   2475 			    errno);
   2476 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2477 		}
   2478 
   2479 		(void) close(fd);
   2480 		return (IMA_STATUS_SUCCESS);
   2481 	}
   2482 }
   2483 
   2484 static IMA_STATUS get_target_oid_list(
   2485     uint32_t targetListType,
   2486     IMA_OID_LIST **ppList)
   2487 {
   2488 	int		    fd;
   2489 	int		    i;
   2490 	int		    target_list_size;
   2491 	iscsi_target_list_t *idlp, tl_info;
   2492 
   2493 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2494 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2495 		    ISCSI_DRIVER_DEVCTL, errno);
   2496 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2497 	}
   2498 
   2499 	(void) memset(&tl_info, 0, sizeof (tl_info));
   2500 	tl_info.tl_vers = ISCSI_INTERFACE_VERSION;
   2501 	tl_info.tl_in_cnt = 0;
   2502 	tl_info.tl_tgt_list_type = targetListType;
   2503 
   2504 	/*
   2505 	 * Issue ioctl to obtain the number of targets.
   2506 	 */
   2507 	if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, &tl_info) != 0) {
   2508 		(void) close(fd);
   2509 		syslog(LOG_USER|LOG_DEBUG,
   2510 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
   2511 		    targetListType, errno);
   2512 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2513 	}
   2514 
   2515 	target_list_size = sizeof (iscsi_target_list_t);
   2516 	if (tl_info.tl_out_cnt > 1) {
   2517 		target_list_size += (sizeof (uint32_t) *
   2518 		    tl_info.tl_out_cnt - 1);
   2519 	}
   2520 
   2521 	idlp = (iscsi_target_list_t *)calloc(1, target_list_size);
   2522 	if (idlp == NULL) {
   2523 		(void) close(fd);
   2524 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   2525 	}
   2526 
   2527 	idlp->tl_vers = ISCSI_INTERFACE_VERSION;
   2528 	idlp->tl_in_cnt = tl_info.tl_out_cnt;
   2529 	idlp->tl_tgt_list_type = targetListType;
   2530 
   2531 	/* Issue the same ioctl again to obtain the OIDs. */
   2532 	if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) {
   2533 		free(idlp);
   2534 		(void) close(fd);
   2535 		syslog(LOG_USER|LOG_DEBUG,
   2536 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
   2537 		    targetListType, errno);
   2538 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2539 	}
   2540 
   2541 	*ppList = (IMA_OID_LIST *)calloc(1, sizeof (IMA_OID_LIST) +
   2542 	    idlp->tl_out_cnt * sizeof (IMA_OID));
   2543 	if (*ppList == NULL) {
   2544 		free(idlp);
   2545 		(void) close(fd);
   2546 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   2547 	}
   2548 	(*ppList)->oidCount = idlp->tl_out_cnt;
   2549 
   2550 	for (i = 0; i < idlp->tl_out_cnt; i++) {
   2551 
   2552 		if (targetListType == ISCSI_STATIC_TGT_OID_LIST)
   2553 			(*ppList)->oids[i].objectType =
   2554 			    IMA_OBJECT_TYPE_STATIC_DISCOVERY_TARGET;
   2555 		else
   2556 			(*ppList)->oids[i].objectType = IMA_OBJECT_TYPE_TARGET;
   2557 
   2558 		(*ppList)->oids[i].ownerId = pluginOwnerId;
   2559 		(*ppList)->oids[i].objectSequenceNumber = idlp->tl_oid_list[i];
   2560 	}
   2561 
   2562 	free(idlp);
   2563 	(void) close(fd);
   2564 	return (IMA_STATUS_SUCCESS);
   2565 }
   2566 
   2567 static IMA_STATUS get_target_lun_oid_list(
   2568     IMA_OID * targetOid,
   2569     iscsi_lun_list_t  **ppLunList)
   2570 {
   2571 	int			fd;
   2572 	iscsi_lun_list_t	*illp, ll_info;
   2573 	int			lun_list_size;
   2574 
   2575 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2576 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2577 		    ISCSI_DRIVER_DEVCTL, errno);
   2578 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2579 	}
   2580 
   2581 	(void) memset(&ll_info, 0, sizeof (ll_info));
   2582 	ll_info.ll_vers = ISCSI_INTERFACE_VERSION;
   2583 	if (targetOid == NULL) {
   2584 		/* get lun oid list for all targets */
   2585 		ll_info.ll_all_tgts = B_TRUE;
   2586 	} else {
   2587 		/* get lun oid list for single target */
   2588 		ll_info.ll_all_tgts = B_FALSE;
   2589 		ll_info.ll_tgt_oid = (uint32_t)targetOid->objectSequenceNumber;
   2590 	}
   2591 	ll_info.ll_in_cnt = 0;
   2592 
   2593 	/*
   2594 	 * Issue ioctl to obtain the number of target LUNs.
   2595 	 */
   2596 	if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, &ll_info) != 0) {
   2597 		(void) close(fd);
   2598 		syslog(LOG_USER|LOG_DEBUG,
   2599 		    "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", errno);
   2600 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2601 	}
   2602 
   2603 	lun_list_size = sizeof (iscsi_lun_list_t);
   2604 	if (ll_info.ll_out_cnt > 1) {
   2605 		lun_list_size += (sizeof (iscsi_if_lun_t) *
   2606 		    (ll_info.ll_out_cnt - 1));
   2607 	}
   2608 
   2609 	illp = (iscsi_lun_list_t *)calloc(1, lun_list_size);
   2610 	if (illp == NULL) {
   2611 		(void) close(fd);
   2612 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   2613 	}
   2614 	illp->ll_vers = ISCSI_INTERFACE_VERSION;
   2615 	illp->ll_all_tgts = ll_info.ll_all_tgts;
   2616 	illp->ll_tgt_oid = ll_info.ll_tgt_oid;
   2617 	illp->ll_in_cnt = ll_info.ll_out_cnt;
   2618 
   2619 	/* Issue the same ioctl again to get the target LUN list */
   2620 	if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) {
   2621 		free(illp);
   2622 		(void) close(fd);
   2623 		syslog(LOG_USER|LOG_DEBUG,
   2624 		    "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", errno);
   2625 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2626 	}
   2627 
   2628 	*ppLunList = illp;
   2629 
   2630 	(void) close(fd);
   2631 	return (IMA_STATUS_SUCCESS);
   2632 }
   2633 
   2634 
   2635 /* A helper function to set authentication method. */
   2636 static IMA_STATUS
   2637 setAuthMethods(
   2638     IMA_OID oid,
   2639     IMA_UINT *pMethodCount,
   2640     const IMA_AUTHMETHOD *pMethodList
   2641 )
   2642 {
   2643 	int fd;
   2644 	int i;
   2645 	iscsi_auth_props_t auth;
   2646 
   2647 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2648 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2649 		    ISCSI_DRIVER_DEVCTL, errno);
   2650 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2651 	}
   2652 	(void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
   2653 	auth.a_vers = ISCSI_INTERFACE_VERSION;
   2654 	auth.a_oid = (uint32_t)oid.objectSequenceNumber;
   2655 	/* First do a get because other data fields may exist */
   2656 	if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
   2657 		/* EMPTY */
   2658 		/* It is fine if there is no other data fields. */
   2659 	}
   2660 	auth.a_auth_method = authMethodNone;
   2661 
   2662 	for (i = 0; i < *pMethodCount; i++) {
   2663 		switch (pMethodList[i]) {
   2664 			case IMA_AUTHMETHOD_CHAP:
   2665 				auth.a_auth_method |= authMethodCHAP;
   2666 				break;
   2667 			default:
   2668 				break;
   2669 		}
   2670 	}
   2671 
   2672 	if (ioctl(fd, ISCSI_AUTH_SET, &auth) != 0) {
   2673 		syslog(LOG_USER|LOG_DEBUG,
   2674 		    "ISCSI_AUTH_SET failed, errno: %d", errno);
   2675 		(void) close(fd);
   2676 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2677 	}
   2678 
   2679 	(void) close(fd);
   2680 	return (IMA_STATUS_SUCCESS);
   2681 }
   2682 
   2683 /* A helper function to get authentication method. */
   2684 static IMA_STATUS
   2685 getAuthMethods(
   2686     IMA_OID oid,
   2687     IMA_UINT	*pMethodCount,
   2688     IMA_AUTHMETHOD *pMethodList
   2689 )
   2690 {
   2691 	int fd, i;
   2692 	iscsi_auth_props_t auth;
   2693 
   2694 	if (pMethodList == NULL) {
   2695 		*pMethodCount = 0;
   2696 		return (IMA_STATUS_SUCCESS);
   2697 	}
   2698 
   2699 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   2700 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   2701 		    ISCSI_DRIVER_DEVCTL, errno);
   2702 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2703 	}
   2704 
   2705 	(void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
   2706 	auth.a_vers = ISCSI_INTERFACE_VERSION;
   2707 	auth.a_oid = (uint32_t)oid.objectSequenceNumber;
   2708 
   2709 	if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
   2710 		syslog(LOG_USER|LOG_DEBUG,
   2711 		    "ISCSI_AUTH_GET failed, errno: %d", errno);
   2712 		(void) close(fd);
   2713 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   2714 	}
   2715 
   2716 	i = 0;
   2717 	if (auth.a_auth_method == IMA_AUTHMETHOD_NONE) {
   2718 		pMethodList[i++] = IMA_AUTHMETHOD_NONE;
   2719 	} else if (auth.a_auth_method & authMethodCHAP) {
   2720 		pMethodList[i++] = IMA_AUTHMETHOD_CHAP;
   2721 	}
   2722 	*pMethodCount = i;
   2723 
   2724 	(void) close(fd);
   2725 	return (IMA_STATUS_SUCCESS);
   2726 }
   2727 
   2728 IMA_API IMA_STATUS IMA_GetPhbaOidList(
   2729 		IMA_OID_LIST **ppList
   2730 )
   2731 {
   2732 	*ppList = (IMA_OID_LIST*)calloc(1, sizeof (IMA_OID_LIST));
   2733 	if (*ppList == NULL) {
   2734 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   2735 	}
   2736 	(*ppList)->oidCount = 0;
   2737 	return (IMA_STATUS_SUCCESS);
   2738 }
   2739 
   2740 /* ARGSUSED */
   2741 IMA_API IMA_STATUS IMA_GetPhbaProperties(
   2742 		IMA_OID phbaOid,
   2743 		IMA_PHBA_PROPERTIES *pProps
   2744 )
   2745 {
   2746 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2747 }
   2748 
   2749 /* ARGSUSED */
   2750 IMA_API IMA_STATUS IMA_GetPhbaStatus(
   2751 		IMA_OID phbaOid,
   2752 		IMA_PHBA_STATUS *pStatus
   2753 )
   2754 {
   2755 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2756 }
   2757 
   2758 /* ARGSUSED */
   2759 IMA_API IMA_STATUS IMA_GetPhbaDownloadProperties(
   2760 		IMA_OID phbaOid,
   2761 		IMA_PHBA_DOWNLOAD_PROPERTIES *pProps
   2762 )
   2763 {
   2764 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2765 }
   2766 
   2767 /* ARGSUSED */
   2768 IMA_API IMA_STATUS IMA_IsPhbaDownloadFile(
   2769 		IMA_OID phbaOid,
   2770 		const IMA_WCHAR *pFileName,
   2771 		IMA_PHBA_DOWNLOAD_IMAGE_PROPERTIES *pProps
   2772 )
   2773 {
   2774 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2775 }
   2776 
   2777 /* ARGSUSED */
   2778 IMA_API IMA_STATUS IMA_PhbaDownload(
   2779 		IMA_OID phbaOid,
   2780 		IMA_PHBA_DOWNLOAD_IMAGE_TYPE imageType,
   2781 		const IMA_WCHAR *pFileName
   2782 )
   2783 {
   2784 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2785 }
   2786 
   2787 IMA_API IMA_STATUS IMA_GetPnpOidList(
   2788 		IMA_OID pnpOid,
   2789 		IMA_OID_LIST **ppList
   2790 )
   2791 {
   2792 	/*
   2793 	 * Always return the same object ID for the pnp as the spec
   2794 	 * states that this function will always return a list of at least
   2795 	 * one element
   2796 	 */
   2797 	pnpOid.objectType = IMA_OBJECT_TYPE_PNP;
   2798 	pnpOid.ownerId = pluginOwnerId;
   2799 	pnpOid.objectSequenceNumber = ISCSI_INITIATOR_OID;
   2800 
   2801 	*ppList = (IMA_OID_LIST*)calloc(1, sizeof (IMA_OID_LIST) +
   2802 	    (1* sizeof (IMA_OID)));
   2803 
   2804 	if (*ppList == NULL) {
   2805 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   2806 	}
   2807 
   2808 	(*ppList)->oidCount = 1;
   2809 	(void) memcpy(&(*ppList)->oids[0], &pnpOid, sizeof (pnpOid));
   2810 	return (IMA_STATUS_SUCCESS);
   2811 }
   2812 
   2813 /* ARGSUSED */
   2814 IMA_API IMA_STATUS IMA_GetPnpProperties(
   2815 		IMA_OID pnpOid,
   2816 		IMA_PNP_PROPERTIES *pProps
   2817 )
   2818 {
   2819 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2820 }
   2821 
   2822 /* ARGSUSED */
   2823 IMA_API IMA_STATUS IMA_GetPnpStatistics(
   2824 		IMA_OID pnpOid,
   2825 		IMA_PNP_STATISTICS *pStats
   2826 )
   2827 {
   2828 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2829 }
   2830 
   2831 /* ARGSUSED */
   2832 IMA_API IMA_STATUS IMA_GetIpProperties(
   2833 		IMA_OID oid,
   2834 		IMA_IP_PROPERTIES *pProps
   2835 )
   2836 {
   2837 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2838 }
   2839 
   2840 /* ARGSUSED */
   2841 IMA_API IMA_STATUS IMA_SetDefaultGateway(
   2842 		IMA_OID oid,
   2843 		IMA_IP_ADDRESS defaultGateway
   2844 )
   2845 {
   2846 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2847 }
   2848 
   2849 /* ARGSUSED */
   2850 IMA_API IMA_STATUS IMA_SetDnsServerAddress(
   2851 		IMA_OID oid,
   2852 		const IMA_IP_ADDRESS *pPrimaryDnsServerAddress,
   2853 		const IMA_IP_ADDRESS *pAlternateDnsServerAddress
   2854 )
   2855 {
   2856 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2857 }
   2858 
   2859 /* ARGSUSED */
   2860 IMA_API IMA_STATUS IMA_SetSubnetMask(
   2861 		IMA_OID oid,
   2862 		IMA_IP_ADDRESS subnetMask
   2863 )
   2864 {
   2865 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2866 }
   2867 
   2868 /* ARGSUSED */
   2869 IMA_API IMA_STATUS IMA_SetIpConfigMethod(
   2870 		IMA_OID oid,
   2871 		IMA_BOOL enableDhcpIpConfiguration
   2872 )
   2873 {
   2874 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2875 }
   2876 
   2877 IMA_API IMA_STATUS IMA_RegisterForObjectPropertyChanges(
   2878 		IMA_OBJECT_PROPERTY_FN pClientFn
   2879 )
   2880 {
   2881 	pObjectPropertyCallback = pClientFn;
   2882 	return (IMA_STATUS_SUCCESS);
   2883 }
   2884 
   2885 /* ARGSUSED */
   2886 IMA_API IMA_STATUS IMA_DeregisterForObjectPropertyChanges(
   2887 		IMA_OBJECT_PROPERTY_FN pClientFn
   2888 )
   2889 {
   2890 	return (IMA_STATUS_SUCCESS);
   2891 }
   2892 
   2893 IMA_API IMA_STATUS IMA_RegisterForObjectVisibilityChanges(
   2894 		IMA_OBJECT_VISIBILITY_FN pClientFn
   2895 )
   2896 {
   2897 	pObjectVisibilityCallback = pClientFn;
   2898 	return (IMA_STATUS_SUCCESS);
   2899 }
   2900 
   2901 /* ARGSUSED */
   2902 IMA_API IMA_STATUS IMA_DeregisterForObjectVisibilityChanges(
   2903 		IMA_OBJECT_VISIBILITY_FN pClientFn
   2904 )
   2905 {
   2906 	return (IMA_STATUS_SUCCESS);
   2907 }
   2908 
   2909 /* ARGSUSED */
   2910 IMA_API IMA_STATUS IMA_GetNetworkPortStatus(
   2911 		IMA_OID portOid,
   2912 		IMA_NETWORK_PORT_STATUS *pStaus
   2913 )
   2914 {
   2915 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2916 }
   2917 
   2918 /* ARGSUSED */
   2919 IMA_API IMA_STATUS IMA_GetNetworkPortalOidList(
   2920 		IMA_OID pnpOid,
   2921 		IMA_OID_LIST **ppList
   2922 )
   2923 {
   2924 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2925 }
   2926 
   2927 /* ARGSUSED */
   2928 IMA_API IMA_STATUS IMA_GetNetworkPortalProperties(
   2929 		IMA_OID networkPortalOid,
   2930 		IMA_NETWORK_PORTAL_PROPERTIES *pProps
   2931 )
   2932 {
   2933 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2934 }
   2935 
   2936 /* ARGSUSED */
   2937 IMA_API IMA_STATUS IMA_SetNetworkPortalIpAddress(
   2938 		IMA_OID networkPortalOid,
   2939 		const IMA_IP_ADDRESS NewIpAddress
   2940 )
   2941 {
   2942 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   2943 }
   2944 
   2945 /* ARGSUSED */
   2946 IMA_API IMA_STATUS IMA_RemoveStaleData(
   2947 		IMA_OID lhbaOid
   2948 )
   2949 {
   2950 	return (IMA_ERROR_NOT_SUPPORTED);
   2951 }
   2952 
   2953 /* ARGSUSED */
   2954 IMA_API IMA_STATUS IMA_GetIpsecProperties(
   2955 		IMA_OID oid,
   2956 		IMA_IPSEC_PROPERTIES *pProps
   2957 )
   2958 {
   2959 	pProps->ipsecSupported = IMA_TRUE;
   2960 	pProps->implementedInHardware = IMA_FALSE;
   2961 	pProps->implementedInSoftware = IMA_TRUE;
   2962 
   2963 	return (IMA_STATUS_SUCCESS);
   2964 }
   2965 
   2966 /* ARGSUSED */
   2967 IMA_API IMA_STATUS IMA_GetLhbaProperties(
   2968 		IMA_OID lhbaOid,
   2969 		IMA_LHBA_PROPERTIES *pProps
   2970 )
   2971 {
   2972 
   2973 	if (pProps == NULL) {
   2974 		return (IMA_ERROR_INVALID_PARAMETER);
   2975 	}
   2976 
   2977 	if (lhbaObjectId.objectSequenceNumber != ISCSI_INITIATOR_OID) {
   2978 		return (IMA_ERROR_OBJECT_NOT_FOUND);
   2979 	}
   2980 
   2981 	(void) memset(pProps, 0, sizeof (IMA_LHBA_PROPERTIES));
   2982 	(void) mbstowcs(pProps->osDeviceName, OS_DEVICE_NAME,
   2983 	    OS_DEVICE_NAME_LEN);
   2984 	pProps->luExposingSupported = IMA_FALSE;
   2985 	pProps->isDestroyable = IMA_FALSE;
   2986 	pProps->staleDataRemovable = IMA_FALSE;
   2987 	pProps->staleDataSize = 0;
   2988 	pProps->initiatorAuthMethodsSettable = IMA_TRUE;
   2989 	pProps->targetAuthMethodsSettable = IMA_FALSE;
   2990 
   2991 	return (IMA_STATUS_SUCCESS);
   2992 }
   2993 
   2994 IMA_API IMA_STATUS IMA_GetLnpOidList(
   2995 		IMA_OID_LIST **ppList
   2996 )
   2997 {
   2998 	*ppList = (IMA_OID_LIST *) calloc(1, (sizeof (IMA_OID_LIST)));
   2999 	if (*ppList == NULL) {
   3000 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   3001 	}
   3002 	(*ppList)->oidCount = 0;
   3003 
   3004 	return (IMA_STATUS_SUCCESS);
   3005 }
   3006 
   3007 /* ARGSUSED */
   3008 IMA_API IMA_STATUS IMA_GetLnpProperties(
   3009 		IMA_OID lnpOid,
   3010 		IMA_LNP_PROPERTIES *pProps
   3011 )
   3012 {
   3013 	return (IMA_ERROR_OBJECT_NOT_FOUND);
   3014 }
   3015 
   3016 #define	IMA_DISK_DEVICE_NAME_PREFIX	"/dev/rdsk/"
   3017 #define	IMA_TAPE_DEVICE_NAME_PREFIX	"/dev/rmt/"
   3018 static int
   3019 get_lun_devlink(di_devlink_t link, void *osDeviceName)
   3020 {
   3021 	if ((strncmp(IMA_DISK_DEVICE_NAME_PREFIX, di_devlink_path(link),
   3022 	    strlen(IMA_DISK_DEVICE_NAME_PREFIX)) == 0) ||
   3023 	    (strncmp(IMA_TAPE_DEVICE_NAME_PREFIX, di_devlink_path(link),
   3024 	    strlen(IMA_TAPE_DEVICE_NAME_PREFIX)) == 0)) {
   3025 		(void) mbstowcs((wchar_t *)osDeviceName, di_devlink_path(link),
   3026 		    MAXPATHLEN);
   3027 		return (DI_WALK_TERMINATE);
   3028 	}
   3029 
   3030 	return (DI_WALK_CONTINUE);
   3031 }
   3032 
   3033 /* ARGSUSED */
   3034 IMA_API IMA_STATUS IMA_GetPluginProperties(
   3035 	IMA_OID pluginOid,
   3036 	IMA_PLUGIN_PROPERTIES *pProps
   3037 )
   3038 {
   3039 	pProps->supportedImaVersion = 1;
   3040 	libSwprintf(pProps->vendor, L"%ls", LIBRARY_PROPERTY_VENDOR);
   3041 	libSwprintf(pProps->implementationVersion, L"%ls",
   3042 	    LIBRARY_PROPERTY_IMPLEMENTATION_VERSION);
   3043 	libSwprintf(pProps->fileName, L"%ls", LIBRARY_FILE_NAME);
   3044 	GetBuildTime(&(pProps->buildTime));
   3045 	pProps->lhbasCanBeCreatedAndDestroyed = IMA_FALSE;
   3046 	return (IMA_STATUS_SUCCESS);
   3047 }
   3048 
   3049 IMA_STATUS getDiscoveryAddressPropertiesList(
   3050     SUN_IMA_DISC_ADDR_PROP_LIST **ppList
   3051 )
   3052 {
   3053 	int		    fd;
   3054 	int		    i;
   3055 	int		    discovery_addr_list_size;
   3056 	iscsi_addr_list_t   *ialp, al_info;
   3057 
   3058 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   3059 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   3060 		    ISCSI_DRIVER_DEVCTL, errno);
   3061 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3062 	}
   3063 
   3064 	(void) memset(&al_info, 0, sizeof (al_info));
   3065 	al_info.al_vers = ISCSI_INTERFACE_VERSION;
   3066 	al_info.al_in_cnt = 0;
   3067 
   3068 	/*
   3069 	 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl to obtain the number of
   3070 	 * discovery addresses.
   3071 	 */
   3072 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
   3073 		(void) close(fd);
   3074 		syslog(LOG_USER|LOG_DEBUG,
   3075 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno: %d",
   3076 		    errno);
   3077 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3078 	}
   3079 
   3080 	discovery_addr_list_size = sizeof (iscsi_addr_list_t);
   3081 	if (al_info.al_out_cnt > 1) {
   3082 		discovery_addr_list_size += (sizeof (iscsi_addr_t) *
   3083 		    al_info.al_out_cnt - 1);
   3084 	}
   3085 
   3086 	ialp = (iscsi_addr_list_t *)calloc(1, discovery_addr_list_size);
   3087 	if (ialp == NULL) {
   3088 		(void) close(fd);
   3089 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   3090 	}
   3091 	ialp->al_vers = ISCSI_INTERFACE_VERSION;
   3092 	ialp->al_in_cnt = al_info.al_out_cnt;
   3093 
   3094 	/*
   3095 	 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl again to obtain the
   3096 	 * discovery addresses.
   3097 	 */
   3098 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, ialp) != 0) {
   3099 		free(ialp);
   3100 		(void) close(fd);
   3101 		syslog(LOG_USER|LOG_DEBUG,
   3102 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno: %d",
   3103 		    errno);
   3104 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3105 	}
   3106 
   3107 	*ppList = (SUN_IMA_DISC_ADDR_PROP_LIST *)
   3108 	    calloc(1, sizeof (SUN_IMA_DISC_ADDR_PROP_LIST) +
   3109 	    ialp->al_out_cnt * sizeof (IMA_DISCOVERY_ADDRESS_PROPERTIES));
   3110 
   3111 	if (*ppList == NULL) {
   3112 		free(ialp);
   3113 		(void) close(fd);
   3114 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   3115 	}
   3116 	(*ppList)->discAddrCount = ialp->al_out_cnt;
   3117 
   3118 	for (i = 0; i < ialp->al_out_cnt; i++) {
   3119 		if (ialp->al_addrs[i].a_addr.i_insize ==
   3120 		    sizeof (struct in_addr)) {
   3121 			(*ppList)->props[i].discoveryAddress.hostnameIpAddress.
   3122 			id.ipAddress.ipv4Address = IMA_TRUE;
   3123 		} else if (ialp->al_addrs[i].a_addr.i_insize ==
   3124 		    sizeof (struct in6_addr)) {
   3125 			(*ppList)->props[i].discoveryAddress.
   3126 			hostnameIpAddress.id.ipAddress.ipv4Address = IMA_FALSE;
   3127 		} else {
   3128 			/* Should not happen */
   3129 			syslog(LOG_USER|LOG_DEBUG,
   3130 			"ISCSI_STATIC_GET returned bad address");
   3131 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3132 		}
   3133 
   3134 		bcopy(&ialp->al_addrs[i].a_addr.i_addr,	(*ppList)->props[i].
   3135 		    discoveryAddress.hostnameIpAddress.id.ipAddress.ipAddress,
   3136 		    sizeof ((*ppList)->props[i].discoveryAddress.
   3137 		    hostnameIpAddress.id.ipAddress.ipAddress));
   3138 
   3139 		(*ppList)->props[i].discoveryAddress.portNumber =
   3140 		    ialp->al_addrs[i].a_port;
   3141 	}
   3142 
   3143 	free(ialp);
   3144 	(void) close(fd);
   3145 	return (IMA_STATUS_SUCCESS);
   3146 }
   3147 
   3148 
   3149 /* ARGSUSED */
   3150 IMA_STATUS sendTargets(
   3151     IMA_TARGET_ADDRESS address,
   3152     SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList
   3153 )
   3154 {
   3155 	char	*colonPos;
   3156 	char	discAddrStr[SUN_IMA_IP_ADDRESS_LEN];
   3157 	int	fd;
   3158 	int	ctr;
   3159 	int	stl_sz;
   3160 	iscsi_sendtgts_list_t	*stl_hdr = NULL;
   3161 	IMA_BOOL		retry = IMA_TRUE;
   3162 
   3163 #define	SENDTGTS_DEFAULT_NUM_TARGETS	10
   3164 
   3165 	stl_sz = sizeof (*stl_hdr) + ((SENDTGTS_DEFAULT_NUM_TARGETS - 1) *
   3166 	    sizeof (iscsi_sendtgts_entry_t));
   3167 	stl_hdr = (iscsi_sendtgts_list_t *)calloc(1, stl_sz);
   3168 	if (stl_hdr == NULL) {
   3169 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   3170 	}
   3171 	stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION;
   3172 	stl_hdr->stl_in_cnt = SENDTGTS_DEFAULT_NUM_TARGETS;
   3173 
   3174 	colonPos = strchr(discAddrStr, ':');
   3175 	if (colonPos == NULL) {
   3176 		/* IPv4 */
   3177 		stl_hdr->stl_entry.e_insize = sizeof (struct in_addr);
   3178 	} else {
   3179 		/* IPv6 */
   3180 		stl_hdr->stl_entry.e_insize = sizeof (struct in6_addr);
   3181 	}
   3182 
   3183 
   3184 	bcopy(address.hostnameIpAddress.id.ipAddress.ipAddress,
   3185 	    &stl_hdr->stl_entry.e_u,
   3186 	    sizeof (address.hostnameIpAddress.id.ipAddress.ipAddress));
   3187 	stl_hdr->stl_entry.e_port = address.portNumber;
   3188 
   3189 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   3190 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   3191 		    ISCSI_DRIVER_DEVCTL, errno);
   3192 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3193 	}
   3194 
   3195 retry_sendtgts:
   3196 	/*
   3197 	 * Issue ioctl to obtain the SendTargets list
   3198 	 */
   3199 	if (ioctl(fd, ISCSI_SENDTGTS_GET, stl_hdr) != 0) {
   3200 		syslog(LOG_USER|LOG_DEBUG,
   3201 		    "ISCSI_SENDTGTS_GET ioctl failed, errno: %d", errno);
   3202 		(void) close(fd);
   3203 		free(stl_hdr);
   3204 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3205 	}
   3206 
   3207 	/* check if all targets received */
   3208 	if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) {
   3209 		if (retry == IMA_TRUE) {
   3210 			stl_sz = sizeof (*stl_hdr) +
   3211 			    ((stl_hdr->stl_out_cnt - 1) *
   3212 			    sizeof (iscsi_sendtgts_entry_t));
   3213 			stl_hdr = (iscsi_sendtgts_list_t *)
   3214 			    realloc(stl_hdr, stl_sz);
   3215 			if (stl_hdr == NULL) {
   3216 				(void) close(fd);
   3217 				return (IMA_ERROR_INSUFFICIENT_MEMORY);
   3218 			}
   3219 			stl_hdr->stl_in_cnt = stl_hdr->stl_out_cnt;
   3220 			retry = IMA_FALSE;
   3221 			goto retry_sendtgts;
   3222 		} else {
   3223 			/*
   3224 			 * don't retry after 2 attempts.  The target list
   3225 			 * shouldn't continue to growing. Justs continue
   3226 			 * on and display what was found.
   3227 			 */
   3228 			syslog(LOG_USER|LOG_DEBUG,
   3229 			    "ISCSI_SENDTGTS_GET overflow: "
   3230 			    "failed to obtain all targets");
   3231 			stl_hdr->stl_out_cnt = stl_hdr->stl_in_cnt;
   3232 		}
   3233 	}
   3234 
   3235 	(void) close(fd);
   3236 
   3237 	/* allocate for caller return buffer */
   3238 	*ppList = (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *)calloc(1,
   3239 	    sizeof (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES) +
   3240 	    stl_hdr->stl_out_cnt * sizeof (SUN_IMA_DISC_ADDRESS_KEY));
   3241 	if (*ppList == NULL) {
   3242 		free(stl_hdr);
   3243 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
   3244 	}
   3245 
   3246 	(*ppList)->keyCount = stl_hdr->stl_out_cnt;
   3247 
   3248 	for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) {
   3249 		(void) mbstowcs((*ppList)->keys[ctr].name,
   3250 		    (char *)stl_hdr->stl_list[ctr].ste_name,
   3251 		    IMA_NODE_NAME_LEN);
   3252 
   3253 		(*ppList)->keys[ctr].tpgt = stl_hdr->stl_list[ctr].ste_tpgt;
   3254 
   3255 		(*ppList)->keys[ctr].address.portNumber =
   3256 		    stl_hdr->stl_list[ctr].ste_ipaddr.a_port;
   3257 
   3258 		if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize ==
   3259 		    sizeof (struct in_addr)) {
   3260 			(*ppList)->keys[ctr].address.ipAddress.ipv4Address =
   3261 			    IMA_TRUE;
   3262 		} else if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize ==
   3263 		    sizeof (struct in6_addr)) {
   3264 			(*ppList)->keys[ctr].address.ipAddress.ipv4Address =
   3265 			    IMA_FALSE;
   3266 		} else {
   3267 			free(stl_hdr);
   3268 			syslog(LOG_USER|LOG_DEBUG,
   3269 			"ISCSI_STATIC_GET returned bad address");
   3270 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3271 		}
   3272 
   3273 
   3274 		(void) memcpy(&(*ppList)->keys[ctr].address.ipAddress.ipAddress,
   3275 		    &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr),
   3276 		    stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize);
   3277 	}
   3278 	free(stl_hdr);
   3279 
   3280 	return (IMA_STATUS_SUCCESS);
   3281 }
   3282 
   3283 IMA_API IMA_STATUS SUN_IMA_GetTunableProperties(
   3284 	IMA_OID oid,
   3285 	ISCSI_TUNABLE_PARAM *param)
   3286 {
   3287 	int fd;
   3288 	iscsi_tunable_object_t pg;
   3289 
   3290 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   3291 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   3292 		    ISCSI_DRIVER_DEVCTL, errno);
   3293 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3294 	}
   3295 	(void) memset(&pg, 0, sizeof (iscsi_tunable_object_t));
   3296 	pg.t_param = param->tunable_objectType;
   3297 	pg.t_oid = (uint32_t)oid.objectSequenceNumber;
   3298 	if (ioctl(fd, ISCSI_TUNABLE_PARAM_GET, &pg) == -1) {
   3299 		syslog(LOG_USER|LOG_DEBUG,
   3300 		    "ISCSI_TUNABLE_PARAM_GET ioctl failed, errno: %d", errno);
   3301 		(void) close(fd);
   3302 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3303 	} else {
   3304 		long long value;
   3305 		char tmp[MAX_LONG_LONG_STRING_LEN], *ptr = NULL;
   3306 		if (pg.t_set == B_FALSE) {
   3307 			/* default value */
   3308 			(void) close(fd);
   3309 			return (IMA_STATUS_SUCCESS);
   3310 		}
   3311 		value = (long long)pg.t_value.v_integer;
   3312 		ptr = lltostr(value, &tmp[MAX_LONG_LONG_STRING_LEN -1]);
   3313 		if ((ptr != NULL) && (ptr != tmp)) {
   3314 			tmp[MAX_LONG_LONG_STRING_LEN - 1] = '\0';
   3315 		} else {
   3316 			(void) close(fd);
   3317 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3318 		}
   3319 		switch (param->tunable_objectType) {
   3320 			case ISCSI_RX_TIMEOUT_VALUE:
   3321 				(void) strlcpy(param->tunable_objectValue,
   3322 				    ptr, strlen(ptr) + 1);
   3323 				break;
   3324 			case ISCSI_CONN_DEFAULT_LOGIN_MAX:
   3325 				(void) strlcpy(param->tunable_objectValue,
   3326 				    ptr, strlen(ptr) + 1);
   3327 				break;
   3328 			case ISCSI_LOGIN_POLLING_DELAY:
   3329 				(void) strlcpy(param->tunable_objectValue,
   3330 				    ptr, strlen(ptr) + 1);
   3331 				break;
   3332 			default:
   3333 				break;
   3334 		}
   3335 	}
   3336 	(void) close(fd);
   3337 	return (IMA_STATUS_SUCCESS);
   3338 }
   3339 
   3340 IMA_API IMA_STATUS SUN_IMA_SetTunableProperties(
   3341 	IMA_OID oid,
   3342 	ISCSI_TUNABLE_PARAM *param)
   3343 {
   3344 	int fd;
   3345 	iscsi_tunable_object_t	ps;
   3346 
   3347 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
   3348 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
   3349 		    ISCSI_DRIVER_DEVCTL, errno);
   3350 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3351 	}
   3352 
   3353 	(void) memset(&ps, 0, sizeof (iscsi_tunable_object_t));
   3354 	ps.t_oid = oid.objectSequenceNumber;
   3355 	ps.t_param = param->tunable_objectType;
   3356 	switch (param->tunable_objectType) {
   3357 		long tmp;
   3358 		case ISCSI_RX_TIMEOUT_VALUE:
   3359 		case ISCSI_CONN_DEFAULT_LOGIN_MAX:
   3360 		case ISCSI_LOGIN_POLLING_DELAY:
   3361 			tmp = strtol(param->tunable_objectValue,
   3362 			    NULL, 10);
   3363 			if (((tmp == 0) && (errno == EINVAL)) ||
   3364 			    ((tmp == LONG_MAX) && (errno == ERANGE)) ||
   3365 			    ((tmp == LONG_MIN) && (errno == ERANGE))) {
   3366 				(void) close(fd);
   3367 				return (IMA_ERROR_INVALID_PARAMETER);
   3368 			}
   3369 			ps.t_value.v_integer = (uint32_t)tmp;
   3370 			break;
   3371 		default:
   3372 			break;
   3373 	}
   3374 	if (ioctl(fd, ISCSI_TUNABLE_PARAM_SET, &ps)) {
   3375 		int tmpErrno = errno;
   3376 		syslog(LOG_USER|LOG_DEBUG,
   3377 		    "ISCSI_TUNABLE_PARAM_SET ioctl failed, errno: %d", errno);
   3378 		(void) close(fd);
   3379 		switch (tmpErrno) {
   3380 			case ENOTSUP :
   3381 				return (IMA_ERROR_NOT_SUPPORTED);
   3382 			default:
   3383 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
   3384 		}
   3385 	}
   3386 	(void) close(fd);
   3387 	return (IMA_STATUS_SUCCESS);
   3388 }
   3389