Home | History | Annotate | Download | only in src
      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 src/sun_nws/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 src/sun_nws/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 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 #pragma ident	"@(#)ima.c	1.7	08/05/23 SMI"
     26 
     27 #include <arpa/inet.h>
     28 #include <sys/socket.h>
     29 #include <sys/types.h>
     30 #include <stdarg.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <strings.h>
     34 #include <unistd.h>
     35 #include <syslog.h>
     36 #include <errno.h>
     37 #include <wchar.h>
     38 #include <widec.h>
     39 #include <libsysevent.h>
     40 #include <sys/nvpair.h>
     41 #include <fcntl.h>
     42 #include <stdio.h>
     43 #include <time.h>
     44 #include <libdevinfo.h>
     45 #include <iscsi_if.h>
     46 #include <iscsi_protocol.h>
     47 #include <ima.h>
     48 
     49 #define	LIBRARY_PROPERTY_IMPLEMENTATION_VERSION	L"1.0.0"
     50 #define	LIBRARY_PROPERTY_VENDOR			L"Sun Microsystems, Inc."
     51 #define	OS_DEVICE_NAME 				"/devices/iscsi"
     52 #define	LIBRARY_FILE_NAME			L"libsun_ima.so"
     53 
     54 #define	OS_DEVICE_NAME_LEN		256
     55 #define	INQUIRY_CMD			0x12
     56 #define	GETCAPACITY_CMD  		0x25
     57 #define	INQUIRY_CMDLEN			6
     58 #define	INQUIRY_REPLY_LEN		96
     59 #define	USCSI_TIMEOUT_IN_SEC		10
     60 #define	MAX_AUTHMETHODS			10
     61 #define	NUM_SUPPORTED_AUTH_METHODS	2
     62 #define	SUN_IMA_MAX_DIGEST_ALGORITHMS	2	/* NONE and CRC 32 */
     63 #define	SUN_IMA_IP_ADDRESS_LEN		256
     64 #define	SUN_IMA_IP_PORT_LEN		64
     65 #define	SUN_IMA_MAX_RADIUS_SECRET_LEN	128
     66 
     67 /* Forward declaration */
     68 #define	BOOL_PARAM			1
     69 #define	MIN_MAX_PARAM			2
     70 
     71 /* OK */
     72 #define	DISC_ADDR_OK			0
     73 /* Incorrect IP address */
     74 #define	DISC_ADDR_INTEGRITY_ERROR   	1
     75 /* Error converting text IP address to numeric binary form */
     76 #define	DISC_ADDR_IP_CONV_ERROR		2
     77 
     78 /* Currently not defined in  IMA_TARGET_DISCOVERY_METHOD enum */
     79 #define	IMA_TARGET_DISCOVERY_METHOD_UNKNOWN  0
     80 
     81 static IMA_OID		lhbaObjectId;
     82 static IMA_UINT32	pluginOwnerId;
     83 static sysevent_handle_t *shp;
     84 
     85 
     86 
     87 /*
     88  * Custom struct to allow tgpt to be specified.
     89  */
     90 typedef struct _SUN_IMA_DISC_ADDRESS_KEY
     91 {
     92 	IMA_NODE_NAME name;
     93 	IMA_ADDRESS_KEY	address;
     94 	IMA_UINT16 tpgt;
     95 } SUN_IMA_DISC_ADDRESS_KEY;
     96 
     97 /*
     98  * Custom struct to allow tgpt to be specified.
     99  */
    100 typedef struct _SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES
    101 {
    102 	IMA_UINT keyCount;
    103 	SUN_IMA_DISC_ADDRESS_KEY keys[1];
    104 } SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES;
    105 
    106 /*
    107  * Custom struct to allow tgpt to be specified.
    108  */
    109 typedef struct _SUN_IMA_DISC_ADDR_PROP_LIST
    110 {
    111 	IMA_UINT discAddrCount;
    112 	IMA_DISCOVERY_ADDRESS_PROPERTIES props[1];
    113 } SUN_IMA_DISC_ADDR_PROP_LIST;
    114 
    115 
    116 static IMA_OBJECT_VISIBILITY_FN pObjectVisibilityCallback = NULL;
    117 static IMA_OBJECT_PROPERTY_FN pObjectPropertyCallback = NULL;
    118 
    119 static IMA_STATUS getISCSINodeParameter(int paramType, IMA_OID *oid,
    120     void *pProps, uint32_t paramIndex);
    121 static IMA_STATUS setISCSINodeParameter(int paramType, IMA_OID *oid,
    122     void *pProps, uint32_t paramIndex);
    123 static IMA_STATUS setAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount,
    124     const IMA_AUTHMETHOD *pMethodList);
    125 static IMA_STATUS getAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount,
    126     IMA_AUTHMETHOD *pMethodList);
    127 
    128 static int prepare_discovery_entry(IMA_TARGET_ADDRESS discoveryAddress,
    129     entry_t *entry);
    130 static IMA_STATUS configure_discovery_method(IMA_BOOL enable,
    131     iSCSIDiscoveryMethod_t method);
    132 static IMA_STATUS get_target_oid_list(uint32_t targetListType,
    133     IMA_OID_LIST **ppList);
    134 static IMA_STATUS get_target_lun_oid_list(IMA_OID * targetOid,
    135 		iscsi_lun_list_t  **ppLunList);
    136 static int get_lun_devlink(di_devlink_t link, void *osDeviceName);
    137 static IMA_STATUS getDiscoveryAddressPropertiesList(
    138 	SUN_IMA_DISC_ADDR_PROP_LIST **ppList
    139 );
    140 static IMA_STATUS sendTargets(IMA_TARGET_ADDRESS address,
    141     SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList
    142 );
    143 
    144 static IMA_STATUS getSupportedAuthMethods(IMA_OID lhbaOid,
    145     IMA_BOOL getSettableMethods, IMA_UINT *pMethodCount,
    146     IMA_AUTHMETHOD *pMethodList);
    147 static IMA_STATUS getLuProperties(IMA_OID luId, IMA_LU_PROPERTIES *pProps);
    148 static IMA_STATUS getTargetProperties(IMA_OID targetId,
    149     IMA_TARGET_PROPERTIES *pProps);
    150 
    151 void InitLibrary();
    152 
    153 static void libSwprintf(wchar_t *wcs, const wchar_t *lpszFormat, ...)
    154 {
    155 	va_list args;
    156 	va_start(args, lpszFormat);
    157 	vswprintf(wcs, OS_DEVICE_NAME_LEN - 1, lpszFormat, args);
    158 	va_end(args);
    159 }
    160 
    161 static void
    162 sysevent_handler(sysevent_t *ev)
    163 {
    164 	IMA_OID tmpOid;
    165 	IMA_BOOL becomingVisible = IMA_FALSE;
    166 	IMA_UINT i;
    167 
    168 	const char *visibility_subclasses[] = {
    169 		ESC_ISCSI_STATIC_START,
    170 		ESC_ISCSI_STATIC_END,
    171 		ESC_ISCSI_SEND_TARGETS_START,
    172 		ESC_ISCSI_SEND_TARGETS_END,
    173 		ESC_ISCSI_SLP_START,
    174 		ESC_ISCSI_SLP_END,
    175 		ESC_ISCSI_ISNS_START,
    176 		ESC_ISCSI_ISNS_END,
    177 		NULL
    178 	};
    179 
    180 	tmpOid.ownerId = pluginOwnerId;
    181 	tmpOid.objectType = IMA_OBJECT_TYPE_TARGET;
    182 	tmpOid.objectSequenceNumber = 0;
    183 
    184 	/* Make sure our event class matches what we are looking for */
    185 	if (strncmp(EC_ISCSI, sysevent_get_class_name(ev),
    186 	    strlen(EC_ISCSI)) != 0) {
    187 		return;
    188 	}
    189 
    190 
    191 	/* Check for object property changes */
    192 	if ((strncmp(ESC_ISCSI_PROP_CHANGE,
    193 	    sysevent_get_subclass_name(ev),
    194 	    strlen(ESC_ISCSI_PROP_CHANGE)) == 0)) {
    195 		if (pObjectPropertyCallback != NULL)
    196 			pObjectPropertyCallback(tmpOid);
    197 	} else {
    198 		i = 0;
    199 		while (visibility_subclasses[i] != NULL) {
    200 			if ((strncmp(visibility_subclasses[i],
    201 			    sysevent_get_subclass_name(ev),
    202 			    strlen(visibility_subclasses[i])) == 0) &&
    203 			    pObjectVisibilityCallback != NULL) {
    204 				becomingVisible = IMA_TRUE;
    205 				pObjectVisibilityCallback(becomingVisible,
    206 				    tmpOid);
    207 			}
    208 			i++;
    209 		}
    210 	}
    211 }
    212 
    213 IMA_STATUS init_sysevents() {
    214 	const char *subclass_list[] = {
    215 		ESC_ISCSI_STATIC_START,
    216 		ESC_ISCSI_STATIC_END,
    217 		ESC_ISCSI_SEND_TARGETS_START,
    218 		ESC_ISCSI_SEND_TARGETS_END,
    219 		ESC_ISCSI_SLP_START,
    220 		ESC_ISCSI_SLP_END,
    221 		ESC_ISCSI_ISNS_START,
    222 		ESC_ISCSI_ISNS_END,
    223 		ESC_ISCSI_PROP_CHANGE,
    224 	};
    225 
    226 	/* Bind event handler and create subscriber handle */
    227 	shp = sysevent_bind_handle(sysevent_handler);
    228 	if (shp == NULL) {
    229 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    230 	}
    231 
    232 	if (sysevent_subscribe_event(shp, EC_ISCSI, subclass_list, 9) != 0) {
    233 		sysevent_unbind_handle(shp);
    234 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    235 	}
    236 	return (IMA_STATUS_SUCCESS);
    237 }
    238 
    239 IMA_STATUS Initialize(IMA_UINT32 pluginOid) {
    240 	pluginOwnerId = pluginOid;
    241 	return (init_sysevents());
    242 }
    243 
    244 void Terminate() {
    245 	if (shp != NULL) {
    246 		sysevent_unsubscribe_event(shp, EC_ISCSI);
    247 	}
    248 
    249 }
    250 
    251 void InitLibrary() {
    252 }
    253 
    254 static void GetBuildTime(IMA_DATETIME* pdatetime)
    255 {
    256 	memset(pdatetime, 0, sizeof (IMA_DATETIME));
    257 }
    258 
    259 /*ARGSUSED*/
    260 IMA_API IMA_STATUS IMA_GetNodeProperties(
    261 	IMA_OID nodeOid,
    262 	IMA_NODE_PROPERTIES *pProps
    263 )
    264 {
    265 	int fd;
    266 	iscsi_param_get_t pg;
    267 
    268 	pProps->runningInInitiatorMode = IMA_TRUE;
    269 	pProps->runningInTargetMode = IMA_FALSE;
    270 	pProps->nameAndAliasSettable = IMA_FALSE;
    271 
    272 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    273 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    274 		    ISCSI_DRIVER_DEVCTL, errno);
    275 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    276 	}
    277 
    278 	memset(&pg, 0, sizeof (iscsi_param_get_t));
    279 	pg.g_vers = ISCSI_INTERFACE_VERSION;
    280 	pg.g_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME;
    281 
    282 	if (ioctl(fd, ISCSI_PARAM_GET, &pg) == -1) {
    283 		pProps->nameValid = IMA_FALSE;
    284 	} else {
    285 		if (strlen((char *)pg.g_value.v_name) > 0) {
    286 			mbstowcs(pProps->name,
    287 			    (char *)pg.g_value.v_name,
    288 			    IMA_NODE_NAME_LEN);
    289 			pProps->nameValid = IMA_TRUE;
    290 		} else {
    291 			pProps->nameValid = IMA_FALSE;
    292 		}
    293 	}
    294 
    295 	memset(&pg, 0, sizeof (iscsi_param_get_t));
    296 	pg.g_vers = ISCSI_INTERFACE_VERSION;
    297 	pg.g_param = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS;
    298 	memset(pProps->alias, 0,
    299 	    sizeof (IMA_WCHAR) * IMA_NODE_ALIAS_LEN);
    300 	if (ioctl(fd, ISCSI_PARAM_GET, &pg) == -1) {
    301 		pProps->aliasValid = IMA_FALSE;
    302 	} else {
    303 		if (strlen((char *)pg.g_value.v_name) > 0) {
    304 			mbstowcs(pProps->alias,
    305 			    (char *)pg.g_value.v_name,
    306 			    IMA_NODE_ALIAS_LEN);
    307 			pProps->aliasValid = IMA_TRUE;
    308 		}
    309 	}
    310 
    311 	close(fd);
    312 	return (IMA_STATUS_SUCCESS);
    313 }
    314 
    315 IMA_API IMA_STATUS IMA_SetNodeName(
    316 	IMA_OID nodeOid,
    317 	const IMA_NODE_NAME newName
    318 )
    319 {
    320 	int fd;
    321 	iscsi_param_set_t ps;
    322 
    323 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    324 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    325 		    ISCSI_DRIVER_DEVCTL, errno);
    326 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    327 	}
    328 
    329 	memset(&ps, 0, sizeof (iscsi_param_set_t));
    330 	ps.s_oid = nodeOid.objectSequenceNumber;
    331 	ps.s_vers = ISCSI_INTERFACE_VERSION;
    332 	ps.s_param = ISCSI_LOGIN_PARAM_INITIATOR_NAME;
    333 	wcstombs((char *)ps.s_value.v_name, newName, ISCSI_MAX_NAME_LEN);
    334 	if (ioctl(fd, ISCSI_INIT_NODE_NAME_SET, &ps)) {
    335 		syslog(LOG_USER|LOG_DEBUG,
    336 		    "ISCSI_PARAM_SET ioctl failed, errno: %d", errno);
    337 		close(fd);
    338 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    339 	}
    340 
    341 	close(fd);
    342 	return (IMA_STATUS_SUCCESS);
    343 }
    344 
    345 IMA_API IMA_STATUS IMA_SetNodeAlias(
    346 	IMA_OID nodeOid,
    347 	const IMA_NODE_ALIAS newAlias
    348 )
    349 {
    350 	int fd;
    351 	iscsi_param_set_t ps;
    352 
    353 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    354 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    355 		    ISCSI_DRIVER_DEVCTL, errno);
    356 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    357 	}
    358 
    359 	memset(&ps, 0, sizeof (iscsi_param_set_t));
    360 	ps.s_oid = nodeOid.objectSequenceNumber;
    361 	ps.s_vers = ISCSI_INTERFACE_VERSION;
    362 	ps.s_param = ISCSI_LOGIN_PARAM_INITIATOR_ALIAS;
    363 
    364 	/* newAlias = NULL specifies that the alias should be deleted. */
    365 	if (newAlias != NULL)
    366 		wcstombs((char *)ps.s_value.v_name, newAlias,
    367 		    ISCSI_MAX_NAME_LEN);
    368 	else
    369 		wcstombs((char *)ps.s_value.v_name, L"", ISCSI_MAX_NAME_LEN);
    370 
    371 	if (ioctl(fd, ISCSI_PARAM_SET, &ps)) {
    372 		syslog(LOG_USER|LOG_DEBUG,
    373 		    "ISCSI_PARAM_SET ioctl failed, errno: %d", errno);
    374 		close(fd);
    375 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    376 	}
    377 
    378 	close(fd);
    379 	return (IMA_STATUS_SUCCESS);
    380 }
    381 
    382 
    383 IMA_API IMA_STATUS IMA_GetLhbaOidList(
    384 	IMA_OID_LIST **ppList
    385 )
    386 {
    387 	/* Always return the same object ID for the lhba */
    388 	lhbaObjectId.objectType = IMA_OBJECT_TYPE_LHBA;
    389 	lhbaObjectId.ownerId = pluginOwnerId;
    390 	lhbaObjectId.objectSequenceNumber = ISCSI_INITIATOR_OID;
    391 
    392 	*ppList = (IMA_OID_LIST*)calloc(1, sizeof (IMA_OID_LIST));
    393 	if (*ppList == NULL) {
    394 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    395 	}
    396 
    397 	(*ppList)->oidCount = 1;
    398 	memcpy(&(*ppList)->oids[0], &lhbaObjectId, sizeof (lhbaObjectId));
    399 	return (IMA_STATUS_SUCCESS);
    400 }
    401 
    402 
    403 /*
    404  * Get the discovery properties of the LHBA
    405  */
    406 /*ARGSUSED*/
    407 IMA_API IMA_STATUS IMA_GetDiscoveryProperties(
    408 	IMA_OID oid,
    409 	IMA_DISCOVERY_PROPERTIES *pProps
    410 )
    411 {
    412 	int fd;
    413 	iSCSIDiscoveryProperties_t discoveryProps;
    414 
    415 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    416 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    417 		    ISCSI_DRIVER_DEVCTL, errno);
    418 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    419 	}
    420 
    421 	memset(&discoveryProps, 0, sizeof (discoveryProps));
    422 	discoveryProps.vers = ISCSI_INTERFACE_VERSION;
    423 
    424 	if (ioctl(fd, ISCSI_DISCOVERY_PROPS, &discoveryProps) != 0) {
    425 		syslog(LOG_USER|LOG_DEBUG,
    426 		    "ISCSI_DISCOVERY_PROPS ioctl failed, errno: %d", errno);
    427 		close(fd);
    428 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    429 	}
    430 
    431 	pProps->iSnsDiscoverySettable = discoveryProps.iSNSDiscoverySettable;
    432 	pProps->iSnsDiscoveryEnabled = discoveryProps.iSNSDiscoveryEnabled;
    433 	/*
    434 	 * Set the iSNS discovery method - The IMA specification indicates
    435 	 * this field is valid only if iSNS discovery is enabled.
    436 	 */
    437 	if (pProps->iSnsDiscoveryEnabled == IMA_TRUE) {
    438 		switch (discoveryProps.iSNSDiscoveryMethod) {
    439 			case iSNSDiscoveryMethodStatic:
    440 				pProps->iSnsDiscoveryMethod =
    441 				    IMA_ISNS_DISCOVERY_METHOD_STATIC;
    442 				break;
    443 			case iSNSDiscoveryMethodDHCP:
    444 				pProps->iSnsDiscoveryMethod =
    445 				    IMA_ISNS_DISCOVERY_METHOD_DHCP;
    446 				break;
    447 			case iSNSDiscoveryMethodSLP:
    448 				pProps->iSnsDiscoveryMethod =
    449 				    IMA_ISNS_DISCOVERY_METHOD_SLP;
    450 				break;
    451 			default:
    452 				close(fd);
    453 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    454 		}
    455 	}
    456 	memcpy(pProps->iSnsHost.id.hostname, discoveryProps.iSNSDomainName,
    457 	    sizeof (pProps->iSnsHost.id.hostname));
    458 	pProps->slpDiscoverySettable = discoveryProps.SLPDiscoverySettable;
    459 	pProps->slpDiscoveryEnabled = discoveryProps.SLPDiscoveryEnabled;
    460 	pProps->staticDiscoverySettable =
    461 	    discoveryProps.StaticDiscoverySettable;
    462 	pProps->staticDiscoveryEnabled = discoveryProps.StaticDiscoveryEnabled;
    463 	pProps->sendTargetsDiscoverySettable =
    464 	    discoveryProps.SendTargetsDiscoverySettable;
    465 	pProps->sendTargetsDiscoveryEnabled =
    466 	    discoveryProps.SendTargetsDiscoveryEnabled;
    467 
    468 	close(fd);
    469 	return (IMA_STATUS_SUCCESS);
    470 }
    471 
    472 IMA_API IMA_STATUS IMA_FreeMemory(
    473 	void *pMemory
    474 )
    475 {
    476 	if (pMemory != NULL)
    477 		free(pMemory);
    478 	return (IMA_STATUS_SUCCESS);
    479 }
    480 
    481 IMA_API IMA_STATUS IMA_GetNonSharedNodeOidList(
    482 		IMA_OID_LIST **ppList
    483 )
    484 {
    485 	if (ppList == NULL)
    486 		return (IMA_ERROR_INVALID_PARAMETER);
    487 
    488 	*ppList = (IMA_OID_LIST*) calloc(1, sizeof (IMA_OID_LIST));
    489 	if (*ppList == NULL) {
    490 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    491 	}
    492 	(*ppList)->oidCount = 0;
    493 
    494 	return (IMA_STATUS_SUCCESS);
    495 }
    496 
    497 IMA_API IMA_STATUS IMA_GetFirstBurstLengthProperties(
    498 		IMA_OID Oid,
    499 		IMA_MIN_MAX_VALUE *pProps
    500 )
    501 {
    502 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    503 	    ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH));
    504 }
    505 
    506 IMA_API IMA_STATUS IMA_GetMaxBurstLengthProperties(
    507 		IMA_OID Oid,
    508 		IMA_MIN_MAX_VALUE *pProps
    509 )
    510 {
    511 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    512 	    ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH));
    513 }
    514 
    515 IMA_API IMA_STATUS IMA_GetMaxRecvDataSegmentLengthProperties(
    516 		IMA_OID Oid,
    517 		IMA_MIN_MAX_VALUE *pProps
    518 )
    519 {
    520 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    521 	    ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH));
    522 }
    523 
    524 /*ARGSUSED*/
    525 IMA_API IMA_STATUS IMA_PluginIOCtl(
    526 		IMA_OID pluginOid,
    527 		IMA_UINT command,
    528 		const void *pInputBuffer,
    529 		IMA_UINT inputBufferLength,
    530 		void *pOutputBuffer,
    531 		IMA_UINT *pOutputBufferLength
    532 )
    533 {
    534 	return (IMA_ERROR_NOT_SUPPORTED);
    535 }
    536 
    537 IMA_API	IMA_STATUS IMA_SetFirstBurstLength(
    538 		IMA_OID lhbaId,
    539 		IMA_UINT firstBurstLength
    540 )
    541 {
    542 	IMA_MIN_MAX_VALUE mv;
    543 
    544 	mv.currentValue = firstBurstLength;
    545 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    546 	    ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH));
    547 }
    548 
    549 IMA_API	IMA_STATUS IMA_SetMaxBurstLength(
    550 		IMA_OID lhbaId,
    551 		IMA_UINT maxBurstLength
    552 )
    553 {
    554 	IMA_MIN_MAX_VALUE mv;
    555 
    556 	mv.currentValue = maxBurstLength;
    557 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    558 	    ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH));
    559 }
    560 
    561 IMA_API	IMA_STATUS IMA_SetMaxRecvDataSegmentLength(
    562 		IMA_OID lhbaId,
    563 		IMA_UINT maxRecvDataSegmentLength
    564 )
    565 {
    566 	IMA_MIN_MAX_VALUE mv;
    567 
    568 	mv.currentValue = maxRecvDataSegmentLength;
    569 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    570 	    ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH));
    571 }
    572 
    573 IMA_API	IMA_STATUS IMA_GetMaxConnectionsProperties(
    574 		IMA_OID Oid,
    575 		IMA_MIN_MAX_VALUE *pProps
    576 )
    577 {
    578 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    579 	    ISCSI_LOGIN_PARAM_MAX_CONNECTIONS));
    580 }
    581 
    582 IMA_API	IMA_STATUS IMA_SetMaxConnections(
    583 		IMA_OID lhbaId,
    584 		IMA_UINT maxConnections
    585 )
    586 {
    587 	IMA_MIN_MAX_VALUE mv;
    588 
    589 	mv.currentValue = maxConnections;
    590 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    591 	    ISCSI_LOGIN_PARAM_MAX_CONNECTIONS));
    592 }
    593 
    594 IMA_API	IMA_STATUS IMA_GetDefaultTime2RetainProperties(
    595 		IMA_OID lhbaId,
    596 		IMA_MIN_MAX_VALUE *pProps
    597 )
    598 {
    599 	return (getISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, pProps,
    600 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN));
    601 }
    602 
    603 IMA_API	IMA_STATUS IMA_SetDefaultTime2Retain(
    604 		IMA_OID lhbaId,
    605 		IMA_UINT defaultTime2Retain
    606 )
    607 {
    608 	IMA_MIN_MAX_VALUE mv;
    609 
    610 	mv.currentValue = defaultTime2Retain;
    611 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    612 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN));
    613 }
    614 
    615 IMA_API	IMA_STATUS IMA_GetDefaultTime2WaitProperties(
    616 		IMA_OID lhbaId,
    617 		IMA_MIN_MAX_VALUE *pProps
    618 )
    619 {
    620 	return (getISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, pProps,
    621 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT));
    622 }
    623 
    624 IMA_API	IMA_STATUS IMA_SetDefaultTime2Wait(
    625 		IMA_OID lhbaId,
    626 		IMA_UINT defaultTime2Wait
    627 )
    628 {
    629 	IMA_MIN_MAX_VALUE mv;
    630 
    631 	mv.currentValue = defaultTime2Wait;
    632 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    633 	    ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT));
    634 }
    635 
    636 IMA_API	IMA_STATUS IMA_GetMaxOutstandingR2TProperties(
    637 		IMA_OID Oid,
    638 		IMA_MIN_MAX_VALUE *pProps
    639 )
    640 {
    641 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    642 	    ISCSI_LOGIN_PARAM_OUTSTANDING_R2T));
    643 }
    644 
    645 IMA_API	IMA_STATUS IMA_SetMaxOutstandingR2T(
    646 		IMA_OID lhbaId,
    647 		IMA_UINT maxOutstandingR2T
    648 )
    649 {
    650 	IMA_MIN_MAX_VALUE mv;
    651 
    652 	mv.currentValue = maxOutstandingR2T;
    653 	return (setISCSINodeParameter(MIN_MAX_PARAM, &lhbaId, &mv,
    654 	    ISCSI_LOGIN_PARAM_OUTSTANDING_R2T));
    655 }
    656 
    657 
    658 IMA_API	IMA_STATUS IMA_GetErrorRecoveryLevelProperties(
    659 		IMA_OID Oid,
    660 		IMA_MIN_MAX_VALUE *pProps
    661 )
    662 {
    663 	return (getISCSINodeParameter(MIN_MAX_PARAM, &Oid, pProps,
    664 	    ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL));
    665 }
    666 
    667 IMA_API	IMA_STATUS IMA_SetErrorRecoveryLevel(
    668 		IMA_OID Oid,
    669 		IMA_UINT errorRecoveryLevel
    670 )
    671 {
    672 	IMA_MIN_MAX_VALUE mv;
    673 
    674 	mv.currentValue = errorRecoveryLevel;
    675 	return (setISCSINodeParameter(MIN_MAX_PARAM, &Oid, &mv,
    676 	    ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL));
    677 }
    678 
    679 IMA_API	IMA_STATUS IMA_GetInitialR2TProperties(
    680 		IMA_OID Oid,
    681 		IMA_BOOL_VALUE *pProps
    682 )
    683 {
    684 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    685 	    ISCSI_LOGIN_PARAM_INITIAL_R2T));
    686 }
    687 
    688 IMA_API	IMA_STATUS IMA_SetInitialR2T(
    689 		IMA_OID Oid,
    690 		IMA_BOOL initialR2T
    691 )
    692 {
    693 	IMA_BOOL_VALUE bv;
    694 
    695 	bv.currentValue = initialR2T;
    696 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    697 	    ISCSI_LOGIN_PARAM_INITIAL_R2T));
    698 }
    699 
    700 
    701 IMA_API	IMA_STATUS IMA_GetImmediateDataProperties(
    702 		IMA_OID Oid,
    703 		IMA_BOOL_VALUE *pProps
    704 )
    705 {
    706 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    707 	    ISCSI_LOGIN_PARAM_IMMEDIATE_DATA));
    708 }
    709 
    710 IMA_API	IMA_STATUS IMA_SetImmediateData(
    711 		IMA_OID Oid,
    712 		IMA_BOOL immediateData
    713 )
    714 {
    715 	IMA_BOOL_VALUE bv;
    716 
    717 	bv.currentValue = immediateData;
    718 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    719 	    ISCSI_LOGIN_PARAM_IMMEDIATE_DATA));
    720 }
    721 
    722 IMA_API	IMA_STATUS IMA_GetDataPduInOrderProperties(
    723 		IMA_OID Oid,
    724 		IMA_BOOL_VALUE *pProps
    725 )
    726 {
    727 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    728 	    ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER));
    729 }
    730 
    731 IMA_API	IMA_STATUS IMA_SetDataPduInOrder(
    732 		IMA_OID Oid,
    733 		IMA_BOOL dataPduInOrder
    734 )
    735 {
    736 	IMA_BOOL_VALUE bv;
    737 
    738 	bv.currentValue = dataPduInOrder;
    739 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    740 	    ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER));
    741 }
    742 
    743 IMA_API	IMA_STATUS IMA_GetDataSequenceInOrderProperties(
    744 		IMA_OID Oid,
    745 		IMA_BOOL_VALUE *pProps
    746 )
    747 {
    748 	return (getISCSINodeParameter(BOOL_PARAM, &Oid, pProps,
    749 	    ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER));
    750 }
    751 
    752 IMA_API	IMA_STATUS IMA_SetDataSequenceInOrder(
    753 		IMA_OID Oid,
    754 		IMA_BOOL dataSequenceInOrder
    755 )
    756 {
    757 	IMA_BOOL_VALUE bv;
    758 
    759 	bv.currentValue = dataSequenceInOrder;
    760 	return (setISCSINodeParameter(BOOL_PARAM, &Oid, &bv,
    761 	    ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER));
    762 }
    763 
    764 
    765 /*ARGSUSED*/
    766 IMA_API	IMA_STATUS IMA_SetStatisticsCollection(
    767 		IMA_OID Oid,
    768 		IMA_BOOL enableStatisticsCollection
    769 )
    770 {
    771 	return (IMA_ERROR_NOT_SUPPORTED);
    772 }
    773 
    774 
    775 /*ARGSUSED*/
    776 IMA_API	IMA_STATUS IMA_GetDiscoveryAddressOidList(
    777 		IMA_OID Oid,
    778 		IMA_OID_LIST **ppList
    779 )
    780 {
    781 	int fd, i, addr_list_size;
    782 	iscsi_addr_list_t *idlp, al_info;
    783 
    784 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    785 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    786 		    ISCSI_DRIVER_DEVCTL, errno);
    787 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    788 	}
    789 
    790 	memset(&al_info, 0, sizeof (al_info));
    791 	al_info.al_vers = ISCSI_INTERFACE_VERSION;
    792 	al_info.al_in_cnt = 0;
    793 
    794 	/*
    795 	 * Issue ioctl to obtain the number of targets.
    796 	 */
    797 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
    798 		syslog(LOG_USER|LOG_DEBUG,
    799 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d",
    800 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    801 		close(fd);
    802 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    803 	}
    804 
    805 	addr_list_size = sizeof (iscsi_addr_list_t);
    806 	if (al_info.al_out_cnt > 1) {
    807 		addr_list_size += (sizeof (iscsi_addr_list_t) *
    808 		    al_info.al_out_cnt - 1);
    809 	}
    810 
    811 	idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size);
    812 	if (idlp == NULL) {
    813 		close(fd);
    814 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    815 	}
    816 
    817 	idlp->al_vers = ISCSI_INTERFACE_VERSION;
    818 	idlp->al_in_cnt = al_info.al_out_cnt;
    819 	/* Issue the same ioctl again to obtain the OIDs. */
    820 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) {
    821 		syslog(LOG_USER|LOG_DEBUG,
    822 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
    823 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    824 		free(idlp);
    825 		close(fd);
    826 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    827 	}
    828 
    829 	*ppList = (IMA_OID_LIST *)calloc(1, sizeof (IMA_OID_LIST) +
    830 	    idlp->al_out_cnt * sizeof (IMA_OID));
    831 	if (*ppList == NULL) {
    832 		free(idlp);
    833 		close(fd);
    834 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    835 	}
    836 	(*ppList)->oidCount = idlp->al_out_cnt;
    837 
    838 	for (i = 0; i < idlp->al_out_cnt; i++) {
    839 		(*ppList)->oids[i].objectType =
    840 		    IMA_OBJECT_TYPE_DISCOVERY_ADDRESS;
    841 		(*ppList)->oids[i].ownerId = pluginOwnerId;
    842 		(*ppList)->oids[i].objectSequenceNumber =
    843 		    idlp->al_addrs[i].a_oid;
    844 	}
    845 
    846 	free(idlp);
    847 	close(fd);
    848 
    849 	return (IMA_STATUS_SUCCESS);
    850 }
    851 
    852 
    853 /* ARGSUSED */
    854 IMA_API	IMA_STATUS IMA_GetStaticDiscoveryTargetOidList(
    855 		IMA_OID Oid,
    856 		IMA_OID_LIST **ppList
    857 )
    858 {
    859 	if (Oid.objectType == IMA_OBJECT_TYPE_PNP) {
    860 		return (IMA_ERROR_OBJECT_NOT_FOUND);
    861 	}
    862 
    863 	return (get_target_oid_list(ISCSI_STATIC_TGT_OID_LIST, ppList));
    864 }
    865 
    866 /* ARGSUSED */
    867 IMA_API	IMA_STATUS IMA_GetTargetOidList(
    868 		IMA_OID Oid,
    869 		IMA_OID_LIST **ppList
    870 )
    871 {
    872 	return (get_target_oid_list(ISCSI_TGT_PARAM_OID_LIST, ppList));
    873 }
    874 
    875 /*ARGSUSED*/
    876 IMA_API	IMA_STATUS IMA_SetIsnsDiscovery(
    877 		IMA_OID phbaId,
    878 		IMA_BOOL enableIsnsDiscovery,
    879 		IMA_ISNS_DISCOVERY_METHOD discoveryMethod,
    880 		const IMA_HOST_ID *iSnsHost
    881 )
    882 {
    883 	/* XXX need to set discovery Method and domaineName */
    884 	return (configure_discovery_method(enableIsnsDiscovery,
    885 	    iSCSIDiscoveryMethodISNS));
    886 }
    887 
    888 
    889 /* ARGSUSED */
    890 IMA_API	IMA_STATUS IMA_SetSlpDiscovery(
    891 		IMA_OID phbaId,
    892 		IMA_BOOL enableSlpDiscovery
    893 )
    894 {
    895 	return (configure_discovery_method(enableSlpDiscovery,
    896 	    iSCSIDiscoveryMethodSLP));
    897 }
    898 
    899 
    900 /* ARGSUSED */
    901 IMA_API	IMA_STATUS IMA_SetStaticDiscovery(
    902 		IMA_OID phbaId,
    903 		IMA_BOOL enableStaticDiscovery
    904 )
    905 {
    906 	return (configure_discovery_method(enableStaticDiscovery,
    907 	    iSCSIDiscoveryMethodStatic));
    908 }
    909 
    910 /* ARGSUSED */
    911 IMA_API	IMA_STATUS IMA_SetSendTargetsDiscovery(
    912 		IMA_OID phbaId,
    913 		IMA_BOOL enableSendTargetsDiscovery
    914 )
    915 {
    916 	return (configure_discovery_method(enableSendTargetsDiscovery,
    917 	    iSCSIDiscoveryMethodSendTargets));
    918 }
    919 
    920 /*ARGSUSED*/
    921 IMA_API IMA_STATUS IMA_RemoveDiscoveryAddress(
    922 		IMA_OID	discoveryAddressOid
    923 )
    924 {
    925 	int status, fd, i, addr_list_size;
    926 	iscsi_addr_list_t *idlp, al_info;
    927 	iscsi_addr_t *matched_addr = NULL;
    928 	entry_t	entry;
    929 
    930 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
    931 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
    932 		    ISCSI_DRIVER_DEVCTL, errno);
    933 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    934 	}
    935 
    936 	memset(&al_info, 0, sizeof (al_info));
    937 	al_info.al_vers = ISCSI_INTERFACE_VERSION;
    938 	al_info.al_in_cnt = 0;
    939 
    940 	/*
    941 	 * Issue ioctl to obtain the number of discovery address.
    942 	 */
    943 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
    944 		syslog(LOG_USER|LOG_DEBUG,
    945 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d",
    946 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    947 		close(fd);
    948 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    949 	}
    950 
    951 	if (al_info.al_out_cnt == 0) {
    952 		return (IMA_ERROR_OBJECT_NOT_FOUND);
    953 	}
    954 
    955 	addr_list_size = sizeof (iscsi_addr_list_t);
    956 	if (al_info.al_out_cnt > 1) {
    957 		addr_list_size += (sizeof (iscsi_addr_list_t) *
    958 		    al_info.al_out_cnt - 1);
    959 	}
    960 
    961 	idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size);
    962 	if (idlp == NULL) {
    963 		close(fd);
    964 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
    965 	}
    966 
    967 	idlp->al_vers = ISCSI_INTERFACE_VERSION;
    968 	idlp->al_in_cnt = al_info.al_out_cnt;
    969 
    970 	/* Issue the same ioctl again to obtain the OIDs. */
    971 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) {
    972 		syslog(LOG_USER|LOG_DEBUG,
    973 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
    974 		    ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
    975 		free(idlp);
    976 		close(fd);
    977 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
    978 	}
    979 
    980 	for (i = 0; i < idlp->al_out_cnt; i++) {
    981 		if (discoveryAddressOid.objectSequenceNumber !=
    982 		    idlp->al_addrs[i].a_oid)
    983 			continue;
    984 		matched_addr = &(idlp->al_addrs[i]);
    985 	}
    986 
    987 	if (matched_addr == NULL) {
    988 		return (IMA_ERROR_OBJECT_NOT_FOUND);
    989 	}
    990 
    991 
    992 	memset(&entry, 0, sizeof (entry_t));
    993 	entry.e_vers = ISCSI_INTERFACE_VERSION;
    994 	entry.e_oid  = discoveryAddressOid.objectSequenceNumber;
    995 	if (matched_addr->a_addr.i_insize == sizeof (struct in_addr)) {
    996 		bcopy(&matched_addr->a_addr.i_addr.in4,
    997 		    &entry.e_u.u_in4, sizeof (entry.e_u.u_in4));
    998 		entry.e_insize = sizeof (struct in_addr);
    999 	} else if (matched_addr->a_addr.i_insize == sizeof (struct in6_addr)) {
   1000 		bcopy(&matched_addr->a_addr.i_addr.in6,
   1001 		    &entry.e_u.u_in6, sizeof (entry.e_u.u_in6));
   1002 		entry.e_insize = sizeof<