xref: /illumos-gate/usr/src/lib/libsun_ima/common/ima.c (revision 563485af1b25ed721b3a7a25a0c9153999957f71)
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 
libSwprintf(wchar_t * wcs,const wchar_t * lpszFormat,...)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
sysevent_handler(sysevent_t * ev)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 
init_sysevents()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 
Initialize(IMA_UINT32 pluginOid)241 IMA_STATUS Initialize(IMA_UINT32 pluginOid) {
242 	pluginOwnerId = pluginOid;
243 	return (init_sysevents());
244 }
245 
Terminate()246 void Terminate() {
247 	if (shp != NULL) {
248 		sysevent_unsubscribe_event(shp, EC_ISCSI);
249 	}
250 
251 }
252 
InitLibrary()253 void InitLibrary() {
254 }
255 
GetBuildTime(IMA_DATETIME * pdatetime)256 static void GetBuildTime(IMA_DATETIME* pdatetime)
257 {
258 	(void) memset(pdatetime, 0, sizeof (IMA_DATETIME));
259 }
260 
261 /*ARGSUSED*/
IMA_GetNodeProperties(IMA_OID nodeOid,IMA_NODE_PROPERTIES * pProps)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 
IMA_SetNodeName(IMA_OID nodeOid,const IMA_NODE_NAME newName)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 
IMA_SetNodeAlias(IMA_OID nodeOid,const IMA_NODE_ALIAS newAlias)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 
IMA_GetLhbaOidList(IMA_OID_LIST ** ppList)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*/
IMA_GetDiscoveryProperties(IMA_OID oid,IMA_DISCOVERY_PROPERTIES * pProps)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 
IMA_FreeMemory(void * pMemory)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 
IMA_GetNonSharedNodeOidList(IMA_OID_LIST ** ppList)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 
IMA_GetFirstBurstLengthProperties(IMA_OID Oid,IMA_MIN_MAX_VALUE * pProps)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 
IMA_GetMaxBurstLengthProperties(IMA_OID Oid,IMA_MIN_MAX_VALUE * pProps)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 
IMA_GetMaxRecvDataSegmentLengthProperties(IMA_OID Oid,IMA_MIN_MAX_VALUE * pProps)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*/
IMA_PluginIOCtl(IMA_OID pluginOid,IMA_UINT command,const void * pInputBuffer,IMA_UINT inputBufferLength,void * pOutputBuffer,IMA_UINT * pOutputBufferLength)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 
IMA_SetFirstBurstLength(IMA_OID lhbaId,IMA_UINT firstBurstLength)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 
IMA_SetMaxBurstLength(IMA_OID lhbaId,IMA_UINT maxBurstLength)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 
IMA_SetMaxRecvDataSegmentLength(IMA_OID lhbaId,IMA_UINT maxRecvDataSegmentLength)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 
IMA_GetMaxConnectionsProperties(IMA_OID Oid,IMA_MIN_MAX_VALUE * pProps)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 
IMA_SetMaxConnections(IMA_OID lhbaId,IMA_UINT maxConnections)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 
IMA_GetDefaultTime2RetainProperties(IMA_OID lhbaId,IMA_MIN_MAX_VALUE * pProps)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 
IMA_SetDefaultTime2Retain(IMA_OID lhbaId,IMA_UINT defaultTime2Retain)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 
IMA_GetDefaultTime2WaitProperties(IMA_OID lhbaId,IMA_MIN_MAX_VALUE * pProps)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 
IMA_SetDefaultTime2Wait(IMA_OID lhbaId,IMA_UINT defaultTime2Wait)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 
IMA_GetMaxOutstandingR2TProperties(IMA_OID Oid,IMA_MIN_MAX_VALUE * pProps)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 
IMA_SetMaxOutstandingR2T(IMA_OID lhbaId,IMA_UINT maxOutstandingR2T)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 
IMA_GetErrorRecoveryLevelProperties(IMA_OID Oid,IMA_MIN_MAX_VALUE * pProps)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 
IMA_SetErrorRecoveryLevel(IMA_OID Oid,IMA_UINT errorRecoveryLevel)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 
IMA_GetInitialR2TProperties(IMA_OID Oid,IMA_BOOL_VALUE * pProps)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 
IMA_SetInitialR2T(IMA_OID Oid,IMA_BOOL initialR2T)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 
IMA_GetImmediateDataProperties(IMA_OID Oid,IMA_BOOL_VALUE * pProps)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 
IMA_SetImmediateData(IMA_OID Oid,IMA_BOOL immediateData)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 
IMA_GetDataPduInOrderProperties(IMA_OID Oid,IMA_BOOL_VALUE * pProps)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 
IMA_SetDataPduInOrder(IMA_OID Oid,IMA_BOOL dataPduInOrder)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 
IMA_GetDataSequenceInOrderProperties(IMA_OID Oid,IMA_BOOL_VALUE * pProps)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 
IMA_SetDataSequenceInOrder(IMA_OID Oid,IMA_BOOL dataSequenceInOrder)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*/
IMA_SetStatisticsCollection(IMA_OID Oid,IMA_BOOL enableStatisticsCollection)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*/
IMA_GetDiscoveryAddressOidList(IMA_OID Oid,IMA_OID_LIST ** ppList)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 */
IMA_GetStaticDiscoveryTargetOidList(IMA_OID Oid,IMA_OID_LIST ** ppList)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 */
IMA_GetTargetOidList(IMA_OID Oid,IMA_OID_LIST ** ppList)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*/
IMA_SetIsnsDiscovery(IMA_OID phbaId,IMA_BOOL enableIsnsDiscovery,IMA_ISNS_DISCOVERY_METHOD discoveryMethod,const IMA_HOST_ID * iSnsHost)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 */
IMA_SetSlpDiscovery(IMA_OID phbaId,IMA_BOOL enableSlpDiscovery)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 */
IMA_SetStaticDiscovery(IMA_OID phbaId,IMA_BOOL enableStaticDiscovery)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 */
IMA_SetSendTargetsDiscovery(IMA_OID phbaId,IMA_BOOL enableSendTargetsDiscovery)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*/
IMA_RemoveDiscoveryAddress(IMA_OID discoveryAddressOid)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*/
IMA_AddDiscoveryAddress(IMA_OID oid,const IMA_TARGET_ADDRESS discoveryAddress,IMA_OID * pDiscoveryAddressOid)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 
IMA_GetStaticDiscoveryTargetProperties(IMA_OID staticTargetOid,IMA_STATIC_DISCOVERY_TARGET_PROPERTIES * pProps)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*/
IMA_GetDiscoveryAddressProperties(IMA_OID discoveryAddressOid,IMA_DISCOVERY_ADDRESS_PROPERTIES * pProps)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 
IMA_RemoveStaticDiscoveryTarget(IMA_OID staticTargetOid)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*/
IMA_AddStaticDiscoveryTarget(IMA_OID lhbaOid,const IMA_STATIC_DISCOVERY_TARGET staticConfig,IMA_OID * pTargetOid)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 = '\0';
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 != '\0') {
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 = '\0';
1371 			(void) strlcpy(target_addr_str, tmp_target_str,
1372 			    sizeof (target_addr_str));
1373 			/* Extract the port number */
1374 			colonPos++;
1375 			if (*colonPos != '\0') {
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 
IMA_GetTargetProperties(IMA_OID targetId,IMA_TARGET_PROPERTIES * pProps)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 
getTargetProperties(IMA_OID targetId,IMA_TARGET_PROPERTIES * pProps)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*/
IMA_GetTargetErrorStatistics(IMA_OID targetId,IMA_TARGET_ERROR_STATISTICS * pStats)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 
IMA_GetLuOidList(IMA_OID oid,IMA_OID_LIST ** ppList)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 
IMA_GetLuOid(IMA_OID targetId,IMA_UINT64 lun,IMA_OID * pluId)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 
IMA_GetLuProperties(IMA_OID luId,IMA_LU_PROPERTIES * pProps)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 
getLuProperties(IMA_OID luId,IMA_LU_PROPERTIES * pProps)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*/
IMA_GetStatisticsProperties(IMA_OID oid,IMA_STATISTICS_PROPERTIES * pProps)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*/
IMA_GetDeviceStatistics(IMA_OID luId,IMA_DEVICE_STATISTICS * pStats)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 
IMA_LuInquiry(IMA_OID deviceId,IMA_BOOL evpd,IMA_BOOL cmddt,IMA_BYTE pageCode,IMA_BYTE * pOutputBuffer,IMA_UINT * pOutputBufferLength,IMA_BYTE * pSenseBuffer,IMA_UINT * pSenseBufferLength)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 
IMA_LuReadCapacity(IMA_OID deviceId,IMA_UINT cdbLength,IMA_BYTE * pOutputBuffer,IMA_UINT * pOutputBufferLength,IMA_BYTE * pSenseBuffer,IMA_UINT * pSenseBufferLength)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 
IMA_LuReportLuns(IMA_OID deviceId,IMA_BOOL sendToWellKnownLun,IMA_BYTE selectReport,IMA_BYTE * pOutputBuffer,IMA_UINT * pOutputBufferLength,IMA_BYTE * pSenseBuffer,IMA_UINT * pSenseBufferLength)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*/
IMA_ExposeLu(IMA_OID luId)2022 IMA_API	IMA_STATUS IMA_ExposeLu(
2023 		IMA_OID luId
2024 )
2025 {
2026 	return (IMA_ERROR_NOT_SUPPORTED);
2027 }
2028 
2029 /*ARGSUSED*/
IMA_UnexposeLu(IMA_OID luId)2030 IMA_API	IMA_STATUS IMA_UnexposeLu(
2031 		IMA_OID luId
2032 )
2033 {
2034 	return (IMA_ERROR_NOT_SUPPORTED);
2035 }
2036 
IMA_GetAddressKeys(IMA_OID targetOid,IMA_ADDRESS_KEYS ** ppKeys)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 
isAuthMethodValid(IMA_OID oid,IMA_AUTHMETHOD method)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 
isAuthMethodListValid(IMA_OID oid,const IMA_AUTHMETHOD * pMethodList,IMA_UINT methodCount)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 
IMA_GetSupportedAuthMethods(IMA_OID lhbaOid,IMA_BOOL getSettableMethods,IMA_UINT * pMethodCount,IMA_AUTHMETHOD * pMethodList)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*/
getSupportedAuthMethods(IMA_OID lhbaOid,IMA_BOOL getSettableMethods,IMA_UINT * pMethodCount,IMA_AUTHMETHOD * pMethodList)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 
IMA_GetInUseInitiatorAuthMethods(IMA_OID lhbaOid,IMA_UINT * pMethodCount,IMA_AUTHMETHOD * pMethodList)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*/
IMA_GetInitiatorAuthParms(IMA_OID lhbaOid,IMA_AUTHMETHOD method,IMA_INITIATOR_AUTHPARMS * pParms)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 
IMA_SetInitiatorAuthMethods(IMA_OID lhbaOid,IMA_UINT methodCount,const IMA_AUTHMETHOD * pMethodList)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  */
IMA_SetInitiatorAuthParms(IMA_OID lhbaOid,IMA_AUTHMETHOD method,const IMA_INITIATOR_AUTHPARMS * pParms)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
getISCSINodeParameter(int paramType,IMA_OID * oid,void * pProps,uint32_t paramIndex)2290 getISCSINodeParameter(int paramType, IMA_OID *oid, void *pProps,
2291     uint32_t paramIndex)
2292 {
2293 	int		    fd;
2294 	iscsi_param_get_t   pg;
2295 
2296 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2297 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2298 		    ISCSI_DRIVER_DEVCTL, errno);
2299 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2300 	}
2301 
2302 	(void) memset(&pg, 0, sizeof (iscsi_param_get_t));
2303 	pg.g_vers = ISCSI_INTERFACE_VERSION;
2304 	pg.g_oid = (uint32_t)oid->objectSequenceNumber;
2305 	pg.g_param = paramIndex;
2306 	pg.g_param_type = ISCSI_SESS_PARAM;
2307 
2308 	if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) {
2309 		syslog(LOG_USER|LOG_DEBUG,
2310 		    "ISCSI_PARAM_GET ioctl failed, errno: %d", errno);
2311 		(void) close(fd);
2312 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2313 	}
2314 
2315 	switch (paramType) {
2316 		IMA_BOOL_VALUE *bp;
2317 		IMA_MIN_MAX_VALUE *mp;
2318 
2319 		case MIN_MAX_PARAM:
2320 			mp = (IMA_MIN_MAX_VALUE *)pProps;
2321 
2322 			mp->currentValueValid =
2323 			    (pg.g_value.v_valid == B_TRUE) ?
2324 			    IMA_TRUE : IMA_FALSE;
2325 			mp->currentValue = pg.g_value.v_integer.i_current;
2326 			mp->defaultValue = pg.g_value.v_integer.i_default;
2327 			mp->minimumValue = pg.g_value.v_integer.i_min;
2328 			mp->maximumValue = pg.g_value.v_integer.i_max;
2329 			mp->incrementValue = pg.g_value.v_integer.i_incr;
2330 			break;
2331 
2332 		case BOOL_PARAM:
2333 			bp = (IMA_BOOL_VALUE *)pProps;
2334 			bp->currentValueValid =
2335 			    (pg.g_value.v_valid == B_TRUE) ?
2336 			    IMA_TRUE : IMA_FALSE;
2337 			bp->currentValue = pg.g_value.v_bool.b_current;
2338 			bp->defaultValue = pg.g_value.v_bool.b_default;
2339 			break;
2340 
2341 		default:
2342 			break;
2343 	}
2344 
2345 	(void) close(fd);
2346 	return (IMA_STATUS_SUCCESS);
2347 }
2348 
2349 /* A helper function to set iSCSI node parameters. */
2350 static IMA_STATUS
setISCSINodeParameter(int paramType,IMA_OID * oid,void * pProp,uint32_t paramIndex)2351 setISCSINodeParameter(int paramType, IMA_OID *oid, void *pProp,
2352     uint32_t paramIndex)
2353 {
2354 	int		    fd;
2355 	iscsi_param_set_t   ps;
2356 
2357 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2358 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2359 		    ISCSI_DRIVER_DEVCTL, errno);
2360 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2361 	}
2362 
2363 	(void) memset(&ps, 0, sizeof (iscsi_param_set_t));
2364 	ps.s_vers = ISCSI_INTERFACE_VERSION;
2365 	ps.s_oid = (uint32_t)oid->objectSequenceNumber;
2366 	ps.s_param = paramIndex;
2367 
2368 	switch (paramType) {
2369 		IMA_BOOL_VALUE *bp;
2370 		IMA_MIN_MAX_VALUE *mp;
2371 
2372 		case MIN_MAX_PARAM:
2373 			mp = (IMA_MIN_MAX_VALUE *)pProp;
2374 			ps.s_value.v_integer = mp->currentValue;
2375 			break;
2376 		case BOOL_PARAM:
2377 			bp = (IMA_BOOL_VALUE *)pProp;
2378 			ps.s_value.v_bool =
2379 			    (bp->currentValue == IMA_TRUE) ?
2380 			    B_TRUE : B_FALSE;
2381 			break;
2382 
2383 		default:
2384 			break;
2385 	}
2386 
2387 	if (ioctl(fd, ISCSI_PARAM_SET, &ps)) {
2388 		int tmpErrno = errno;
2389 		syslog(LOG_USER|LOG_DEBUG,
2390 		    "ISCSI_PARAM_SET ioctl failed, errno: %d", errno);
2391 		(void) close(fd);
2392 		switch (tmpErrno) {
2393 			case ENOTSUP :
2394 				return (IMA_ERROR_NOT_SUPPORTED);
2395 			default :
2396 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2397 		}
2398 	}
2399 
2400 	(void) close(fd);
2401 	return (IMA_STATUS_SUCCESS);
2402 }
2403 
2404 static int
prepare_discovery_entry(IMA_TARGET_ADDRESS discoveryAddress,entry_t * entry)2405 prepare_discovery_entry(IMA_TARGET_ADDRESS discoveryAddress, entry_t *entry)
2406 {
2407 	(void) memset(entry, 0, sizeof (entry_t));
2408 	entry->e_vers = ISCSI_INTERFACE_VERSION;
2409 	entry->e_oid = ISCSI_OID_NOTSET;
2410 
2411 	if (discoveryAddress.hostnameIpAddress.id.ipAddress.ipv4Address ==
2412 	    IMA_FALSE) {
2413 		bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress.ipAddress,
2414 		    entry->e_u.u_in6.s6_addr,
2415 		    sizeof (entry->e_u.u_in6.s6_addr));
2416 		entry->e_insize = sizeof (struct in6_addr);
2417 	} else {
2418 		bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress.ipAddress,
2419 		    &entry->e_u.u_in4.s_addr,
2420 		    sizeof (entry->e_u.u_in4.s_addr));
2421 		entry->e_insize = sizeof (struct in_addr);
2422 	}
2423 
2424 	entry->e_port = discoveryAddress.portNumber;
2425 	entry->e_tpgt = 0;
2426 	return (DISC_ADDR_OK);
2427 }
2428 
configure_discovery_method(IMA_BOOL enable,iSCSIDiscoveryMethod_t method)2429 static IMA_STATUS configure_discovery_method(
2430     IMA_BOOL enable,
2431     iSCSIDiscoveryMethod_t method
2432 )
2433 {
2434 	int fd, status;
2435 
2436 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2437 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2438 		    ISCSI_DRIVER_DEVCTL, errno);
2439 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2440 	}
2441 
2442 	if (enable == IMA_FALSE) {
2443 		if (ioctl(fd, ISCSI_DISCOVERY_CLEAR, &method)) {
2444 			status = errno;
2445 			(void) close(fd);
2446 			syslog(LOG_USER|LOG_DEBUG,
2447 			    "ISCSI_DISCOVERY_CLEAR ioctl failed, errno: %d",
2448 			    status);
2449 			if (status == EBUSY) {
2450 				return (IMA_ERROR_LU_IN_USE);
2451 			} else {
2452 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2453 			}
2454 		}
2455 
2456 		(void) close(fd);
2457 		return (IMA_STATUS_SUCCESS);
2458 	} else {
2459 		/* Set the discovery method */
2460 		if (ioctl(fd, ISCSI_DISCOVERY_SET, &method)) {
2461 			(void) close(fd);
2462 			syslog(LOG_USER|LOG_DEBUG,
2463 			    "ISCSI_DISCOVERY_SET ioctl failed, errno: %d",
2464 			    errno);
2465 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2466 		}
2467 
2468 		(void) close(fd);
2469 		return (IMA_STATUS_SUCCESS);
2470 	}
2471 }
2472 
get_target_oid_list(uint32_t targetListType,IMA_OID_LIST ** ppList)2473 static IMA_STATUS get_target_oid_list(
2474     uint32_t targetListType,
2475     IMA_OID_LIST **ppList)
2476 {
2477 	int		    fd;
2478 	int		    i;
2479 	int		    target_list_size;
2480 	iscsi_target_list_t *idlp, tl_info;
2481 
2482 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2483 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2484 		    ISCSI_DRIVER_DEVCTL, errno);
2485 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2486 	}
2487 
2488 	(void) memset(&tl_info, 0, sizeof (tl_info));
2489 	tl_info.tl_vers = ISCSI_INTERFACE_VERSION;
2490 	tl_info.tl_in_cnt = 0;
2491 	tl_info.tl_tgt_list_type = targetListType;
2492 
2493 	/*
2494 	 * Issue ioctl to obtain the number of targets.
2495 	 */
2496 	if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, &tl_info) != 0) {
2497 		(void) close(fd);
2498 		syslog(LOG_USER|LOG_DEBUG,
2499 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
2500 		    targetListType, errno);
2501 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2502 	}
2503 
2504 	target_list_size = sizeof (iscsi_target_list_t);
2505 	if (tl_info.tl_out_cnt > 1) {
2506 		target_list_size += (sizeof (uint32_t) *
2507 		    tl_info.tl_out_cnt - 1);
2508 	}
2509 
2510 	idlp = (iscsi_target_list_t *)calloc(1, target_list_size);
2511 	if (idlp == NULL) {
2512 		(void) close(fd);
2513 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
2514 	}
2515 
2516 	idlp->tl_vers = ISCSI_INTERFACE_VERSION;
2517 	idlp->tl_in_cnt = tl_info.tl_out_cnt;
2518 	idlp->tl_tgt_list_type = targetListType;
2519 
2520 	/* Issue the same ioctl again to obtain the OIDs. */
2521 	if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) {
2522 		free(idlp);
2523 		(void) close(fd);
2524 		syslog(LOG_USER|LOG_DEBUG,
2525 		    "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
2526 		    targetListType, errno);
2527 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2528 	}
2529 
2530 	*ppList = (IMA_OID_LIST *)calloc(1, sizeof (IMA_OID_LIST) +
2531 	    idlp->tl_out_cnt * sizeof (IMA_OID));
2532 	if (*ppList == NULL) {
2533 		free(idlp);
2534 		(void) close(fd);
2535 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
2536 	}
2537 	(*ppList)->oidCount = idlp->tl_out_cnt;
2538 
2539 	for (i = 0; i < idlp->tl_out_cnt; i++) {
2540 
2541 		if (targetListType == ISCSI_STATIC_TGT_OID_LIST)
2542 			(*ppList)->oids[i].objectType =
2543 			    IMA_OBJECT_TYPE_STATIC_DISCOVERY_TARGET;
2544 		else
2545 			(*ppList)->oids[i].objectType = IMA_OBJECT_TYPE_TARGET;
2546 
2547 		(*ppList)->oids[i].ownerId = pluginOwnerId;
2548 		(*ppList)->oids[i].objectSequenceNumber = idlp->tl_oid_list[i];
2549 	}
2550 
2551 	free(idlp);
2552 	(void) close(fd);
2553 	return (IMA_STATUS_SUCCESS);
2554 }
2555 
get_target_lun_oid_list(IMA_OID * targetOid,iscsi_lun_list_t ** ppLunList)2556 static IMA_STATUS get_target_lun_oid_list(
2557     IMA_OID * targetOid,
2558     iscsi_lun_list_t  **ppLunList)
2559 {
2560 	int			fd;
2561 	iscsi_lun_list_t	*illp, ll_info;
2562 	int			lun_list_size;
2563 
2564 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2565 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2566 		    ISCSI_DRIVER_DEVCTL, errno);
2567 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2568 	}
2569 
2570 	(void) memset(&ll_info, 0, sizeof (ll_info));
2571 	ll_info.ll_vers = ISCSI_INTERFACE_VERSION;
2572 	if (targetOid == NULL) {
2573 		/* get lun oid list for all targets */
2574 		ll_info.ll_all_tgts = B_TRUE;
2575 	} else {
2576 		/* get lun oid list for single target */
2577 		ll_info.ll_all_tgts = B_FALSE;
2578 		ll_info.ll_tgt_oid = (uint32_t)targetOid->objectSequenceNumber;
2579 	}
2580 	ll_info.ll_in_cnt = 0;
2581 
2582 	/*
2583 	 * Issue ioctl to obtain the number of target LUNs.
2584 	 */
2585 	if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, &ll_info) != 0) {
2586 		(void) close(fd);
2587 		syslog(LOG_USER|LOG_DEBUG,
2588 		    "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", errno);
2589 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2590 	}
2591 
2592 	lun_list_size = sizeof (iscsi_lun_list_t);
2593 	if (ll_info.ll_out_cnt > 1) {
2594 		lun_list_size += (sizeof (iscsi_if_lun_t) *
2595 		    (ll_info.ll_out_cnt - 1));
2596 	}
2597 
2598 	illp = (iscsi_lun_list_t *)calloc(1, lun_list_size);
2599 	if (illp == NULL) {
2600 		(void) close(fd);
2601 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
2602 	}
2603 	illp->ll_vers = ISCSI_INTERFACE_VERSION;
2604 	illp->ll_all_tgts = ll_info.ll_all_tgts;
2605 	illp->ll_tgt_oid = ll_info.ll_tgt_oid;
2606 	illp->ll_in_cnt = ll_info.ll_out_cnt;
2607 
2608 	/* Issue the same ioctl again to get the target LUN list */
2609 	if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) {
2610 		free(illp);
2611 		(void) close(fd);
2612 		syslog(LOG_USER|LOG_DEBUG,
2613 		    "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", errno);
2614 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2615 	}
2616 
2617 	*ppLunList = illp;
2618 
2619 	(void) close(fd);
2620 	return (IMA_STATUS_SUCCESS);
2621 }
2622 
2623 
2624 /* A helper function to set authentication method. */
2625 static IMA_STATUS
setAuthMethods(IMA_OID oid,IMA_UINT * pMethodCount,const IMA_AUTHMETHOD * pMethodList)2626 setAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount,
2627     const IMA_AUTHMETHOD *pMethodList)
2628 {
2629 	int fd;
2630 	int i;
2631 	iscsi_auth_props_t auth;
2632 
2633 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2634 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2635 		    ISCSI_DRIVER_DEVCTL, errno);
2636 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2637 	}
2638 	(void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
2639 	auth.a_vers = ISCSI_INTERFACE_VERSION;
2640 	auth.a_oid = (uint32_t)oid.objectSequenceNumber;
2641 	/* First do a get because other data fields may exist */
2642 	if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
2643 		/* EMPTY */
2644 		/* It is fine if there is no other data fields. */
2645 	}
2646 	auth.a_auth_method = authMethodNone;
2647 
2648 	for (i = 0; i < *pMethodCount; i++) {
2649 		switch (pMethodList[i]) {
2650 			case IMA_AUTHMETHOD_CHAP:
2651 				auth.a_auth_method |= authMethodCHAP;
2652 				break;
2653 			default:
2654 				break;
2655 		}
2656 	}
2657 
2658 	if (ioctl(fd, ISCSI_AUTH_SET, &auth) != 0) {
2659 		syslog(LOG_USER|LOG_DEBUG,
2660 		    "ISCSI_AUTH_SET failed, errno: %d", errno);
2661 		(void) close(fd);
2662 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2663 	}
2664 
2665 	(void) close(fd);
2666 	return (IMA_STATUS_SUCCESS);
2667 }
2668 
2669 /* A helper function to get authentication method. */
2670 static IMA_STATUS
getAuthMethods(IMA_OID oid,IMA_UINT * pMethodCount,IMA_AUTHMETHOD * pMethodList)2671 getAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount, IMA_AUTHMETHOD *pMethodList)
2672 {
2673 	int fd, i;
2674 	iscsi_auth_props_t auth;
2675 
2676 	if (pMethodList == NULL) {
2677 		*pMethodCount = 0;
2678 		return (IMA_STATUS_SUCCESS);
2679 	}
2680 
2681 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2682 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2683 		    ISCSI_DRIVER_DEVCTL, errno);
2684 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2685 	}
2686 
2687 	(void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
2688 	auth.a_vers = ISCSI_INTERFACE_VERSION;
2689 	auth.a_oid = (uint32_t)oid.objectSequenceNumber;
2690 
2691 	if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
2692 		syslog(LOG_USER|LOG_DEBUG,
2693 		    "ISCSI_AUTH_GET failed, errno: %d", errno);
2694 		(void) close(fd);
2695 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2696 	}
2697 
2698 	i = 0;
2699 	if (auth.a_auth_method == authMethodNone) {
2700 		pMethodList[i++] = IMA_AUTHMETHOD_NONE;
2701 	} else if (auth.a_auth_method & authMethodCHAP) {
2702 		pMethodList[i++] = IMA_AUTHMETHOD_CHAP;
2703 	}
2704 	*pMethodCount = i;
2705 
2706 	(void) close(fd);
2707 	return (IMA_STATUS_SUCCESS);
2708 }
2709 
IMA_GetPhbaOidList(IMA_OID_LIST ** ppList)2710 IMA_API IMA_STATUS IMA_GetPhbaOidList(
2711 		IMA_OID_LIST **ppList
2712 )
2713 {
2714 	*ppList = (IMA_OID_LIST*)calloc(1, sizeof (IMA_OID_LIST));
2715 	if (*ppList == NULL) {
2716 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
2717 	}
2718 	(*ppList)->oidCount = 0;
2719 	return (IMA_STATUS_SUCCESS);
2720 }
2721 
2722 /* ARGSUSED */
IMA_GetPhbaProperties(IMA_OID phbaOid,IMA_PHBA_PROPERTIES * pProps)2723 IMA_API IMA_STATUS IMA_GetPhbaProperties(
2724 		IMA_OID phbaOid,
2725 		IMA_PHBA_PROPERTIES *pProps
2726 )
2727 {
2728 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2729 }
2730 
2731 /* ARGSUSED */
IMA_GetPhbaStatus(IMA_OID phbaOid,IMA_PHBA_STATUS * pStatus)2732 IMA_API IMA_STATUS IMA_GetPhbaStatus(
2733 		IMA_OID phbaOid,
2734 		IMA_PHBA_STATUS *pStatus
2735 )
2736 {
2737 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2738 }
2739 
2740 /* ARGSUSED */
IMA_GetPhbaDownloadProperties(IMA_OID phbaOid,IMA_PHBA_DOWNLOAD_PROPERTIES * pProps)2741 IMA_API IMA_STATUS IMA_GetPhbaDownloadProperties(
2742 		IMA_OID phbaOid,
2743 		IMA_PHBA_DOWNLOAD_PROPERTIES *pProps
2744 )
2745 {
2746 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2747 }
2748 
2749 /* ARGSUSED */
IMA_IsPhbaDownloadFile(IMA_OID phbaOid,const IMA_WCHAR * pFileName,IMA_PHBA_DOWNLOAD_IMAGE_PROPERTIES * pProps)2750 IMA_API IMA_STATUS IMA_IsPhbaDownloadFile(
2751 		IMA_OID phbaOid,
2752 		const IMA_WCHAR *pFileName,
2753 		IMA_PHBA_DOWNLOAD_IMAGE_PROPERTIES *pProps
2754 )
2755 {
2756 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2757 }
2758 
2759 /* ARGSUSED */
IMA_PhbaDownload(IMA_OID phbaOid,IMA_PHBA_DOWNLOAD_IMAGE_TYPE imageType,const IMA_WCHAR * pFileName)2760 IMA_API IMA_STATUS IMA_PhbaDownload(
2761 		IMA_OID phbaOid,
2762 		IMA_PHBA_DOWNLOAD_IMAGE_TYPE imageType,
2763 		const IMA_WCHAR *pFileName
2764 )
2765 {
2766 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2767 }
2768 
IMA_GetPnpOidList(IMA_OID pnpOid,IMA_OID_LIST ** ppList)2769 IMA_API IMA_STATUS IMA_GetPnpOidList(
2770 		IMA_OID pnpOid,
2771 		IMA_OID_LIST **ppList
2772 )
2773 {
2774 	/*
2775 	 * Always return the same object ID for the pnp as the spec
2776 	 * states that this function will always return a list of at least
2777 	 * one element
2778 	 */
2779 	pnpOid.objectType = IMA_OBJECT_TYPE_PNP;
2780 	pnpOid.ownerId = pluginOwnerId;
2781 	pnpOid.objectSequenceNumber = ISCSI_INITIATOR_OID;
2782 
2783 	*ppList = (IMA_OID_LIST*)calloc(1, sizeof (IMA_OID_LIST) +
2784 	    (1* sizeof (IMA_OID)));
2785 
2786 	if (*ppList == NULL) {
2787 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
2788 	}
2789 
2790 	(*ppList)->oidCount = 1;
2791 	(void) memcpy(&(*ppList)->oids[0], &pnpOid, sizeof (pnpOid));
2792 	return (IMA_STATUS_SUCCESS);
2793 }
2794 
2795 /* ARGSUSED */
IMA_GetPnpProperties(IMA_OID pnpOid,IMA_PNP_PROPERTIES * pProps)2796 IMA_API IMA_STATUS IMA_GetPnpProperties(
2797 		IMA_OID pnpOid,
2798 		IMA_PNP_PROPERTIES *pProps
2799 )
2800 {
2801 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2802 }
2803 
2804 /* ARGSUSED */
IMA_GetPnpStatistics(IMA_OID pnpOid,IMA_PNP_STATISTICS * pStats)2805 IMA_API IMA_STATUS IMA_GetPnpStatistics(
2806 		IMA_OID pnpOid,
2807 		IMA_PNP_STATISTICS *pStats
2808 )
2809 {
2810 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2811 }
2812 
2813 /* ARGSUSED */
IMA_GetIpProperties(IMA_OID oid,IMA_IP_PROPERTIES * pProps)2814 IMA_API IMA_STATUS IMA_GetIpProperties(
2815 		IMA_OID oid,
2816 		IMA_IP_PROPERTIES *pProps
2817 )
2818 {
2819 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2820 }
2821 
2822 /* ARGSUSED */
IMA_SetDefaultGateway(IMA_OID oid,IMA_IP_ADDRESS defaultGateway)2823 IMA_API IMA_STATUS IMA_SetDefaultGateway(
2824 		IMA_OID oid,
2825 		IMA_IP_ADDRESS defaultGateway
2826 )
2827 {
2828 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2829 }
2830 
2831 /* ARGSUSED */
IMA_SetDnsServerAddress(IMA_OID oid,const IMA_IP_ADDRESS * pPrimaryDnsServerAddress,const IMA_IP_ADDRESS * pAlternateDnsServerAddress)2832 IMA_API IMA_STATUS IMA_SetDnsServerAddress(
2833 		IMA_OID oid,
2834 		const IMA_IP_ADDRESS *pPrimaryDnsServerAddress,
2835 		const IMA_IP_ADDRESS *pAlternateDnsServerAddress
2836 )
2837 {
2838 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2839 }
2840 
2841 /* ARGSUSED */
IMA_SetSubnetMask(IMA_OID oid,IMA_IP_ADDRESS subnetMask)2842 IMA_API IMA_STATUS IMA_SetSubnetMask(
2843 		IMA_OID oid,
2844 		IMA_IP_ADDRESS subnetMask
2845 )
2846 {
2847 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2848 }
2849 
2850 /* ARGSUSED */
IMA_SetIpConfigMethod(IMA_OID oid,IMA_BOOL enableDhcpIpConfiguration)2851 IMA_API IMA_STATUS IMA_SetIpConfigMethod(
2852 		IMA_OID oid,
2853 		IMA_BOOL enableDhcpIpConfiguration
2854 )
2855 {
2856 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2857 }
2858 
IMA_RegisterForObjectPropertyChanges(IMA_OBJECT_PROPERTY_FN pClientFn)2859 IMA_API IMA_STATUS IMA_RegisterForObjectPropertyChanges(
2860 		IMA_OBJECT_PROPERTY_FN pClientFn
2861 )
2862 {
2863 	pObjectPropertyCallback = pClientFn;
2864 	return (IMA_STATUS_SUCCESS);
2865 }
2866 
2867 /* ARGSUSED */
IMA_DeregisterForObjectPropertyChanges(IMA_OBJECT_PROPERTY_FN pClientFn)2868 IMA_API IMA_STATUS IMA_DeregisterForObjectPropertyChanges(
2869 		IMA_OBJECT_PROPERTY_FN pClientFn
2870 )
2871 {
2872 	return (IMA_STATUS_SUCCESS);
2873 }
2874 
IMA_RegisterForObjectVisibilityChanges(IMA_OBJECT_VISIBILITY_FN pClientFn)2875 IMA_API IMA_STATUS IMA_RegisterForObjectVisibilityChanges(
2876 		IMA_OBJECT_VISIBILITY_FN pClientFn
2877 )
2878 {
2879 	pObjectVisibilityCallback = pClientFn;
2880 	return (IMA_STATUS_SUCCESS);
2881 }
2882 
2883 /* ARGSUSED */
IMA_DeregisterForObjectVisibilityChanges(IMA_OBJECT_VISIBILITY_FN pClientFn)2884 IMA_API IMA_STATUS IMA_DeregisterForObjectVisibilityChanges(
2885 		IMA_OBJECT_VISIBILITY_FN pClientFn
2886 )
2887 {
2888 	return (IMA_STATUS_SUCCESS);
2889 }
2890 
2891 /* ARGSUSED */
IMA_GetNetworkPortStatus(IMA_OID portOid,IMA_NETWORK_PORT_STATUS * pStaus)2892 IMA_API IMA_STATUS IMA_GetNetworkPortStatus(
2893 		IMA_OID portOid,
2894 		IMA_NETWORK_PORT_STATUS *pStaus
2895 )
2896 {
2897 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2898 }
2899 
2900 /* ARGSUSED */
IMA_GetNetworkPortalOidList(IMA_OID pnpOid,IMA_OID_LIST ** ppList)2901 IMA_API IMA_STATUS IMA_GetNetworkPortalOidList(
2902 		IMA_OID pnpOid,
2903 		IMA_OID_LIST **ppList
2904 )
2905 {
2906 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2907 }
2908 
2909 /* ARGSUSED */
IMA_GetNetworkPortalProperties(IMA_OID networkPortalOid,IMA_NETWORK_PORTAL_PROPERTIES * pProps)2910 IMA_API IMA_STATUS IMA_GetNetworkPortalProperties(
2911 		IMA_OID networkPortalOid,
2912 		IMA_NETWORK_PORTAL_PROPERTIES *pProps
2913 )
2914 {
2915 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2916 }
2917 
2918 /* ARGSUSED */
IMA_SetNetworkPortalIpAddress(IMA_OID networkPortalOid,const IMA_IP_ADDRESS NewIpAddress)2919 IMA_API IMA_STATUS IMA_SetNetworkPortalIpAddress(
2920 		IMA_OID networkPortalOid,
2921 		const IMA_IP_ADDRESS NewIpAddress
2922 )
2923 {
2924 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2925 }
2926 
2927 /* ARGSUSED */
IMA_RemoveStaleData(IMA_OID lhbaOid)2928 IMA_API IMA_STATUS IMA_RemoveStaleData(
2929 		IMA_OID lhbaOid
2930 )
2931 {
2932 	return (IMA_ERROR_NOT_SUPPORTED);
2933 }
2934 
2935 /* ARGSUSED */
IMA_GetIpsecProperties(IMA_OID oid,IMA_IPSEC_PROPERTIES * pProps)2936 IMA_API IMA_STATUS IMA_GetIpsecProperties(
2937 		IMA_OID oid,
2938 		IMA_IPSEC_PROPERTIES *pProps
2939 )
2940 {
2941 	pProps->ipsecSupported = IMA_TRUE;
2942 	pProps->implementedInHardware = IMA_FALSE;
2943 	pProps->implementedInSoftware = IMA_TRUE;
2944 
2945 	return (IMA_STATUS_SUCCESS);
2946 }
2947 
2948 /* ARGSUSED */
IMA_GetLhbaProperties(IMA_OID lhbaOid,IMA_LHBA_PROPERTIES * pProps)2949 IMA_API IMA_STATUS IMA_GetLhbaProperties(
2950 		IMA_OID lhbaOid,
2951 		IMA_LHBA_PROPERTIES *pProps
2952 )
2953 {
2954 
2955 	if (pProps == NULL) {
2956 		return (IMA_ERROR_INVALID_PARAMETER);
2957 	}
2958 
2959 	if (lhbaObjectId.objectSequenceNumber != ISCSI_INITIATOR_OID) {
2960 		return (IMA_ERROR_OBJECT_NOT_FOUND);
2961 	}
2962 
2963 	(void) memset(pProps, 0, sizeof (IMA_LHBA_PROPERTIES));
2964 	(void) mbstowcs(pProps->osDeviceName, OS_DEVICE_NAME,
2965 	    OS_DEVICE_NAME_LEN);
2966 	pProps->luExposingSupported = IMA_FALSE;
2967 	pProps->isDestroyable = IMA_FALSE;
2968 	pProps->staleDataRemovable = IMA_FALSE;
2969 	pProps->staleDataSize = 0;
2970 	pProps->initiatorAuthMethodsSettable = IMA_TRUE;
2971 	pProps->targetAuthMethodsSettable = IMA_FALSE;
2972 
2973 	return (IMA_STATUS_SUCCESS);
2974 }
2975 
IMA_GetLnpOidList(IMA_OID_LIST ** ppList)2976 IMA_API IMA_STATUS IMA_GetLnpOidList(
2977 		IMA_OID_LIST **ppList
2978 )
2979 {
2980 	*ppList = (IMA_OID_LIST *) calloc(1, (sizeof (IMA_OID_LIST)));
2981 	if (*ppList == NULL) {
2982 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
2983 	}
2984 	(*ppList)->oidCount = 0;
2985 
2986 	return (IMA_STATUS_SUCCESS);
2987 }
2988 
2989 /* ARGSUSED */
IMA_GetLnpProperties(IMA_OID lnpOid,IMA_LNP_PROPERTIES * pProps)2990 IMA_API IMA_STATUS IMA_GetLnpProperties(
2991 		IMA_OID lnpOid,
2992 		IMA_LNP_PROPERTIES *pProps
2993 )
2994 {
2995 	return (IMA_ERROR_OBJECT_NOT_FOUND);
2996 }
2997 
2998 #define	IMA_DISK_DEVICE_NAME_PREFIX	"/dev/rdsk/"
2999 #define	IMA_TAPE_DEVICE_NAME_PREFIX	"/dev/rmt/"
3000 static int
get_lun_devlink(di_devlink_t link,void * osDeviceName)3001 get_lun_devlink(di_devlink_t link, void *osDeviceName)
3002 {
3003 	if ((strncmp(IMA_DISK_DEVICE_NAME_PREFIX, di_devlink_path(link),
3004 	    strlen(IMA_DISK_DEVICE_NAME_PREFIX)) == 0) ||
3005 	    (strncmp(IMA_TAPE_DEVICE_NAME_PREFIX, di_devlink_path(link),
3006 	    strlen(IMA_TAPE_DEVICE_NAME_PREFIX)) == 0)) {
3007 		(void) mbstowcs((wchar_t *)osDeviceName, di_devlink_path(link),
3008 		    MAXPATHLEN);
3009 		return (DI_WALK_TERMINATE);
3010 	}
3011 
3012 	return (DI_WALK_CONTINUE);
3013 }
3014 
3015 /* ARGSUSED */
IMA_GetPluginProperties(IMA_OID pluginOid,IMA_PLUGIN_PROPERTIES * pProps)3016 IMA_API IMA_STATUS IMA_GetPluginProperties(
3017 	IMA_OID pluginOid,
3018 	IMA_PLUGIN_PROPERTIES *pProps
3019 )
3020 {
3021 	pProps->supportedImaVersion = 1;
3022 	libSwprintf(pProps->vendor, L"%ls", LIBRARY_PROPERTY_VENDOR);
3023 	libSwprintf(pProps->implementationVersion, L"%ls",
3024 	    LIBRARY_PROPERTY_IMPLEMENTATION_VERSION);
3025 	libSwprintf(pProps->fileName, L"%ls", LIBRARY_FILE_NAME);
3026 	GetBuildTime(&(pProps->buildTime));
3027 	pProps->lhbasCanBeCreatedAndDestroyed = IMA_FALSE;
3028 	return (IMA_STATUS_SUCCESS);
3029 }
3030 
getDiscoveryAddressPropertiesList(SUN_IMA_DISC_ADDR_PROP_LIST ** ppList)3031 IMA_STATUS getDiscoveryAddressPropertiesList(
3032     SUN_IMA_DISC_ADDR_PROP_LIST **ppList
3033 )
3034 {
3035 	int		    fd;
3036 	int		    i;
3037 	int		    discovery_addr_list_size;
3038 	iscsi_addr_list_t   *ialp, al_info;
3039 
3040 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3041 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
3042 		    ISCSI_DRIVER_DEVCTL, errno);
3043 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3044 	}
3045 
3046 	(void) memset(&al_info, 0, sizeof (al_info));
3047 	al_info.al_vers = ISCSI_INTERFACE_VERSION;
3048 	al_info.al_in_cnt = 0;
3049 
3050 	/*
3051 	 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl to obtain the number of
3052 	 * discovery addresses.
3053 	 */
3054 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
3055 		(void) close(fd);
3056 		syslog(LOG_USER|LOG_DEBUG,
3057 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno: %d",
3058 		    errno);
3059 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3060 	}
3061 
3062 	discovery_addr_list_size = sizeof (iscsi_addr_list_t);
3063 	if (al_info.al_out_cnt > 1) {
3064 		discovery_addr_list_size += (sizeof (iscsi_addr_t) *
3065 		    al_info.al_out_cnt - 1);
3066 	}
3067 
3068 	ialp = (iscsi_addr_list_t *)calloc(1, discovery_addr_list_size);
3069 	if (ialp == NULL) {
3070 		(void) close(fd);
3071 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
3072 	}
3073 	ialp->al_vers = ISCSI_INTERFACE_VERSION;
3074 	ialp->al_in_cnt = al_info.al_out_cnt;
3075 
3076 	/*
3077 	 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl again to obtain the
3078 	 * discovery addresses.
3079 	 */
3080 	if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, ialp) != 0) {
3081 		free(ialp);
3082 		(void) close(fd);
3083 		syslog(LOG_USER|LOG_DEBUG,
3084 		    "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno: %d",
3085 		    errno);
3086 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3087 	}
3088 
3089 	*ppList = (SUN_IMA_DISC_ADDR_PROP_LIST *)
3090 	    calloc(1, sizeof (SUN_IMA_DISC_ADDR_PROP_LIST) +
3091 	    ialp->al_out_cnt * sizeof (IMA_DISCOVERY_ADDRESS_PROPERTIES));
3092 
3093 	if (*ppList == NULL) {
3094 		free(ialp);
3095 		(void) close(fd);
3096 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
3097 	}
3098 	(*ppList)->discAddrCount = ialp->al_out_cnt;
3099 
3100 	for (i = 0; i < ialp->al_out_cnt; i++) {
3101 		if (ialp->al_addrs[i].a_addr.i_insize ==
3102 		    sizeof (struct in_addr)) {
3103 			(*ppList)->props[i].discoveryAddress.hostnameIpAddress.
3104 			id.ipAddress.ipv4Address = IMA_TRUE;
3105 		} else if (ialp->al_addrs[i].a_addr.i_insize ==
3106 		    sizeof (struct in6_addr)) {
3107 			(*ppList)->props[i].discoveryAddress.
3108 			hostnameIpAddress.id.ipAddress.ipv4Address = IMA_FALSE;
3109 		} else {
3110 			/* Should not happen */
3111 			syslog(LOG_USER|LOG_DEBUG,
3112 			"ISCSI_STATIC_GET returned bad address");
3113 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3114 		}
3115 
3116 		bcopy(&ialp->al_addrs[i].a_addr.i_addr,	(*ppList)->props[i].
3117 		    discoveryAddress.hostnameIpAddress.id.ipAddress.ipAddress,
3118 		    sizeof ((*ppList)->props[i].discoveryAddress.
3119 		    hostnameIpAddress.id.ipAddress.ipAddress));
3120 
3121 		(*ppList)->props[i].discoveryAddress.portNumber =
3122 		    ialp->al_addrs[i].a_port;
3123 	}
3124 
3125 	free(ialp);
3126 	(void) close(fd);
3127 	return (IMA_STATUS_SUCCESS);
3128 }
3129 
3130 
3131 /* ARGSUSED */
sendTargets(IMA_TARGET_ADDRESS address,SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES ** ppList)3132 IMA_STATUS sendTargets(
3133     IMA_TARGET_ADDRESS address,
3134     SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList
3135 )
3136 {
3137 	char	*colonPos;
3138 	char	discAddrStr[SUN_IMA_IP_ADDRESS_LEN];
3139 	int	fd;
3140 	int	ctr;
3141 	int	stl_sz;
3142 	iscsi_sendtgts_list_t	*stl_hdr = NULL;
3143 	IMA_BOOL		retry = IMA_TRUE;
3144 
3145 #define	SENDTGTS_DEFAULT_NUM_TARGETS	10
3146 
3147 	stl_sz = sizeof (*stl_hdr) + ((SENDTGTS_DEFAULT_NUM_TARGETS - 1) *
3148 	    sizeof (iscsi_sendtgts_entry_t));
3149 	stl_hdr = (iscsi_sendtgts_list_t *)calloc(1, stl_sz);
3150 	if (stl_hdr == NULL) {
3151 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
3152 	}
3153 	stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION;
3154 	stl_hdr->stl_in_cnt = SENDTGTS_DEFAULT_NUM_TARGETS;
3155 
3156 	colonPos = strchr(discAddrStr, ':');
3157 	if (colonPos == NULL) {
3158 		/* IPv4 */
3159 		stl_hdr->stl_entry.e_insize = sizeof (struct in_addr);
3160 	} else {
3161 		/* IPv6 */
3162 		stl_hdr->stl_entry.e_insize = sizeof (struct in6_addr);
3163 	}
3164 
3165 
3166 	bcopy(address.hostnameIpAddress.id.ipAddress.ipAddress,
3167 	    &stl_hdr->stl_entry.e_u,
3168 	    sizeof (address.hostnameIpAddress.id.ipAddress.ipAddress));
3169 	stl_hdr->stl_entry.e_port = address.portNumber;
3170 
3171 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3172 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
3173 		    ISCSI_DRIVER_DEVCTL, errno);
3174 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3175 	}
3176 
3177 retry_sendtgts:
3178 	/*
3179 	 * Issue ioctl to obtain the SendTargets list
3180 	 */
3181 	if (ioctl(fd, ISCSI_SENDTGTS_GET, stl_hdr) != 0) {
3182 		syslog(LOG_USER|LOG_DEBUG,
3183 		    "ISCSI_SENDTGTS_GET ioctl failed, errno: %d", errno);
3184 		(void) close(fd);
3185 		free(stl_hdr);
3186 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3187 	}
3188 
3189 	/* check if all targets received */
3190 	if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) {
3191 		if (retry == IMA_TRUE) {
3192 			stl_sz = sizeof (*stl_hdr) +
3193 			    ((stl_hdr->stl_out_cnt - 1) *
3194 			    sizeof (iscsi_sendtgts_entry_t));
3195 			stl_hdr = (iscsi_sendtgts_list_t *)
3196 			    realloc(stl_hdr, stl_sz);
3197 			if (stl_hdr == NULL) {
3198 				(void) close(fd);
3199 				return (IMA_ERROR_INSUFFICIENT_MEMORY);
3200 			}
3201 			stl_hdr->stl_in_cnt = stl_hdr->stl_out_cnt;
3202 			retry = IMA_FALSE;
3203 			goto retry_sendtgts;
3204 		} else {
3205 			/*
3206 			 * don't retry after 2 attempts.  The target list
3207 			 * shouldn't continue to growing. Justs continue
3208 			 * on and display what was found.
3209 			 */
3210 			syslog(LOG_USER|LOG_DEBUG,
3211 			    "ISCSI_SENDTGTS_GET overflow: "
3212 			    "failed to obtain all targets");
3213 			stl_hdr->stl_out_cnt = stl_hdr->stl_in_cnt;
3214 		}
3215 	}
3216 
3217 	(void) close(fd);
3218 
3219 	/* allocate for caller return buffer */
3220 	*ppList = (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *)calloc(1,
3221 	    sizeof (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES) +
3222 	    stl_hdr->stl_out_cnt * sizeof (SUN_IMA_DISC_ADDRESS_KEY));
3223 	if (*ppList == NULL) {
3224 		free(stl_hdr);
3225 		return (IMA_ERROR_INSUFFICIENT_MEMORY);
3226 	}
3227 
3228 	(*ppList)->keyCount = stl_hdr->stl_out_cnt;
3229 
3230 	for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) {
3231 		(void) mbstowcs((*ppList)->keys[ctr].name,
3232 		    (char *)stl_hdr->stl_list[ctr].ste_name,
3233 		    IMA_NODE_NAME_LEN);
3234 
3235 		(*ppList)->keys[ctr].tpgt = stl_hdr->stl_list[ctr].ste_tpgt;
3236 
3237 		(*ppList)->keys[ctr].address.portNumber =
3238 		    stl_hdr->stl_list[ctr].ste_ipaddr.a_port;
3239 
3240 		if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize ==
3241 		    sizeof (struct in_addr)) {
3242 			(*ppList)->keys[ctr].address.ipAddress.ipv4Address =
3243 			    IMA_TRUE;
3244 		} else if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize ==
3245 		    sizeof (struct in6_addr)) {
3246 			(*ppList)->keys[ctr].address.ipAddress.ipv4Address =
3247 			    IMA_FALSE;
3248 		} else {
3249 			free(stl_hdr);
3250 			syslog(LOG_USER|LOG_DEBUG,
3251 			"ISCSI_STATIC_GET returned bad address");
3252 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3253 		}
3254 
3255 
3256 		(void) memcpy(&(*ppList)->keys[ctr].address.ipAddress.ipAddress,
3257 		    &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr),
3258 		    stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize);
3259 	}
3260 	free(stl_hdr);
3261 
3262 	return (IMA_STATUS_SUCCESS);
3263 }
3264 
SUN_IMA_GetTunableProperties(IMA_OID oid,ISCSI_TUNABLE_PARAM * param)3265 IMA_API IMA_STATUS SUN_IMA_GetTunableProperties(
3266 	IMA_OID oid,
3267 	ISCSI_TUNABLE_PARAM *param)
3268 {
3269 	int fd;
3270 	iscsi_tunable_object_t pg;
3271 
3272 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3273 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
3274 		    ISCSI_DRIVER_DEVCTL, errno);
3275 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3276 	}
3277 	(void) memset(&pg, 0, sizeof (iscsi_tunable_object_t));
3278 	pg.t_param = param->tunable_objectType;
3279 	pg.t_oid = (uint32_t)oid.objectSequenceNumber;
3280 	if (ioctl(fd, ISCSI_TUNABLE_PARAM_GET, &pg) == -1) {
3281 		syslog(LOG_USER|LOG_DEBUG,
3282 		    "ISCSI_TUNABLE_PARAM_GET ioctl failed, errno: %d", errno);
3283 		(void) close(fd);
3284 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3285 	} else {
3286 		long long value;
3287 		char tmp[MAX_LONG_LONG_STRING_LEN], *ptr = NULL;
3288 		if (pg.t_set == B_FALSE) {
3289 			/* default value */
3290 			(void) close(fd);
3291 			return (IMA_STATUS_SUCCESS);
3292 		}
3293 		value = (long long)pg.t_value.v_integer;
3294 		ptr = lltostr(value, &tmp[MAX_LONG_LONG_STRING_LEN -1]);
3295 		if ((ptr != NULL) && (ptr != tmp)) {
3296 			tmp[MAX_LONG_LONG_STRING_LEN - 1] = '\0';
3297 		} else {
3298 			(void) close(fd);
3299 			return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3300 		}
3301 		switch (param->tunable_objectType) {
3302 			case ISCSI_RX_TIMEOUT_VALUE:
3303 				(void) strlcpy(param->tunable_objectValue,
3304 				    ptr, strlen(ptr) + 1);
3305 				break;
3306 			case ISCSI_CONN_DEFAULT_LOGIN_MAX:
3307 				(void) strlcpy(param->tunable_objectValue,
3308 				    ptr, strlen(ptr) + 1);
3309 				break;
3310 			case ISCSI_LOGIN_POLLING_DELAY:
3311 				(void) strlcpy(param->tunable_objectValue,
3312 				    ptr, strlen(ptr) + 1);
3313 				break;
3314 			default:
3315 				break;
3316 		}
3317 	}
3318 	(void) close(fd);
3319 	return (IMA_STATUS_SUCCESS);
3320 }
3321 
SUN_IMA_SetTunableProperties(IMA_OID oid,ISCSI_TUNABLE_PARAM * param)3322 IMA_API IMA_STATUS SUN_IMA_SetTunableProperties(
3323 	IMA_OID oid,
3324 	ISCSI_TUNABLE_PARAM *param)
3325 {
3326 	int fd;
3327 	iscsi_tunable_object_t	ps;
3328 
3329 	if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3330 		syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
3331 		    ISCSI_DRIVER_DEVCTL, errno);
3332 		return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3333 	}
3334 
3335 	(void) memset(&ps, 0, sizeof (iscsi_tunable_object_t));
3336 	ps.t_oid = oid.objectSequenceNumber;
3337 	ps.t_param = param->tunable_objectType;
3338 	switch (param->tunable_objectType) {
3339 		long tmp;
3340 		case ISCSI_RX_TIMEOUT_VALUE:
3341 		case ISCSI_CONN_DEFAULT_LOGIN_MAX:
3342 		case ISCSI_LOGIN_POLLING_DELAY:
3343 			tmp = strtol(param->tunable_objectValue,
3344 			    NULL, 10);
3345 			if (((tmp == 0) && (errno == EINVAL)) ||
3346 			    ((tmp == LONG_MAX) && (errno == ERANGE)) ||
3347 			    ((tmp == LONG_MIN) && (errno == ERANGE))) {
3348 				(void) close(fd);
3349 				return (IMA_ERROR_INVALID_PARAMETER);
3350 			}
3351 			ps.t_value.v_integer = (uint32_t)tmp;
3352 			break;
3353 		default:
3354 			break;
3355 	}
3356 	if (ioctl(fd, ISCSI_TUNABLE_PARAM_SET, &ps)) {
3357 		int tmpErrno = errno;
3358 		syslog(LOG_USER|LOG_DEBUG,
3359 		    "ISCSI_TUNABLE_PARAM_SET ioctl failed, errno: %d", errno);
3360 		(void) close(fd);
3361 		switch (tmpErrno) {
3362 			case ENOTSUP :
3363 				return (IMA_ERROR_NOT_SUPPORTED);
3364 			default:
3365 				return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3366 		}
3367 	}
3368 	(void) close(fd);
3369 	return (IMA_STATUS_SUCCESS);
3370 }
3371