libuutil: move under bmake
[unleashed.git] / usr / src / cmd / iscsiadm / sun_ima.c
blobbe763baddd3546c9f020f81a011a1e017128733b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <arpa/inet.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <unistd.h>
33 #include <syslog.h>
34 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <time.h>
39 #include <libdevinfo.h>
41 #include <sys/scsi/adapters/iscsi_if.h>
42 #include <sys/scsi/adapters/iscsi_door.h>
43 #include <sys/iscsi_protocol.h>
44 #include <ima.h>
45 #include "iscsiadm.h"
46 #include "sun_ima.h"
48 #define LIBRARY_PROPERTY_SUPPORTED_IMA_VERSION 1
49 #define LIBRARY_PROPERTY_IMPLEMENTATION_VERSION L"1.0.0"
50 #define LIBRARY_PROPERTY_VENDOR L"Sun Microsystems, Inc."
51 #define DEFAULT_NODE_NAME_FORMAT "iqn.2003-13.com.ima.%s"
52 #define PLUGIN_OWNER 1
53 #define MAX_CHAP_SECRET_LEN 16
55 /* LINTED E_STATIC_UNUSED */
56 static IMA_INT32 number_of_plugins = -1;
57 /* LINTED E_STATIC_UNUSED */
58 static IMA_NODE_NAME sharedNodeName;
59 /* LINTED E_STATIC_UNUSED */
60 static IMA_NODE_ALIAS sharedNodeAlias;
61 /* LINTED E_STATIC_UNUSED */
62 static IMA_PLUGIN_PROPERTIES PluginProperties;
64 /* LINTED E_STATIC_UNUSED */
65 static IMA_OID pluginOid;
66 static IMA_OID lhbaObjectId;
67 /* LINTED E_STATIC_UNUSED */
68 static boolean_t pluginInit = B_FALSE;
70 /* Forward declaration */
71 #define BOOL_PARAM 1
72 #define MIN_MAX_PARAM 2
73 #define PARAM_OP_OK 0
74 #define PARAM_OP_FAILED 1
76 static int open_driver(int *fd);
77 static IMA_STATUS getISCSINodeParameter(int paramType,
78 IMA_OID *oid,
79 void *pProps,
80 uint32_t paramIndex);
81 static IMA_STATUS setISCSINodeParameter(int paramType,
82 IMA_OID *oid,
83 void *pProps,
84 uint32_t paramIndex);
85 static IMA_STATUS getDigest(IMA_OID oid, int ioctlCmd,
86 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm);
87 static IMA_STATUS setAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount,
88 const IMA_AUTHMETHOD *pMethodList);
89 static IMA_STATUS getAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount,
90 IMA_AUTHMETHOD *pMethodList);
91 IMA_STATUS getNegotiatedDigest(int digestType,
92 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm,
93 SUN_IMA_CONN_PROPERTIES *connProps);
95 /* OK */
96 #define DISC_ADDR_OK 0
97 /* Incorrect IP address */
98 #define DISC_ADDR_INTEGRITY_ERROR 1
99 /* Error converting text IP address to numeric binary form */
100 #define DISC_ADDR_IP_CONV_ERROR 2
101 static int prepare_discovery_entry(SUN_IMA_TARGET_ADDRESS discoveryAddress,
102 entry_t *entry);
103 static int prepare_discovery_entry_IMA(IMA_TARGET_ADDRESS discoveryAddress,
104 entry_t *entry);
106 /* LINTED E_STATIC_UNUSED */
107 static IMA_STATUS configure_discovery_method(IMA_BOOL enable,
108 iSCSIDiscoveryMethod_t method);
110 static IMA_STATUS get_target_oid_list(uint32_t targetListType,
111 IMA_OID_LIST **ppList);
113 static IMA_STATUS get_target_lun_oid_list(IMA_OID * targetOid,
114 iscsi_lun_list_t **ppLunList);
116 static int get_lun_devlink(di_devlink_t link, void *arg);
118 static IMA_STATUS getConnOidList(
119 IMA_OID *oid,
120 iscsi_conn_list_t **ppConnList);
122 static IMA_STATUS getConnProps(
123 iscsi_if_conn_t *pConn,
124 iscsi_conn_props_t **ppConnProps);
126 /* LINTED E_STATIC_UNUSED */
127 static void libSwprintf(wchar_t *wcs, const wchar_t *lpszFormat, ...)
129 va_list args;
130 va_start(args, lpszFormat);
131 (void) vswprintf(wcs, 255, lpszFormat, args);
132 va_end(args);
136 char *
137 _strlwr(char *s)
139 char *t = s;
140 while (t != NULL && *t) {
141 if (*t >= 'A' && *t <= 'Z')
142 *t += 32;
143 t++;
145 return (s);
148 /* LINTED E_STATIC_UNUSED */
149 static void GetBuildTime(IMA_DATETIME* pdatetime)
151 #if defined(BUILD_DATE)
152 if (strptime(BUILD_DATE, "%Y/%m/%d %T %Z", pdatetime) == NULL) {
153 (void) memset(pdatetime, 0, sizeof (IMA_DATETIME));
155 #else
156 (void) memset(pdatetime, 0, sizeof (IMA_DATETIME));
157 #endif
161 * Non-IMA defined function.
163 IMA_API IMA_STATUS SUN_IMA_GetDiscoveryAddressPropertiesList(
164 SUN_IMA_DISC_ADDR_PROP_LIST **ppList
167 char discovery_addr_str[256];
168 int fd;
169 int i;
170 int discovery_addr_list_size;
171 int status;
172 int out_cnt;
173 iscsi_addr_list_t *ialp;
174 /* LINTED E_FUNC_SET_NOT_USED */
175 IMA_IP_ADDRESS *ipAddr;
177 if ((status = open_driver(&fd))) {
178 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
181 ialp = (iscsi_addr_list_t *)calloc(1, sizeof (iscsi_addr_list_t));
182 if (ialp == NULL) {
183 (void) close(fd);
184 return (IMA_ERROR_INSUFFICIENT_MEMORY);
187 ialp->al_vers = ISCSI_INTERFACE_VERSION;
188 ialp->al_in_cnt = ialp->al_out_cnt = 1;
191 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl
192 * We have allocated space for one entry, if more than one
193 * address is going to be returned, we will re-issue the ioctl
195 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, ialp) != 0) {
196 (void) close(fd);
197 syslog(LOG_USER|LOG_DEBUG,
198 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno: %d",
199 errno);
200 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
203 if (ialp->al_out_cnt > 1) {
205 * we need to allocate more space, save off the out_cnt
206 * and free ialp
208 out_cnt = ialp->al_out_cnt;
209 free(ialp);
211 discovery_addr_list_size = sizeof (iscsi_addr_list_t);
212 discovery_addr_list_size += (sizeof (iscsi_addr_t) *
213 out_cnt - 1);
214 ialp = (iscsi_addr_list_t *)calloc(1, discovery_addr_list_size);
215 if (ialp == NULL) {
216 (void) close(fd);
217 return (IMA_ERROR_INSUFFICIENT_MEMORY);
219 ialp->al_vers = ISCSI_INTERFACE_VERSION;
220 ialp->al_in_cnt = out_cnt;
223 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl again to obtain all
224 * the discovery addresses.
226 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, ialp) != 0) {
227 #define ERROR_STR "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno :%d"
228 free(ialp);
229 (void) close(fd);
230 syslog(LOG_USER|LOG_DEBUG,
231 ERROR_STR, errno);
232 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
233 #undef ERROR_STR
238 *ppList = (SUN_IMA_DISC_ADDR_PROP_LIST *)calloc(1,
239 sizeof (SUN_IMA_DISC_ADDR_PROP_LIST) +
240 ialp->al_out_cnt * sizeof (IMA_DISCOVERY_ADDRESS_PROPERTIES));
241 if (*ppList == NULL) {
242 free(ialp);
243 (void) close(fd);
244 return (IMA_ERROR_INSUFFICIENT_MEMORY);
246 (*ppList)->discAddrCount = ialp->al_out_cnt;
248 for (i = 0; i < ialp->al_out_cnt; i++) {
249 if (ialp->al_addrs[i].a_addr.i_insize ==
250 sizeof (struct in_addr)) {
252 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.
253 id.ipAddress.ipv4Address = IMA_TRUE;
255 } else if (ialp->al_addrs[i].a_addr.i_insize ==
256 sizeof (struct in6_addr)) {
258 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.
259 id.ipAddress.ipv4Address = IMA_FALSE;
261 } else {
262 (void) strlcpy(discovery_addr_str, "unknown",
263 sizeof (discovery_addr_str));
266 ipAddr = &(*ppList)->props[i].discoveryAddress.
267 hostnameIpAddress.id.ipAddress;
269 bcopy(&ialp->al_addrs[i].a_addr.i_addr,
270 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.id.
271 ipAddress.ipAddress,
272 sizeof (ipAddr->ipAddress));
274 (*ppList)->props[i].discoveryAddress.portNumber =
275 ialp->al_addrs[i].a_port;
278 free(ialp);
279 (void) close(fd);
280 return (IMA_STATUS_SUCCESS);
283 IMA_API IMA_STATUS SUN_IMA_GetStaticTargetProperties(
284 IMA_OID staticTargetOid,
285 SUN_IMA_STATIC_TARGET_PROPERTIES *pProps
288 int fd;
289 int status;
290 iscsi_static_property_t prop;
291 /* LINTED */
292 IMA_IP_ADDRESS *ipAddr;
294 if ((status = open_driver(&fd))) {
295 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
298 (void) memset(&prop, 0, sizeof (iscsi_static_property_t));
299 prop.p_vers = ISCSI_INTERFACE_VERSION;
300 prop.p_oid = (uint32_t)staticTargetOid.objectSequenceNumber;
301 if (ioctl(fd, ISCSI_STATIC_GET, &prop) != 0) {
302 status = errno;
303 (void) close(fd);
304 syslog(LOG_USER|LOG_DEBUG,
305 "ISCSI_STATIC_GET ioctl failed, errno: %d", status);
306 if (status == ENOENT) {
307 return (IMA_ERROR_OBJECT_NOT_FOUND);
308 } else {
309 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
312 (void) close(fd);
314 (void) mbstowcs(pProps->staticTarget.targetName, (char *)prop.p_name,
315 sizeof (pProps->staticTarget.targetName)/sizeof (IMA_WCHAR));
317 if (prop.p_addr_list.al_addrs[0].a_addr.i_insize ==
318 sizeof (struct in_addr)) {
319 /* IPv4 */
320 pProps->staticTarget.targetAddress.imaStruct.hostnameIpAddress.
321 id.ipAddress.ipv4Address = IMA_TRUE;
322 } else if (prop.p_addr_list.al_addrs[0].a_addr.i_insize ==
323 sizeof (struct in6_addr)) {
324 /* IPv6 */
325 pProps->staticTarget.targetAddress.imaStruct.hostnameIpAddress.
326 id.ipAddress.ipv4Address = IMA_FALSE;
327 } else {
328 /* Should not happen */
329 syslog(LOG_USER|LOG_DEBUG,
330 "ISCSI_STATIC_GET returned bad address");
331 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
334 ipAddr = &pProps->staticTarget.targetAddress.imaStruct.
335 hostnameIpAddress.id.ipAddress;
337 bcopy(&prop.p_addr_list.al_addrs[0].a_addr.i_addr,
338 pProps->staticTarget.targetAddress.imaStruct.hostnameIpAddress.id.
339 ipAddress.ipAddress, sizeof (ipAddr->ipAddress));
341 pProps->staticTarget.targetAddress.imaStruct.portNumber =
342 prop.p_addr_list.al_addrs[0].a_port;
345 if (prop.p_addr_list.al_tpgt == (uint32_t)ISCSI_DEFAULT_TPGT) {
346 pProps->staticTarget.targetAddress.defaultTpgt = IMA_TRUE;
347 pProps->staticTarget.targetAddress.tpgt = 0;
348 } else {
349 pProps->staticTarget.targetAddress.defaultTpgt = IMA_FALSE;
350 pProps->staticTarget.targetAddress.tpgt =
351 prop.p_addr_list.al_tpgt;
354 return (IMA_STATUS_SUCCESS);
357 /*ARGSUSED*/
358 IMA_API IMA_STATUS SUN_IMA_AddStaticTarget(
359 IMA_OID lhbaOid,
360 const SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig,
361 IMA_OID *pTargetOid
364 iscsi_target_entry_t target;
365 int fd;
366 int target_in_addr_size;
367 int status;
368 union {
369 struct in_addr u_in4;
370 struct in6_addr u_in6;
371 } target_in;
374 * staticConfig.address may come in with port number at its trailer.
375 * Parse it to separate the IP address and port number.
376 * Also translate the hostname to IP address if needed.
379 if (staticConfig.targetAddress.imaStruct.hostnameIpAddress.id.ipAddress.
380 ipv4Address == IMA_FALSE) {
382 bcopy(staticConfig.targetAddress.imaStruct.hostnameIpAddress.
383 id.ipAddress.ipAddress, &target_in.u_in6,
384 sizeof (target_in.u_in6));
386 target_in_addr_size = sizeof (struct in6_addr);
387 } else {
389 bcopy(staticConfig.targetAddress.imaStruct.hostnameIpAddress.
390 id.ipAddress.ipAddress, &target_in.u_in4,
391 sizeof (target_in.u_in4));
393 target_in_addr_size = sizeof (struct in_addr);
396 (void) memset(&target, 0, sizeof (iscsi_target_entry_t));
397 target.te_entry.e_vers = ISCSI_INTERFACE_VERSION;
398 target.te_entry.e_oid = ISCSI_OID_NOTSET;
400 (void) wcstombs((char *)target.te_name, staticConfig.targetName,
401 ISCSI_MAX_NAME_LEN);
403 target.te_entry.e_insize = target_in_addr_size;
404 if (target.te_entry.e_insize == sizeof (struct in_addr)) {
405 target.te_entry.e_u.u_in4.s_addr = target_in.u_in4.s_addr;
406 } else if (target.te_entry.e_insize == sizeof (struct in6_addr)) {
407 bcopy(target_in.u_in6.s6_addr,
408 target.te_entry.e_u.u_in6.s6_addr,
409 sizeof (struct in6_addr));
410 } else {
411 return (IMA_ERROR_INVALID_PARAMETER);
414 target.te_entry.e_port =
415 staticConfig.targetAddress.imaStruct.portNumber;
417 if (staticConfig.targetAddress.defaultTpgt == IMA_TRUE) {
418 target.te_entry.e_tpgt = ISCSI_DEFAULT_TPGT;
419 } else {
420 target.te_entry.e_tpgt = staticConfig.targetAddress.tpgt;
423 if ((status = open_driver(&fd))) {
424 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
427 if (ioctl(fd, ISCSI_STATIC_SET, &target)) {
429 * Encountered problem setting the IP address and port for
430 * the target just added.
432 syslog(LOG_USER|LOG_DEBUG,
433 "ISCSI_STATIC_SET ioctl failed, errno: %d", errno);
434 (void) close(fd);
435 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
438 pTargetOid->objectType = IMA_OBJECT_TYPE_TARGET;
439 pTargetOid->ownerId = 1;
440 pTargetOid->objectSequenceNumber = target.te_entry.e_oid;
442 (void) close(fd);
443 return (IMA_STATUS_SUCCESS);
446 IMA_API IMA_STATUS SUN_IMA_GetTargetProperties(
447 IMA_OID targetId,
448 SUN_IMA_TARGET_PROPERTIES *pProps
451 int fd;
452 int status;
453 iscsi_property_t prop;
455 if ((status = open_driver(&fd))) {
456 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
459 (void) memset(&prop, 0, sizeof (iscsi_property_t));
460 prop.p_vers = ISCSI_INTERFACE_VERSION;
461 prop.p_oid = (uint32_t)targetId.objectSequenceNumber;
463 if (ioctl(fd, ISCSI_TARGET_PROPS_GET, &prop) != 0) {
464 syslog(LOG_USER|LOG_DEBUG,
465 "ISCSI_TARGET_PROPS_GET ioctl failed, errno: %d", errno);
466 (void) close(fd);
467 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
470 (void) mbstowcs(pProps->imaProps.name,
471 (char *)prop.p_name, IMA_NODE_NAME_LEN);
472 (void) memset(pProps->imaProps.alias, 0,
473 (sizeof (IMA_WCHAR) * SUN_IMA_NODE_ALIAS_LEN));
474 if (prop.p_alias_len > 0) {
475 (void) mbstowcs(pProps->imaProps.alias, (char *)prop.p_alias,
476 SUN_IMA_NODE_ALIAS_LEN);
479 /* Initialize the discovery method to unknown method. */
480 pProps->imaProps.discoveryMethodFlags =
481 IMA_TARGET_DISCOVERY_METHOD_UNKNOWN;
482 if (!((prop.p_discovery & iSCSIDiscoveryMethodStatic) ^
483 iSCSIDiscoveryMethodStatic)) {
484 pProps->imaProps.discoveryMethodFlags |=
485 IMA_TARGET_DISCOVERY_METHOD_STATIC;
488 if (!((prop.p_discovery & iSCSIDiscoveryMethodSLP) ^
489 iSCSIDiscoveryMethodSLP)) {
490 pProps->imaProps.discoveryMethodFlags |=
491 IMA_TARGET_DISCOVERY_METHOD_SLP;
494 if (!((prop.p_discovery & iSCSIDiscoveryMethodISNS) ^
495 iSCSIDiscoveryMethodISNS)) {
496 pProps->imaProps.discoveryMethodFlags |=
497 iSCSIDiscoveryMethodISNS;
500 if (!((prop.p_discovery & iSCSIDiscoveryMethodSendTargets) ^
501 iSCSIDiscoveryMethodSendTargets)) {
502 pProps->imaProps.discoveryMethodFlags |=
503 iSCSIDiscoveryMethodSendTargets;
506 if (prop.p_tpgt_conf == ISCSI_DEFAULT_TPGT) {
507 pProps->defaultTpgtConf = IMA_TRUE;
508 pProps->tpgtConf = 0;
509 } else {
510 pProps->defaultTpgtConf = IMA_FALSE;
511 pProps->tpgtConf = prop.p_tpgt_conf;
514 if (prop.p_tpgt_nego == ISCSI_DEFAULT_TPGT) {
515 pProps->defaultTpgtNego = IMA_TRUE;
516 pProps->tpgtNego = 0;
517 } else {
518 pProps->defaultTpgtNego = IMA_FALSE;
519 pProps->tpgtNego = prop.p_tpgt_nego;
522 bcopy(prop.p_isid, pProps->isid, ISCSI_ISID_LEN);
524 (void) close(fd);
525 return (IMA_STATUS_SUCCESS);
529 * This function only sets CHAP params since we only support CHAP for now.
531 IMA_STATUS SUN_IMA_SetTargetAuthParams(
532 IMA_OID targetOid,
533 IMA_AUTHMETHOD method,
534 const IMA_INITIATOR_AUTHPARMS *pParms
537 int fd;
538 iscsi_chap_props_t chap_p;
540 if (method != IMA_AUTHMETHOD_CHAP)
541 return (IMA_ERROR_INVALID_PARAMETER);
543 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
544 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
545 ISCSI_DRIVER_DEVCTL, errno);
546 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
549 (void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t));
550 chap_p.c_vers = ISCSI_INTERFACE_VERSION;
551 chap_p.c_oid = (uint32_t)targetOid.objectSequenceNumber;
553 chap_p.c_user_len =
554 pParms->chapParms.nameLength;
555 (void) memcpy(chap_p.c_user,
556 pParms->chapParms.name, chap_p.c_user_len);
558 chap_p.c_secret_len =
559 pParms->chapParms.challengeSecretLength;
560 (void) memcpy(chap_p.c_secret,
561 pParms->chapParms.challengeSecret,
562 chap_p.c_secret_len);
564 if (ioctl(fd, ISCSI_CHAP_SET, &chap_p) != 0) {
565 syslog(LOG_USER|LOG_DEBUG,
566 "ISCSI_CHAP_SET ioctl failed, errno: %d", errno);
567 (void) close(fd);
568 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
571 return (IMA_STATUS_SUCCESS);
574 IMA_STATUS SUN_IMA_GetTargetAuthMethods(
575 IMA_OID lhbaOid,
576 IMA_OID targetOid,
577 IMA_UINT *pMethodCount,
578 IMA_AUTHMETHOD *pMethodList
581 if (getAuthMethods(targetOid, pMethodCount, pMethodList)
582 != IMA_STATUS_SUCCESS) {
583 return (getAuthMethods(lhbaOid, pMethodCount, pMethodList));
585 return (IMA_STATUS_SUCCESS);
588 IMA_STATUS SUN_IMA_SetInitiatorRadiusConfig(
589 IMA_OID lhbaOid,
590 SUN_IMA_RADIUS_CONFIG *config
593 int af;
594 int fd;
595 int status;
596 iscsi_radius_props_t radius;
597 union {
598 struct in_addr u_in4;
599 struct in6_addr u_in6;
600 } radius_in;
602 if ((status = open_driver(&fd))) {
603 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
606 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t));
607 radius.r_vers = ISCSI_INTERFACE_VERSION;
608 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber;
609 /* Get first because other data fields may already exist */
610 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) {
611 /* EMPTY */
612 /* It's fine if other data fields are not there. */
615 if (config->isIpv6 == IMA_TRUE) {
616 af = AF_INET6;
617 } else {
618 af = AF_INET;
621 if (inet_pton(af, config->hostnameIpAddress, &radius_in.u_in4) != 1) {
622 return (IMA_ERROR_INVALID_PARAMETER);
625 switch (af) {
626 case AF_INET:
627 radius.r_addr.u_in4.s_addr = radius_in.u_in4.s_addr;
628 radius.r_insize = sizeof (struct in_addr);
629 break;
630 case AF_INET6:
631 (void) memcpy(radius.r_addr.u_in6.s6_addr,
632 radius_in.u_in6.s6_addr, 16);
633 radius.r_insize = sizeof (struct in6_addr);
634 break;
636 radius.r_port = config->port;
637 radius.r_radius_config_valid = B_TRUE;
638 /* Allow resetting the RADIUS shared secret to NULL */
639 if (config->sharedSecretValid == IMA_TRUE) {
640 radius.r_shared_secret_len = config->sharedSecretLength;
641 (void) memset(&radius.r_shared_secret[0], 0,
642 MAX_RAD_SHARED_SECRET_LEN);
643 (void) memcpy(&radius.r_shared_secret[0], config->sharedSecret,
644 config->sharedSecretLength);
647 if (ioctl(fd, ISCSI_RADIUS_SET, &radius) != 0) {
648 syslog(LOG_USER|LOG_DEBUG,
649 "ISCSI_RADIUS_SET ioctl failed, errno: %d", errno);
650 (void) close(fd);
651 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
654 (void) close(fd);
655 return (IMA_STATUS_SUCCESS);
658 IMA_STATUS SUN_IMA_GetInitiatorRadiusConfig(
659 IMA_OID lhbaOid,
660 SUN_IMA_RADIUS_CONFIG *config
663 int af;
664 int fd;
665 int status;
666 iscsi_radius_props_t radius;
668 if ((status = open_driver(&fd))) {
669 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
672 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t));
673 radius.r_vers = ISCSI_INTERFACE_VERSION;
674 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber;
676 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) {
677 (void) close(fd);
678 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
681 (void) memset(config, 0, sizeof (SUN_IMA_RADIUS_CONFIG));
682 if (radius.r_insize == sizeof (struct in_addr)) {
683 /* IPv4 */
684 af = AF_INET;
685 } else if (radius.r_insize == sizeof (struct in6_addr)) {
686 /* IPv6 */
687 af = AF_INET6;
688 } else {
690 * It's legitimate that the existing RADIUS record does not
691 * have configuration data.
693 config->hostnameIpAddress[0] = '\0';
694 config->port = 0;
695 (void) close(fd);
696 return (IMA_STATUS_SUCCESS);
698 (void) inet_ntop(af, (void *)&radius.r_addr.u_in4,
699 config->hostnameIpAddress, 256);
700 config->port = radius.r_port;
701 (void) memcpy(config->sharedSecret, &radius.r_shared_secret[0],
702 radius.r_shared_secret_len);
703 config->sharedSecretLength = radius.r_shared_secret_len;
704 config->sharedSecretValid = B_TRUE;
706 (void) close(fd);
707 return (IMA_STATUS_SUCCESS);
710 IMA_STATUS SUN_IMA_SetInitiatorRadiusAccess(
711 IMA_OID lhbaOid,
712 IMA_BOOL radiusAccess
715 int fd;
716 int status;
717 iscsi_radius_props_t radius;
719 if ((status = open_driver(&fd))) {
720 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
723 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t));
724 radius.r_vers = ISCSI_INTERFACE_VERSION;
725 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber;
726 /* Get first because other data fields may already exist */
727 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) {
728 if (radiusAccess == IMA_TRUE) {
730 * Cannot enable RADIUS if no RADIUS configuration
731 * can be found.
733 syslog(LOG_USER|LOG_DEBUG,
734 "RADIUS config data not found - "
735 "cannot enable RADIUS, errno: %d", errno);
736 (void) close(fd);
737 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
738 } else {
739 /* EMPTY */
740 /* Otherwise it's fine to disable RADIUS */
744 if ((radius.r_insize != sizeof (struct in_addr)) &&
745 (radius.r_insize != sizeof (struct in6_addr))) {
747 * Cannot enable RADIUS if no RADIUS configuration
748 * can be found.
750 if (radiusAccess == IMA_TRUE) {
751 syslog(LOG_USER|LOG_DEBUG,
752 "RADIUS config data not found - "
753 "cannot enable RADIUS");
754 (void) close(fd);
755 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
759 radius.r_radius_access = (radiusAccess == IMA_TRUE) ?
760 B_TRUE : B_FALSE;
762 if (ioctl(fd, ISCSI_RADIUS_SET, &radius) != 0) {
763 syslog(LOG_USER|LOG_DEBUG,
764 "ISCSI_RADIUS_SET ioctl failed, errno: %d", errno);
765 (void) close(fd);
766 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
769 (void) close(fd);
770 return (IMA_STATUS_SUCCESS);
773 IMA_STATUS SUN_IMA_GetInitiatorRadiusAccess(
774 IMA_OID lhbaOid,
775 IMA_BOOL *radiusAccess
778 int fd;
779 int status;
780 iscsi_radius_props_t radius;
782 if ((status = open_driver(&fd))) {
783 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
786 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t));
787 radius.r_vers = ISCSI_INTERFACE_VERSION;
788 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber;
790 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) {
791 (void) close(fd);
792 if (errno == ENOENT) {
793 return (IMA_ERROR_OBJECT_NOT_FOUND);
794 } else {
795 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
799 *radiusAccess = (radius.r_radius_access == B_TRUE) ?
800 IMA_TRUE : IMA_FALSE;
802 (void) close(fd);
803 return (IMA_STATUS_SUCCESS);
806 IMA_STATUS SUN_IMA_SendTargets(
807 IMA_NODE_NAME nodeName,
808 IMA_TARGET_ADDRESS address,
809 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList
812 char *colonPos;
813 char discAddrStr[256];
814 char nodeNameStr[ISCSI_MAX_NAME_LEN];
815 int fd;
816 int ctr;
817 int stl_sz;
818 int status;
819 iscsi_sendtgts_list_t *stl_hdr = NULL;
820 IMA_BOOL retry = IMA_TRUE;
821 /* LINTED */
822 IMA_IP_ADDRESS *ipAddr;
824 #define SENDTGTS_DEFAULT_NUM_TARGETS 10
826 stl_sz = sizeof (*stl_hdr) + ((SENDTGTS_DEFAULT_NUM_TARGETS - 1) *
827 sizeof (iscsi_sendtgts_entry_t));
828 stl_hdr = (iscsi_sendtgts_list_t *)calloc(1, stl_sz);
829 if (stl_hdr == NULL) {
830 return (IMA_ERROR_INSUFFICIENT_MEMORY);
832 stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION;
833 stl_hdr->stl_in_cnt = SENDTGTS_DEFAULT_NUM_TARGETS;
835 (void) wcstombs(nodeNameStr, nodeName, ISCSI_MAX_NAME_LEN);
837 colonPos = strchr(discAddrStr, ':');
838 if (colonPos == NULL) {
839 /* IPv4 */
840 stl_hdr->stl_entry.e_insize = sizeof (struct in_addr);
841 } else {
842 /* IPv6 */
843 stl_hdr->stl_entry.e_insize = sizeof (struct in6_addr);
846 ipAddr = &address.hostnameIpAddress.id.ipAddress;
848 bcopy(address.hostnameIpAddress.id.ipAddress.ipAddress,
849 &stl_hdr->stl_entry.e_u, sizeof (ipAddr->ipAddress));
851 stl_hdr->stl_entry.e_port = address.portNumber;
853 if ((status = open_driver(&fd))) {
854 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
857 retry_sendtgts:
859 * Issue ioctl to obtain the SendTargets list
861 if (ioctl(fd, ISCSI_SENDTGTS_GET, stl_hdr) != 0) {
862 syslog(LOG_USER|LOG_DEBUG,
863 "ISCSI_SENDTGTS_GET ioctl failed, errno: %d", errno);
864 (void) close(fd);
865 free(stl_hdr);
866 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
869 /* check if all targets received */
870 if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) {
871 if (retry == IMA_TRUE) {
872 stl_sz = sizeof (*stl_hdr) +
873 ((stl_hdr->stl_out_cnt - 1) *
874 sizeof (iscsi_sendtgts_entry_t));
875 stl_hdr = (iscsi_sendtgts_list_t *)
876 realloc(stl_hdr, stl_sz);
877 if (stl_hdr == NULL) {
878 (void) close(fd);
879 return (IMA_ERROR_INSUFFICIENT_MEMORY);
881 stl_hdr->stl_in_cnt = stl_hdr->stl_out_cnt;
882 retry = IMA_FALSE;
883 goto retry_sendtgts;
884 } else {
886 * don't retry after 2 attempts. The target list
887 * shouldn't continue to growing. Justs continue
888 * on and display what was found.
890 syslog(LOG_USER|LOG_DEBUG,
891 "ISCSI_SENDTGTS_GET overflow: "
892 "failed to obtain all targets");
893 stl_hdr->stl_out_cnt = stl_hdr->stl_in_cnt;
897 (void) close(fd);
899 /* allocate for caller return buffer */
900 *ppList = (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *)calloc(1,
901 sizeof (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES) +
902 stl_hdr->stl_out_cnt * sizeof (SUN_IMA_DISC_ADDRESS_KEY));
903 if (*ppList == NULL) {
904 free(stl_hdr);
905 return (IMA_ERROR_INSUFFICIENT_MEMORY);
908 (*ppList)->keyCount = stl_hdr->stl_out_cnt;
910 for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) {
911 (void) mbstowcs((*ppList)->keys[ctr].name,
912 (char *)stl_hdr->stl_list[ctr].ste_name,
913 IMA_NODE_NAME_LEN);
915 (*ppList)->keys[ctr].tpgt = stl_hdr->stl_list[ctr].ste_tpgt;
917 (*ppList)->keys[ctr].address.portNumber =
918 stl_hdr->stl_list[ctr].ste_ipaddr.a_port;
920 if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize ==
921 sizeof (struct in_addr)) {
922 (*ppList)->keys[ctr].address.ipAddress.ipv4Address =
923 IMA_TRUE;
924 } else if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize ==
925 sizeof (struct in6_addr)) {
926 (*ppList)->keys[ctr].address.ipAddress.ipv4Address =
927 IMA_FALSE;
928 } else {
929 free(stl_hdr);
930 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
933 (void) memcpy(&(*ppList)->keys[ctr].address.ipAddress.ipAddress,
934 &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr),
935 stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize);
937 free(stl_hdr);
939 return (IMA_STATUS_SUCCESS);
942 IMA_STATUS SUN_IMA_SetTargetBidirAuthFlag(
943 IMA_OID targetOid,
944 IMA_BOOL *bidirAuthFlag
947 int fd;
948 int status;
949 iscsi_auth_props_t auth;
951 if ((status = open_driver(&fd))) {
952 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
955 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
956 auth.a_vers = ISCSI_INTERFACE_VERSION;
957 auth.a_oid = (uint32_t)targetOid.objectSequenceNumber;
958 /* Get first because other data fields may already exist */
959 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
960 /* EMPTY */
961 /* It is fine if there is no other data fields. */
963 auth.a_bi_auth = (*bidirAuthFlag == IMA_TRUE) ? B_TRUE : B_FALSE;
964 if (ioctl(fd, ISCSI_AUTH_SET, &auth) != 0) {
965 syslog(LOG_USER|LOG_DEBUG,
966 "ISCSI_AUTH_SET ioctl failed, errno: %d", errno);
967 (void) close(fd);
968 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
971 (void) close(fd);
972 return (IMA_STATUS_SUCCESS);
975 IMA_STATUS SUN_IMA_GetTargetBidirAuthFlag(
976 IMA_OID targetOid,
977 IMA_BOOL *bidirAuthFlag
980 int fd;
981 int status;
982 iscsi_auth_props_t auth;
984 if ((status = open_driver(&fd))) {
985 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
988 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
989 auth.a_vers = ISCSI_INTERFACE_VERSION;
990 auth.a_oid = (uint32_t)targetOid.objectSequenceNumber;
992 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
993 (void) close(fd);
994 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
997 *bidirAuthFlag = (auth.a_bi_auth == B_TRUE) ?
998 IMA_TRUE : IMA_FALSE;
1000 (void) close(fd);
1001 return (IMA_STATUS_SUCCESS);
1004 IMA_STATUS SUN_IMA_CreateTargetOid(
1005 IMA_NODE_NAME targetName,
1006 IMA_OID *targetOid
1009 int fd;
1010 int status;
1011 iscsi_oid_t oid;
1013 if ((status = open_driver(&fd))) {
1014 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1017 (void) memset(&oid, 0, sizeof (iscsi_oid_t));
1018 (void) wcstombs((char *)oid.o_name, targetName, ISCSI_MAX_NAME_LEN);
1019 oid.o_tpgt = ISCSI_DEFAULT_TPGT;
1020 oid.o_vers = ISCSI_INTERFACE_VERSION;
1021 if (ioctl(fd, ISCSI_CREATE_OID, &oid) == -1) {
1022 syslog(LOG_USER|LOG_DEBUG,
1023 "ISCSI_CREATE_OID ioctl failed, errno: %d", errno);
1024 (void) close(fd);
1025 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1028 targetOid->objectType = IMA_OBJECT_TYPE_TARGET;
1029 targetOid->ownerId = 1;
1030 targetOid->objectSequenceNumber = oid.o_oid;
1032 (void) close(fd);
1033 return (IMA_STATUS_SUCCESS);
1036 IMA_STATUS SUN_IMA_RemoveTargetParam(
1037 IMA_OID targetOid
1040 entry_t entry;
1041 int fd;
1042 int status;
1043 iscsi_auth_props_t auth_p;
1044 iscsi_chap_props_t chap_p;
1046 if ((status = open_driver(&fd))) {
1047 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1050 (void) memset(&entry, 0, sizeof (entry_t));
1051 entry.e_vers = ISCSI_INTERFACE_VERSION;
1052 entry.e_oid = (uint32_t)targetOid.objectSequenceNumber;
1053 if (ioctl(fd, ISCSI_TARGET_PARAM_CLEAR, &entry)) {
1055 * It could be that the target exists but the associated
1056 * target_param does not, and that is legitimate.
1058 syslog(LOG_USER|LOG_DEBUG,
1059 "ISCSI_TARGET_PARAM_CLEAR ioctl failed, errno: %d", errno);
1062 /* Issue ISCSI_CHAP_CLEAR ioctl */
1063 (void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t));
1064 chap_p.c_vers = ISCSI_INTERFACE_VERSION;
1065 chap_p.c_oid = (uint32_t)targetOid.objectSequenceNumber;
1066 if (ioctl(fd, ISCSI_CHAP_CLEAR, &chap_p) != 0) {
1068 * It could be that the CHAP of this target has never
1069 * been set.
1071 syslog(LOG_USER|LOG_DEBUG,
1072 "ISCSI_CHAP_CLEAR ioctl failed, errno: %d", errno);
1076 * Issue ISCSI_AUTH_CLEAR ioctl, in which the authentication information
1077 * is removed and the target that is not discovered by initiator
1078 * is removed from the memory. So this ioctl should be called at last
1080 (void) memset(&auth_p, 0, sizeof (iscsi_auth_props_t));
1081 auth_p.a_vers = ISCSI_INTERFACE_VERSION;
1082 auth_p.a_oid = (uint32_t)targetOid.objectSequenceNumber;
1083 if (ioctl(fd, ISCSI_AUTH_CLEAR, &auth_p) != 0) {
1085 * It could be that the auth data of this target has
1086 * never been set.
1088 syslog(LOG_USER|LOG_DEBUG,
1089 "ISCSI_AUTH_CLEAR ioctl failed, errno: %d", errno);
1092 (void) close(fd);
1093 return (IMA_STATUS_SUCCESS);
1096 IMA_API IMA_STATUS SUN_IMA_SetHeaderDigest(
1097 IMA_OID oid,
1098 IMA_UINT algorithmCount,
1099 const SUN_IMA_DIGEST_ALGORITHM *algorithmList
1102 IMA_MIN_MAX_VALUE mv;
1103 uint32_t digest_algorithm;
1105 /* We only support one preference of digest algorithm. */
1106 if (algorithmCount > 1) {
1107 syslog(LOG_USER|LOG_DEBUG,
1108 "More than one digest algorithm specified.");
1109 return (IMA_ERROR_NOT_SUPPORTED);
1111 switch (algorithmList[0]) {
1112 case SUN_IMA_DIGEST_NONE:
1113 digest_algorithm = ISCSI_DIGEST_NONE;
1114 break;
1115 case SUN_IMA_DIGEST_CRC32:
1116 digest_algorithm = ISCSI_DIGEST_CRC32C;
1117 break;
1118 default:
1119 digest_algorithm = ISCSI_DIGEST_NONE;
1120 break;
1122 mv.currentValue = digest_algorithm;
1123 return (setISCSINodeParameter(MIN_MAX_PARAM, &oid, &mv,
1124 ISCSI_LOGIN_PARAM_HEADER_DIGEST));
1127 IMA_API IMA_STATUS SUN_IMA_SetDataDigest(
1128 IMA_OID oid,
1129 IMA_UINT algorithmCount,
1130 const SUN_IMA_DIGEST_ALGORITHM *algorithmList
1133 IMA_MIN_MAX_VALUE mv;
1134 uint32_t digest_algorithm;
1136 /* We only support one preference of digest algorithm. */
1137 if (algorithmCount > 1) {
1138 syslog(LOG_USER|LOG_DEBUG,
1139 "More than one digest algorithm specified.");
1140 return (IMA_ERROR_NOT_SUPPORTED);
1142 switch (algorithmList[0]) {
1143 case SUN_IMA_DIGEST_NONE:
1144 digest_algorithm = ISCSI_DIGEST_NONE;
1145 break;
1146 case SUN_IMA_DIGEST_CRC32:
1147 digest_algorithm = ISCSI_DIGEST_CRC32C;
1148 break;
1149 default:
1150 digest_algorithm = ISCSI_DIGEST_NONE;
1151 break;
1153 mv.currentValue = digest_algorithm;
1154 return (setISCSINodeParameter(MIN_MAX_PARAM, &oid, &mv,
1155 ISCSI_LOGIN_PARAM_DATA_DIGEST));
1158 IMA_API IMA_STATUS SUN_IMA_GetHeaderDigest(
1159 IMA_OID oid,
1160 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm
1163 return (getDigest(oid, ISCSI_LOGIN_PARAM_HEADER_DIGEST, algorithm));
1166 IMA_API IMA_STATUS SUN_IMA_GetDataDigest(
1167 IMA_OID oid,
1168 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm
1171 return (getDigest(oid, ISCSI_LOGIN_PARAM_DATA_DIGEST, algorithm));
1174 typedef struct walk_devlink {
1175 char *path;
1176 size_t len;
1177 char **linkpp;
1178 } walk_devlink_t;
1180 IMA_STATUS SUN_IMA_GetLuProperties(
1181 IMA_OID luId,
1182 SUN_IMA_LU_PROPERTIES *pProps
1185 IMA_STATUS status;
1186 iscsi_lun_list_t *pLunList;
1187 int j;
1188 IMA_BOOL lunMatch = IMA_FALSE;
1189 int fd;
1190 int openStatus;
1191 iscsi_lun_props_t lun;
1192 di_devlink_handle_t hdl;
1193 walk_devlink_t warg;
1194 char *minor_path, *devlinkp, lunpath[MAXPATHLEN];
1196 if (luId.objectType != IMA_OBJECT_TYPE_LU) {
1197 return (IMA_ERROR_INCORRECT_OBJECT_TYPE);
1201 * get list of lun oids for all targets
1203 status = get_target_lun_oid_list(NULL, &pLunList);
1204 if (!IMA_SUCCESS(status)) {
1205 return (status);
1207 for (j = 0; j < pLunList->ll_out_cnt; j++) {
1209 * for each lun, check if match is found
1211 if (pLunList->ll_luns[j].l_oid == luId.objectSequenceNumber) {
1213 * match found, break out of lun loop
1215 lunMatch = IMA_TRUE;
1216 break;
1220 if (lunMatch == IMA_TRUE) {
1221 (void) memset(&lun, 0, sizeof (iscsi_lun_props_t));
1222 lun.lp_vers = ISCSI_INTERFACE_VERSION;
1223 lun.lp_tgt_oid = pLunList->ll_luns[j].l_tgt_oid;
1224 lun.lp_oid = pLunList->ll_luns[j].l_oid;
1227 free(pLunList);
1229 if (lunMatch == IMA_FALSE) {
1230 return (IMA_ERROR_OBJECT_NOT_FOUND);
1234 * get lun properties
1236 if ((openStatus = open_driver(&fd))) {
1237 return (SUN_IMA_ERROR_SYSTEM_ERROR | openStatus);
1240 if (ioctl(fd, ISCSI_LUN_PROPS_GET, &lun)) {
1241 syslog(LOG_USER|LOG_DEBUG,
1242 "ISCSI_LUN_PROPS_GET ioctl failed, errno: %d", errno);
1243 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1246 (void) close(fd);
1249 * set property values
1251 pProps->imaProps.associatedTargetOid.objectType =
1252 IMA_OBJECT_TYPE_TARGET;
1253 pProps->imaProps.associatedTargetOid.ownerId = 1;
1254 pProps->imaProps.associatedTargetOid.objectSequenceNumber = lun.lp_oid;
1255 pProps->imaProps.targetLun = (IMA_UINT64)lun.lp_num;
1256 (void) strncpy(pProps->vendorId, lun.lp_vid, SUN_IMA_LU_VENDOR_ID_LEN);
1257 (void) strncpy(pProps->productId, lun.lp_pid,
1258 SUN_IMA_LU_PRODUCT_ID_LEN);
1260 * lun.lp_status is defined as
1261 * LunValid = 0
1262 * LunDoesNotExist = 1
1263 * IMA_LU_PROPS.exposedtoOS is defined as an IMA_BOOL
1264 * IMA_TRUE = 1
1265 * IMA_FALSE = 0
1267 pProps->imaProps.exposedToOs = !lun.lp_status;
1268 if (gmtime_r(&lun.lp_time_online, &pProps->imaProps.timeExposedToOs)
1269 == NULL) {
1270 (void) memset(&pProps->imaProps.timeExposedToOs, 0,
1271 sizeof (pProps->imaProps.timeExposedToOs));
1274 if (lun.lp_status == LunValid) {
1275 if ((strlen(lun.lp_pathname) + strlen("/devices")) >
1276 (MAXPATHLEN -1)) {
1278 * lun.lp_pathname length too long
1280 pProps->imaProps.osDeviceNameValid = IMA_FALSE;
1281 pProps->imaProps.osParallelIdsValid = IMA_FALSE;
1282 return (IMA_STATUS_SUCCESS);
1284 if ((strstr(lun.lp_pathname, "st@") != NULL) ||
1285 (strstr(lun.lp_pathname, "tape@") != NULL)) {
1286 (void) strlcat(lun.lp_pathname, ":n", MAXPATHLEN);
1287 } else if ((strstr(lun.lp_pathname, "sd@") != NULL) ||
1288 (strstr(lun.lp_pathname, "ssd@") != NULL) ||
1289 (strstr(lun.lp_pathname, "disk@") != NULL)) {
1291 * modify returned pathname to obtain the 2nd slice
1292 * of the raw disk
1294 (void) strlcat(lun.lp_pathname, ":c,raw", MAXPATHLEN);
1295 } else if ((strstr(lun.lp_pathname, "ses@") != NULL) ||
1296 (strstr(lun.lp_pathname, "enclosure@") != NULL)) {
1297 (void) strlcat(lun.lp_pathname, ":0", MAXPATHLEN);
1300 (void) snprintf(lunpath, sizeof (lun.lp_pathname),
1301 "/devices%s", lun.lp_pathname);
1302 if (strchr(lunpath, ':')) {
1303 minor_path = lunpath;
1304 if (strstr(minor_path, "/devices") != NULL) {
1305 minor_path = lunpath +
1306 strlen("/devices");
1307 } else {
1308 minor_path = lunpath;
1310 warg.path = NULL;
1311 } else {
1312 minor_path = NULL;
1313 warg.len = strlen(lunpath);
1314 warg.path = lunpath;
1316 devlinkp = NULL;
1317 warg.linkpp = &devlinkp;
1320 * Pathname returned by driver is the physical device path.
1321 * This name needs to be converted to the OS device name.
1323 if (hdl = di_devlink_init(lun.lp_pathname, DI_MAKE_LINK)) {
1324 pProps->imaProps.osDeviceName[0] = L'\0';
1325 (void) di_devlink_walk(hdl, NULL, minor_path,
1326 DI_PRIMARY_LINK, (void *)&warg, get_lun_devlink);
1327 if (devlinkp != NULL) {
1328 (void) mbstowcs(pProps->imaProps.osDeviceName,
1329 devlinkp, MAXPATHLEN);
1330 free(devlinkp);
1331 pProps->imaProps.osDeviceNameValid = IMA_TRUE;
1332 } else {
1333 /* OS device name is asynchronously made */
1334 pProps->imaProps.osDeviceNameValid = IMA_FALSE;
1337 (void) di_devlink_fini(&hdl);
1339 } else {
1340 pProps->imaProps.osDeviceNameValid = IMA_FALSE;
1343 } else {
1344 pProps->imaProps.osDeviceNameValid = IMA_FALSE;
1347 pProps->imaProps.osParallelIdsValid = IMA_FALSE;
1349 return (IMA_STATUS_SUCCESS);
1352 static int
1353 get_lun_devlink(di_devlink_t link, void *arg)
1355 walk_devlink_t *warg = (walk_devlink_t *)arg;
1356 if (warg->path) {
1357 char *content = (char *)di_devlink_content(link);
1358 char *start = strstr(content, "/devices");
1359 if (start == NULL ||
1360 strncmp(start, warg->path, warg->len) != 0 ||
1361 start[warg->len] != ':')
1362 return (DI_WALK_CONTINUE);
1365 *(warg->linkpp) = strdup(di_devlink_path(link));
1366 return (DI_WALK_TERMINATE);
1371 * SUN_IMA_GetConnectionOidList -
1373 * Non-IMA defined function.
1375 IMA_API IMA_STATUS SUN_IMA_GetConnOidList(
1376 IMA_OID *oid,
1377 IMA_OID_LIST **ppList
1380 IMA_STATUS imaStatus;
1381 IMA_OID_LIST *imaOidList;
1382 iscsi_conn_list_t *iscsiConnList = NULL;
1383 int i;
1384 size_t allocLen;
1386 if ((lhbaObjectId.objectType == oid->objectType) &&
1387 (lhbaObjectId.ownerId == oid->ownerId) &&
1388 (lhbaObjectId.objectSequenceNumber == oid->objectSequenceNumber)) {
1389 imaStatus = getConnOidList(NULL, &iscsiConnList);
1390 } else {
1391 if (oid->objectType == IMA_OBJECT_TYPE_TARGET) {
1392 imaStatus = getConnOidList(oid, &iscsiConnList);
1393 } else {
1394 return (IMA_ERROR_INCORRECT_OBJECT_TYPE);
1397 if (imaStatus != IMA_STATUS_SUCCESS) {
1398 return (imaStatus);
1402 * Based on the results a SUN_IMA_CONN_LIST structure is allocated.
1404 allocLen = iscsiConnList->cl_out_cnt * sizeof (IMA_OID);
1405 allocLen += sizeof (IMA_OID_LIST) - sizeof (IMA_OID);
1406 imaOidList = (IMA_OID_LIST *)calloc(1, allocLen);
1408 if (imaOidList == NULL) {
1409 free(iscsiConnList);
1410 return (IMA_ERROR_INSUFFICIENT_MEMORY);
1413 /* The data is transfered from iscsiConnList to imaConnList. */
1414 imaOidList->oidCount = iscsiConnList->cl_out_cnt;
1415 for (i = 0; i < iscsiConnList->cl_out_cnt; i++) {
1416 imaOidList->oids[i].objectType = SUN_IMA_OBJECT_TYPE_CONN;
1417 imaOidList->oids[i].ownerId = 1;
1418 imaOidList->oids[i].objectSequenceNumber =
1419 iscsiConnList->cl_list[i].c_oid;
1421 /* The pointer to the SUN_IMA_CONN_LIST structure is returned. */
1422 *ppList = imaOidList;
1424 free(iscsiConnList);
1425 return (IMA_STATUS_SUCCESS);
1429 * SUN_IMA_GetConnProperties -
1431 * Non-IMA defined function.
1433 IMA_API IMA_STATUS SUN_IMA_GetConnProperties(
1434 IMA_OID *connOid,
1435 SUN_IMA_CONN_PROPERTIES **pProps
1438 iscsi_conn_list_t *pConnList;
1439 iscsi_conn_props_t *pConnProps;
1440 /* LINTED */
1441 struct sockaddr_in6 *addrIn6;
1442 /* LINTED */
1443 struct sockaddr_in *addrIn;
1444 SUN_IMA_CONN_PROPERTIES *pImaConnProps;
1445 IMA_STATUS imaStatus;
1446 int i;
1448 /* If there is any error *pProps should be set to NULL */
1449 *pProps = NULL;
1451 pImaConnProps = (SUN_IMA_CONN_PROPERTIES *)calloc(1,
1452 sizeof (SUN_IMA_CONN_PROPERTIES));
1454 if (pImaConnProps == NULL) {
1455 return (IMA_ERROR_INSUFFICIENT_MEMORY);
1458 imaStatus = getConnOidList(NULL, &pConnList);
1460 if (imaStatus != IMA_STATUS_SUCCESS) {
1461 free(pImaConnProps);
1462 return (imaStatus);
1466 * Walk the list returned to find our connection.
1468 for (i = 0; i < pConnList->cl_out_cnt; i++) {
1470 if (pConnList->cl_list[i].c_oid ==
1471 (uint32_t)connOid->objectSequenceNumber) {
1473 /* This is our connection. */
1474 imaStatus = getConnProps(&pConnList->cl_list[i],
1475 &pConnProps);
1477 if (imaStatus != IMA_STATUS_SUCCESS) {
1478 free(pConnList);
1479 free(pImaConnProps);
1480 return (imaStatus);
1482 pImaConnProps->connectionID = pConnProps->cp_cid;
1485 * Local Propeties
1487 if (pConnProps->cp_local.soa4.sin_family == AF_INET) {
1489 pImaConnProps->local.ipAddress.ipv4Address =
1490 IMA_TRUE;
1491 pImaConnProps->local.portNumber =
1492 pConnProps->cp_local.soa4.sin_port;
1493 addrIn = &(pConnProps->cp_local.soa4);
1494 bcopy(&pConnProps->cp_local.soa4.sin_addr,
1495 pImaConnProps->local.ipAddress.ipAddress,
1496 sizeof (addrIn->sin_addr));
1498 } else {
1499 pImaConnProps->local.ipAddress.ipv4Address =
1500 IMA_FALSE;
1501 pImaConnProps->local.portNumber =
1502 pConnProps->cp_local.soa6.sin6_port;
1503 addrIn6 = &(pConnProps->cp_local.soa6);
1504 bcopy(&pConnProps->cp_local.soa6.sin6_addr,
1505 pImaConnProps->local.ipAddress.ipAddress,
1506 sizeof (addrIn6->sin6_addr));
1511 * Peer Propeties
1513 if (pConnProps->cp_peer.soa4.sin_family == AF_INET) {
1515 pImaConnProps->peer.ipAddress.ipv4Address =
1516 IMA_TRUE;
1517 pImaConnProps->peer.portNumber =
1518 pConnProps->cp_peer.soa4.sin_port;
1519 addrIn = &(pConnProps->cp_local.soa4);
1520 bcopy(&pConnProps->cp_peer.soa4.sin_addr,
1521 pImaConnProps->peer.ipAddress.ipAddress,
1522 sizeof (addrIn->sin_addr));
1524 } else {
1525 pImaConnProps->peer.ipAddress.ipv4Address =
1526 IMA_FALSE;
1527 pImaConnProps->peer.portNumber =
1528 pConnProps->cp_peer.soa6.sin6_port;
1530 addrIn6 = &pConnProps->cp_local.soa6;
1531 bcopy(&pConnProps->cp_peer.soa6.sin6_addr,
1532 pImaConnProps->peer.ipAddress.ipAddress,
1533 sizeof (addrIn6->sin6_addr));
1537 pImaConnProps->valuesValid =
1538 pConnProps->cp_params_valid;
1539 pImaConnProps->defaultTime2Retain =
1540 pConnProps->cp_params.default_time_to_retain;
1541 pImaConnProps->defaultTime2Wait =
1542 pConnProps->cp_params.default_time_to_wait;
1543 pImaConnProps->errorRecoveryLevel =
1544 pConnProps->cp_params.error_recovery_level;
1545 pImaConnProps->firstBurstLength =
1546 pConnProps->cp_params.first_burst_length;
1547 pImaConnProps->maxBurstLength =
1548 pConnProps->cp_params.max_burst_length;
1549 pImaConnProps->maxConnections =
1550 pConnProps->cp_params.max_connections;
1551 pImaConnProps->maxOutstandingR2T =
1552 pConnProps->cp_params.max_outstanding_r2t;
1553 pImaConnProps->maxRecvDataSegmentLength =
1554 pConnProps->cp_params.max_recv_data_seg_len;
1556 pImaConnProps->dataPduInOrder =
1557 pConnProps->cp_params.data_pdu_in_order;
1558 pImaConnProps->dataSequenceInOrder =
1559 pConnProps->cp_params.data_sequence_in_order;
1560 pImaConnProps->immediateData =
1561 pConnProps->cp_params.immediate_data;
1562 pImaConnProps->initialR2T =
1563 pConnProps->cp_params.initial_r2t;
1565 pImaConnProps->headerDigest =
1566 pConnProps->cp_params.header_digest;
1567 pImaConnProps->dataDigest =
1568 pConnProps->cp_params.data_digest;
1570 free(pConnProps);
1571 break;
1574 free(pConnList);
1575 *pProps = pImaConnProps;
1576 return (IMA_STATUS_SUCCESS);
1581 * SUN_IMA_GetConfigSessions -
1583 * Non-IMA defined function.
1585 IMA_API IMA_STATUS SUN_IMA_GetConfigSessions(
1586 IMA_OID targetOid,
1587 SUN_IMA_CONFIG_SESSIONS **pConfigSessions
1590 int fd;
1591 int status;
1592 iscsi_config_sess_t *ics;
1593 int size, idx;
1595 /* Allocate and setup initial buffer */
1596 size = sizeof (*ics);
1597 ics = (iscsi_config_sess_t *)calloc(1, size);
1598 if (ics == NULL) {
1599 return (IMA_ERROR_INSUFFICIENT_MEMORY);
1601 ics->ics_ver = ISCSI_INTERFACE_VERSION;
1602 ics->ics_oid = targetOid.objectSequenceNumber;
1603 ics->ics_in = 1;
1605 /* Open driver devctl for ioctl */
1606 if ((status = open_driver(&fd))) {
1607 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1610 /* Issue ioctl request */
1611 if (ioctl(fd, ISCSI_GET_CONFIG_SESSIONS, ics) != 0) {
1612 syslog(LOG_USER|LOG_DEBUG,
1613 "ISCSI_GET_CONFIG_SESSIONS ioctl failed, errno: %d",
1614 errno);
1615 (void) close(fd);
1616 free(ics);
1617 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1620 /* Check if we need to collect more information */
1621 idx = ics->ics_out;
1622 if (idx > 1) {
1624 /* Free old buffer and reallocate re-sized buffer */
1625 free(ics);
1626 size = ISCSI_SESSION_CONFIG_SIZE(idx);
1627 ics = (iscsi_config_sess_t *)calloc(1, size);
1628 if (ics == NULL) {
1629 return (IMA_ERROR_INSUFFICIENT_MEMORY);
1631 ics->ics_ver = ISCSI_INTERFACE_VERSION;
1632 ics->ics_oid = targetOid.objectSequenceNumber;
1633 ics->ics_in = idx;
1635 /* Issue ioctl request */
1636 if (ioctl(fd, ISCSI_GET_CONFIG_SESSIONS, ics) != 0) {
1637 syslog(LOG_USER|LOG_DEBUG,
1638 "ISCSI_GET_CONFIG_SESSIONS ioctl failed, errno: %d",
1639 errno);
1640 (void) close(fd);
1641 free(ics);
1642 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1645 (void) close(fd);
1647 /* Allocate output buffer */
1648 size = sizeof (SUN_IMA_CONFIG_SESSIONS) +
1649 ((ics->ics_out - 1) * sizeof (IMA_ADDRESS_KEY));
1650 *pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size);
1651 if ((*pConfigSessions) == NULL) {
1652 return (IMA_ERROR_INSUFFICIENT_MEMORY);
1655 /* Copy output information */
1656 (*pConfigSessions)->bound =
1657 (ics->ics_bound == B_TRUE ? IMA_TRUE : IMA_FALSE);
1658 (*pConfigSessions)->in = ics->ics_in;
1659 (*pConfigSessions)->out = ics->ics_out;
1660 for (idx = 0; idx < ics->ics_in; idx++) {
1661 if (ics->ics_bindings[idx].i_insize ==
1662 sizeof (struct in_addr)) {
1663 (*pConfigSessions)->bindings[idx].ipAddress.
1664 ipv4Address = IMA_TRUE;
1665 bcopy(&ics->ics_bindings[idx].i_addr.in4,
1666 (*pConfigSessions)->bindings[idx].ipAddress.
1667 ipAddress, sizeof (struct in_addr));
1668 } else {
1669 (*pConfigSessions)->bindings[idx].ipAddress.
1670 ipv4Address = IMA_FALSE;
1671 bcopy(&ics->ics_bindings[idx].i_addr.in6,
1672 (*pConfigSessions)->bindings[idx].ipAddress.
1673 ipAddress, sizeof (struct in6_addr));
1677 free(ics);
1678 return (IMA_STATUS_SUCCESS);
1682 * SUN_IMA_SetConfigSessions -
1684 * Non-IMA defined function.
1686 IMA_API IMA_STATUS SUN_IMA_SetConfigSessions(
1687 IMA_OID targetOid,
1688 SUN_IMA_CONFIG_SESSIONS *pConfigSessions
1691 int fd;
1692 int status;
1693 iscsi_config_sess_t *ics;
1694 int idx, size;
1696 /* verify allowed range of sessions */
1697 if ((pConfigSessions->in < ISCSI_MIN_CONFIG_SESSIONS) ||
1698 (pConfigSessions->in > ISCSI_MAX_CONFIG_SESSIONS)) {
1699 return (IMA_ERROR_INVALID_PARAMETER);
1702 /* allocate record config_sess size */
1703 size = ISCSI_SESSION_CONFIG_SIZE(pConfigSessions->in);
1704 ics = (iscsi_config_sess_t *)malloc(size);
1706 /* setup config_sess information */
1707 (void) memset(ics, 0, sizeof (iscsi_config_sess_t));
1708 ics->ics_ver = ISCSI_INTERFACE_VERSION;
1709 ics->ics_oid = targetOid.objectSequenceNumber;
1710 ics->ics_bound =
1711 (pConfigSessions->bound == IMA_TRUE ? B_TRUE : B_FALSE);
1712 ics->ics_in = pConfigSessions->in;
1713 for (idx = 0; idx < ics->ics_in; idx++) {
1714 if (pConfigSessions->bindings[idx].ipAddress.
1715 ipv4Address == IMA_TRUE) {
1716 ics->ics_bindings[idx].i_insize =
1717 sizeof (struct in_addr);
1718 bcopy(pConfigSessions->bindings[idx].
1719 ipAddress.ipAddress,
1720 &ics->ics_bindings[idx].i_addr.in4,
1721 sizeof (struct in_addr));
1722 } else {
1723 ics->ics_bindings[idx].i_insize =
1724 sizeof (struct in6_addr);
1725 bcopy(pConfigSessions->bindings[idx].
1726 ipAddress.ipAddress,
1727 &ics->ics_bindings[idx].i_addr.in6,
1728 sizeof (struct in6_addr));
1732 /* open driver */
1733 if ((status = open_driver(&fd))) {
1734 free(ics);
1735 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1738 /* issue ioctl request */
1739 if (ioctl(fd, ISCSI_SET_CONFIG_SESSIONS, ics) != 0) {
1740 syslog(LOG_USER|LOG_DEBUG,
1741 "ISCSI_SET_CONFIG_SESSIONS ioctl failed, errno: %d",
1742 errno);
1743 (void) close(fd);
1744 free(ics);
1745 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1747 (void) close(fd);
1748 free(ics);
1749 return (IMA_STATUS_SUCCESS);
1752 /* A helper function to obtain iSCSI node parameters. */
1753 static IMA_STATUS
1754 getISCSINodeParameter(
1755 int paramType,
1756 IMA_OID *oid,
1757 void *pProps,
1758 uint32_t paramIndex
1761 int fd;
1762 int status;
1763 iscsi_param_get_t pg;
1765 if ((status = open_driver(&fd))) {
1766 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1769 (void) memset(&pg, 0, sizeof (iscsi_param_get_t));
1770 pg.g_vers = ISCSI_INTERFACE_VERSION;
1771 pg.g_oid = (uint32_t)oid->objectSequenceNumber;
1772 pg.g_param = paramIndex;
1773 pg.g_param_type = ISCSI_SESS_PARAM;
1775 if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) {
1776 syslog(LOG_USER|LOG_DEBUG,
1777 "ISCSI_PARAM_GET ioctl failed, errno: %d", errno);
1778 (void) close(fd);
1779 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1782 switch (paramType) {
1783 IMA_BOOL_VALUE *bp;
1784 IMA_MIN_MAX_VALUE *mp;
1786 case MIN_MAX_PARAM:
1787 mp = (IMA_MIN_MAX_VALUE *)pProps;
1789 mp->currentValueValid =
1790 (pg.g_value.v_valid == B_TRUE) ?
1791 IMA_TRUE : IMA_FALSE;
1792 mp->currentValue = pg.g_value.v_integer.i_current;
1793 mp->defaultValue = pg.g_value.v_integer.i_default;
1794 mp->minimumValue = pg.g_value.v_integer.i_min;
1795 mp->maximumValue = pg.g_value.v_integer.i_max;
1796 mp->incrementValue = pg.g_value.v_integer.i_incr;
1797 break;
1799 case BOOL_PARAM:
1800 bp = (IMA_BOOL_VALUE *)pProps;
1801 bp->currentValueValid =
1802 (pg.g_value.v_valid == B_TRUE) ?
1803 IMA_TRUE : IMA_FALSE;
1804 bp->currentValue = pg.g_value.v_bool.b_current;
1805 bp->defaultValue = pg.g_value.v_bool.b_default;
1806 break;
1808 default:
1809 break;
1812 /* Issue ISCSI_PARAM_GET ioctl again to obtain connection parameters. */
1813 pg.g_param_type = ISCSI_CONN_PARAM;
1814 if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) {
1815 syslog(LOG_USER|LOG_DEBUG,
1816 "ISCSI_PARAM_GET ioctl failed, errno: %d", errno);
1817 (void) close(fd);
1818 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1821 (void) close(fd);
1822 return (IMA_STATUS_SUCCESS);
1825 /* A helper function to set iSCSI node parameters. */
1826 static IMA_STATUS
1827 setISCSINodeParameter(
1828 int paramType,
1829 IMA_OID *oid,
1830 void *pProp,
1831 uint32_t paramIndex
1834 int fd;
1835 int status;
1836 iscsi_param_set_t ps;
1838 if ((status = open_driver(&fd))) {
1839 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1842 (void) memset(&ps, 0, sizeof (iscsi_param_set_t));
1843 ps.s_vers = ISCSI_INTERFACE_VERSION;
1844 ps.s_oid = (uint32_t)oid->objectSequenceNumber;
1845 ps.s_param = paramIndex;
1847 switch (paramType) {
1848 IMA_BOOL_VALUE *bp;
1849 IMA_MIN_MAX_VALUE *mp;
1851 case MIN_MAX_PARAM:
1852 mp = (IMA_MIN_MAX_VALUE *)pProp;
1853 ps.s_value.v_integer = mp->currentValue;
1854 break;
1855 case BOOL_PARAM:
1856 bp = (IMA_BOOL_VALUE *)pProp;
1857 ps.s_value.v_bool =
1858 (bp->currentValue == IMA_TRUE) ?
1859 B_TRUE : B_FALSE;
1860 break;
1862 default:
1863 break;
1865 if (ioctl(fd, ISCSI_PARAM_SET, &ps)) {
1866 (void) close(fd);
1867 syslog(LOG_USER|LOG_DEBUG,
1868 "ISCSI_PARAM_SET ioctl failed, errno: %d", errno);
1869 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1872 (void) close(fd);
1873 return (IMA_STATUS_SUCCESS);
1876 static int
1877 prepare_discovery_entry(
1878 SUN_IMA_TARGET_ADDRESS discoveryAddress,
1879 entry_t *entry
1882 return (prepare_discovery_entry_IMA(discoveryAddress.imaStruct, entry));
1885 static int
1886 prepare_discovery_entry_IMA(
1887 IMA_TARGET_ADDRESS discoveryAddress,
1888 entry_t *entry
1891 (void) memset(entry, 0, sizeof (entry_t));
1892 entry->e_vers = ISCSI_INTERFACE_VERSION;
1893 entry->e_oid = ISCSI_OID_NOTSET;
1895 if (discoveryAddress.hostnameIpAddress.id.ipAddress.
1896 ipv4Address == IMA_FALSE) {
1898 bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress.
1899 ipAddress, entry->e_u.u_in6.s6_addr,
1900 sizeof (entry->e_u.u_in6.s6_addr));
1902 entry->e_insize = sizeof (struct in6_addr);
1903 } else {
1905 bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress.
1906 ipAddress, &entry->e_u.u_in4.s_addr,
1907 sizeof (entry->e_u.u_in4.s_addr));
1909 entry->e_insize = sizeof (struct in_addr);
1912 entry->e_port = discoveryAddress.portNumber;
1913 entry->e_tpgt = 0;
1914 return (DISC_ADDR_OK);
1917 static IMA_STATUS configure_discovery_method(
1918 IMA_BOOL enable,
1919 iSCSIDiscoveryMethod_t method
1922 int fd, status;
1924 if ((status = open_driver(&fd))) {
1925 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1928 if (enable == IMA_FALSE) {
1929 if (ioctl(fd, ISCSI_DISCOVERY_CLEAR, &method)) {
1930 status = errno;
1931 (void) close(fd);
1932 syslog(LOG_USER|LOG_DEBUG,
1933 "ISCSI_DISCOVERY_CLEAR ioctl failed, errno: %d",
1934 status);
1935 if (status == EBUSY) {
1936 return (IMA_ERROR_LU_IN_USE);
1937 } else {
1938 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1942 (void) close(fd);
1943 return (IMA_STATUS_SUCCESS);
1944 } else {
1945 /* Set the discovery method */
1946 if (ioctl(fd, ISCSI_DISCOVERY_SET, &method)) {
1947 status = errno;
1948 (void) close(fd);
1949 syslog(LOG_USER|LOG_DEBUG,
1950 "ISCSI_DISCOVERY_SET ioctl failed, errno: %d",
1951 status);
1952 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
1955 (void) close(fd);
1956 return (IMA_STATUS_SUCCESS);
1960 /* LINTED E_STATIC_UNUSED */
1961 static IMA_BOOL authMethodMatch(
1962 IMA_AUTHMETHOD matchingMethod,
1963 IMA_AUTHMETHOD *methodList,
1964 IMA_UINT maxEntries
1967 IMA_UINT i;
1969 for (i = 0; i < maxEntries; i++) {
1970 if (methodList[i] == matchingMethod) {
1971 return (IMA_TRUE);
1975 return (IMA_FALSE);
1978 static IMA_STATUS get_target_oid_list(
1979 uint32_t targetListType,
1980 IMA_OID_LIST **ppList)
1982 int fd;
1983 int i;
1984 int target_list_size;
1985 int status;
1986 int out_cnt;
1987 iscsi_target_list_t *idlp;
1989 if ((status = open_driver(&fd))) {
1990 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
1993 idlp = (iscsi_target_list_t *)calloc(1, sizeof (iscsi_target_list_t));
1994 if (idlp == NULL) {
1995 (void) close(fd);
1996 return (IMA_ERROR_INSUFFICIENT_MEMORY);
1998 idlp->tl_vers = ISCSI_INTERFACE_VERSION;
1999 idlp->tl_in_cnt = idlp->tl_out_cnt = 1;
2000 idlp->tl_tgt_list_type = targetListType;
2003 * Issue ioctl. Space has been allocted for one entry.
2004 * If more than one entry should be returned, we will re-issue the
2005 * entry with the right amount of space allocted
2007 if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) {
2008 (void) close(fd);
2009 syslog(LOG_USER|LOG_DEBUG,
2010 "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d",
2011 targetListType, errno);
2012 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2014 if (idlp->tl_out_cnt > 1) {
2015 out_cnt = idlp->tl_out_cnt;
2016 free(idlp);
2018 target_list_size = sizeof (iscsi_target_list_t);
2019 target_list_size += (sizeof (uint32_t) * out_cnt - 1);
2020 idlp = (iscsi_target_list_t *)calloc(1, target_list_size);
2021 if (idlp == NULL) {
2022 (void) close(fd);
2023 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2025 idlp->tl_vers = ISCSI_INTERFACE_VERSION;
2026 idlp->tl_in_cnt = out_cnt;
2027 idlp->tl_tgt_list_type = targetListType;
2029 /* Issue the same ioctl again to obtain all the OIDs. */
2030 if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) {
2031 #define ERROR_STR "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno :%d"
2032 free(idlp);
2033 (void) close(fd);
2034 syslog(LOG_USER|LOG_DEBUG,
2035 ERROR_STR, targetListType, errno);
2036 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2037 #undef ERROR_STR
2042 *ppList = (IMA_OID_LIST *)calloc(1, sizeof (IMA_OID_LIST) +
2043 idlp->tl_out_cnt * sizeof (IMA_OID));
2044 (*ppList)->oidCount = idlp->tl_out_cnt;
2045 for (i = 0; i < idlp->tl_out_cnt; i++) {
2046 (*ppList)->oids[i].objectType = IMA_OBJECT_TYPE_TARGET;
2047 (*ppList)->oids[i].ownerId = 1;
2048 (*ppList)->oids[i].objectSequenceNumber = idlp->tl_oid_list[i];
2051 free(idlp);
2052 (void) close(fd);
2053 return (IMA_STATUS_SUCCESS);
2056 static IMA_STATUS get_target_lun_oid_list(
2057 IMA_OID * targetOid,
2058 iscsi_lun_list_t **ppLunList)
2060 int fd;
2061 iscsi_lun_list_t *illp, *illp_saved;
2062 int lun_list_size;
2063 int status;
2065 if ((status = open_driver(&fd))) {
2066 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2069 illp = (iscsi_lun_list_t *)calloc(1, sizeof (iscsi_lun_list_t));
2070 if (illp == NULL) {
2071 (void) close(fd);
2072 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2074 illp->ll_vers = ISCSI_INTERFACE_VERSION;
2075 if (targetOid == NULL) {
2076 /* get lun oid list for all targets */
2077 illp->ll_all_tgts = B_TRUE;
2078 } else {
2079 /* get lun oid list for single target */
2080 illp->ll_all_tgts = B_FALSE;
2081 illp->ll_tgt_oid = (uint32_t)targetOid->objectSequenceNumber;
2083 illp->ll_in_cnt = illp->ll_out_cnt = 1;
2086 * Issue ioctl to retrieve the target luns. Space has been allocted
2087 * for one entry. If more than one entry should be returned, we
2088 * will re-issue the entry with the right amount of space allocted
2090 if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) {
2091 (void) close(fd);
2092 syslog(LOG_USER|LOG_DEBUG,
2093 "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", errno);
2094 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2097 if (illp->ll_out_cnt > 1) {
2098 illp_saved = illp;
2099 lun_list_size = sizeof (iscsi_lun_list_t);
2100 lun_list_size += (sizeof (iscsi_if_lun_t) *
2101 (illp->ll_out_cnt - 1));
2102 illp = (iscsi_lun_list_t *)calloc(1, lun_list_size);
2103 if (illp == NULL) {
2104 (void) close(fd);
2105 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2107 illp->ll_vers = ISCSI_INTERFACE_VERSION;
2108 illp->ll_all_tgts = illp_saved->ll_all_tgts;
2109 illp->ll_tgt_oid = illp_saved->ll_tgt_oid;
2110 illp->ll_in_cnt = illp_saved->ll_out_cnt;
2112 free(illp_saved);
2114 /* Issue the same ioctl again to get all the target LUN list */
2115 if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) {
2116 free(illp);
2117 (void) close(fd);
2118 syslog(LOG_USER|LOG_DEBUG,
2119 "ISCSI_LUN_LIST_GET ioctl failed, errno: %d",
2120 errno);
2121 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2125 *ppLunList = illp;
2128 (void) close(fd);
2129 return (IMA_STATUS_SUCCESS);
2132 /* A helper function to obtain digest algorithms. */
2133 static IMA_STATUS
2134 getDigest(
2135 IMA_OID oid,
2136 int ioctlCmd,
2137 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm
2140 IMA_MIN_MAX_VALUE pProps;
2141 IMA_STATUS status;
2143 if ((status = getISCSINodeParameter(MIN_MAX_PARAM, &oid, &pProps,
2144 ioctlCmd)) != IMA_STATUS_SUCCESS) {
2145 return (status);
2148 switch (pProps.defaultValue) {
2149 case ISCSI_DIGEST_NONE:
2150 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_NONE;
2151 algorithm->defaultAlgorithmCount = 1;
2152 break;
2153 case ISCSI_DIGEST_CRC32C:
2154 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_CRC32C;
2155 algorithm->defaultAlgorithmCount = 1;
2156 break;
2158 case ISCSI_DIGEST_CRC32C_NONE:
2159 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_CRC32C;
2160 algorithm->defaultAlgorithms[1] = ISCSI_DIGEST_NONE;
2161 algorithm->defaultAlgorithmCount = 2;
2162 break;
2163 case ISCSI_DIGEST_NONE_CRC32C:
2164 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_NONE;
2165 algorithm->defaultAlgorithms[1] = ISCSI_DIGEST_CRC32C;
2166 algorithm->defaultAlgorithmCount = 2;
2167 break;
2168 default:
2169 /* Error */
2170 syslog(LOG_USER|LOG_DEBUG,
2171 "Invalid default digest: %d", pProps.defaultValue);
2172 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2175 /* The configured value */
2176 if (pProps.currentValueValid == IMA_TRUE) {
2177 algorithm->currentValid = IMA_TRUE;
2179 switch (pProps.currentValue) {
2180 case ISCSI_DIGEST_NONE:
2181 algorithm->currentAlgorithms[0] =
2182 ISCSI_DIGEST_NONE;
2183 algorithm->currentAlgorithmCount = 1;
2184 break;
2185 case ISCSI_DIGEST_CRC32C:
2186 algorithm->currentAlgorithms[0] =
2187 ISCSI_DIGEST_CRC32C;
2188 algorithm->currentAlgorithmCount = 1;
2189 break;
2191 case ISCSI_DIGEST_CRC32C_NONE:
2192 algorithm->currentAlgorithms[0] =
2193 ISCSI_DIGEST_CRC32C;
2194 algorithm->currentAlgorithms[1] =
2195 ISCSI_DIGEST_NONE;
2196 algorithm->currentAlgorithmCount = 2;
2197 break;
2198 case ISCSI_DIGEST_NONE_CRC32C:
2199 algorithm->currentAlgorithms[0] =
2200 ISCSI_DIGEST_NONE;
2201 algorithm->currentAlgorithms[1] =
2202 ISCSI_DIGEST_CRC32C;
2203 algorithm->currentAlgorithmCount = 2;
2204 break;
2205 default:
2206 /* Error */
2207 syslog(LOG_USER|LOG_DEBUG,
2208 "Invalid configured digest: %d",
2209 pProps.defaultValue);
2210 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2213 } else {
2214 algorithm->currentValid = IMA_FALSE;
2217 return (IMA_STATUS_SUCCESS);
2221 * getConnOidList -
2223 static IMA_STATUS getConnOidList(
2224 IMA_OID *sessOid,
2225 iscsi_conn_list_t **ppConnList
2228 iscsi_conn_list_t *iscsiConnList = NULL;
2229 size_t allocLen;
2230 int fd;
2231 int status;
2232 int out_cnt;
2234 /* Preset it to NULL to prepare for the case of failure */
2235 *ppConnList = NULL;
2237 /* We try to open the driver now. */
2238 if ((status = open_driver(&fd))) {
2239 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2242 iscsiConnList = (iscsi_conn_list_t *)calloc(1,
2243 sizeof (iscsi_conn_list_t));
2244 if (iscsiConnList == NULL) {
2245 (void) close(fd);
2246 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2248 iscsiConnList->cl_vers = ISCSI_INTERFACE_VERSION;
2249 iscsiConnList->cl_in_cnt = iscsiConnList->cl_out_cnt = 1;
2250 if (sessOid == NULL) {
2251 iscsiConnList->cl_all_sess = B_TRUE;
2252 } else {
2253 iscsiConnList->cl_all_sess = B_FALSE;
2254 iscsiConnList->cl_sess_oid =
2255 (uint32_t)sessOid->objectSequenceNumber;
2258 * Issue ioctl to retrieve the connection OIDs. Space has been
2259 * allocated for one entry. If more than one entry should be
2260 * returned, we will re-issue the entry with the right amount of
2261 * space allocted
2263 if (ioctl(fd, ISCSI_CONN_OID_LIST_GET, iscsiConnList) != 0) {
2264 syslog(LOG_USER|LOG_DEBUG,
2265 "ISCSI_CONN_OID_LIST_GET ioctl failed, errno: %d", errno);
2266 *ppConnList = NULL;
2267 (void) close(fd);
2268 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2270 if (iscsiConnList->cl_out_cnt > 1) {
2271 out_cnt = iscsiConnList->cl_out_cnt;
2272 free(iscsiConnList);
2274 allocLen = sizeof (iscsi_conn_list_t);
2275 allocLen += (sizeof (iscsi_if_conn_t) * out_cnt - 1);
2276 iscsiConnList = (iscsi_conn_list_t *)calloc(1, allocLen);
2277 if (iscsiConnList == NULL) {
2278 *ppConnList = NULL;
2279 (void) close(fd);
2280 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2282 iscsiConnList->cl_vers = ISCSI_INTERFACE_VERSION;
2283 iscsiConnList->cl_in_cnt = out_cnt;
2284 if (sessOid == NULL) {
2285 iscsiConnList->cl_all_sess = B_TRUE;
2286 } else {
2287 iscsiConnList->cl_all_sess = B_FALSE;
2288 iscsiConnList->cl_sess_oid =
2289 (uint32_t)sessOid->objectSequenceNumber;
2291 /* Issue the same ioctl again to obtain all the OIDs */
2292 if (ioctl(fd, ISCSI_CONN_OID_LIST_GET, iscsiConnList) != 0) {
2294 syslog(LOG_USER|LOG_DEBUG,
2295 "ISCSI_CONN_OID_LIST_GET ioctl failed, errno: %d",
2296 errno);
2297 *ppConnList = NULL;
2298 free(iscsiConnList);
2299 (void) close(fd);
2300 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2304 if (out_cnt < iscsiConnList->cl_out_cnt) {
2306 * The connection list grew between the first and second
2307 * ioctls.
2309 syslog(LOG_USER|LOG_DEBUG,
2310 "The connection list has grown. There could be "
2311 "more connections than listed.");
2316 (void) close(fd);
2317 *ppConnList = iscsiConnList;
2318 return (IMA_STATUS_SUCCESS);
2322 * getConnProps -
2324 static IMA_STATUS getConnProps(
2325 iscsi_if_conn_t *pConn,
2326 iscsi_conn_props_t **ppConnProps
2329 iscsi_conn_props_t *iscsiConnProps;
2330 int fd;
2331 int status;
2333 /* We try to open the driver. */
2334 if ((status = open_driver(&fd))) {
2335 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2338 iscsiConnProps = (iscsi_conn_props_t *)calloc(1,
2339 sizeof (*iscsiConnProps));
2341 if (iscsiConnProps == NULL) {
2342 (void) close(fd);
2343 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2346 iscsiConnProps->cp_vers = ISCSI_INTERFACE_VERSION;
2347 iscsiConnProps->cp_oid = pConn->c_oid;
2348 iscsiConnProps->cp_cid = pConn->c_cid;
2349 iscsiConnProps->cp_sess_oid = pConn->c_sess_oid;
2351 /* The IOCTL is submitted. */
2352 if (ioctl(fd, ISCSI_CONN_PROPS_GET, iscsiConnProps) != 0) {
2353 /* IOCTL failed */
2354 syslog(LOG_USER|LOG_DEBUG,
2355 "ISCSI_AUTH_CLEAR ioctl failed, errno: %d", errno);
2356 free(iscsiConnProps);
2357 (void) close(fd);
2358 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2360 (void) close(fd);
2361 *ppConnProps = iscsiConnProps;
2362 return (IMA_STATUS_SUCCESS);
2365 /* A helper function to set authentication method. */
2366 static IMA_STATUS
2367 setAuthMethods(
2368 IMA_OID oid,
2369 IMA_UINT *pMethodCount,
2370 const IMA_AUTHMETHOD *pMethodList
2373 int fd;
2374 int i;
2375 int status;
2376 iscsi_auth_props_t auth;
2378 if ((status = open_driver(&fd))) {
2379 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2381 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
2382 auth.a_vers = ISCSI_INTERFACE_VERSION;
2383 auth.a_oid = (uint32_t)oid.objectSequenceNumber;
2386 * Get the current auth fields so they don't need to be reset
2387 * here.
2389 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
2390 /* EMPTY */
2391 /* Initializing auth structure with current settings */
2393 auth.a_auth_method = authMethodNone;
2395 for (i = 0; i < *pMethodCount; i++) {
2396 switch (pMethodList[i]) {
2397 case IMA_AUTHMETHOD_CHAP:
2398 auth.a_auth_method |= authMethodCHAP;
2399 break;
2400 default:
2401 break;
2405 if (ioctl(fd, ISCSI_AUTH_SET, &auth) != 0) {
2406 syslog(LOG_USER|LOG_DEBUG,
2407 "ISCSI_AUTH_SET failed, errno: %d", errno);
2408 (void) close(fd);
2409 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2412 (void) close(fd);
2413 return (IMA_STATUS_SUCCESS);
2416 /* A helper function to set authentication method. */
2417 static IMA_STATUS getAuthMethods(
2418 IMA_OID oid,
2419 IMA_UINT *pMethodCount,
2420 IMA_AUTHMETHOD *pMethodList
2423 int fd;
2424 int status;
2425 iscsi_auth_props_t auth;
2427 if ((status = open_driver(&fd))) {
2428 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2431 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t));
2432 auth.a_vers = ISCSI_INTERFACE_VERSION;
2433 auth.a_oid = (uint32_t)oid.objectSequenceNumber;
2435 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) {
2436 syslog(LOG_USER|LOG_DEBUG,
2437 "ISCSI_AUTH_GET failed, errno: %d", errno);
2438 (void) close(fd);
2439 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2442 if (auth.a_auth_method == authMethodNone) {
2443 pMethodList[0] = IMA_AUTHMETHOD_NONE;
2444 *pMethodCount = 1;
2445 } else {
2446 int i = 0;
2447 if (!((auth.a_auth_method & authMethodCHAP)^authMethodCHAP)) {
2448 pMethodList[i++] = IMA_AUTHMETHOD_CHAP;
2450 *pMethodCount = i;
2453 (void) close(fd);
2454 return (IMA_STATUS_SUCCESS);
2457 /* Helper function to open driver */
2458 int open_driver(
2459 int *fd
2462 int ret = 0;
2463 if ((*fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
2464 ret = errno;
2465 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
2466 ISCSI_DRIVER_DEVCTL, ret);
2468 return (ret);
2472 * Iscsi driver does not support OID for discovery address. Create
2473 * a modified version of IMA_RemoveDiscoveryAddress that takes
2474 * discoveryAddress (instead of an OID) as input argument.
2476 IMA_API IMA_STATUS SUN_IMA_RemoveDiscoveryAddress(
2477 SUN_IMA_TARGET_ADDRESS discoveryAddress
2480 entry_t entry;
2481 int fd;
2482 int status, i, addr_list_size, insize;
2483 iscsi_addr_list_t *idlp, al_info;
2484 iscsi_addr_t *matched_addr = NULL;
2486 if ((status = open_driver(&fd))) {
2487 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2490 if (prepare_discovery_entry(discoveryAddress, &entry) !=
2491 DISC_ADDR_OK) {
2492 (void) close(fd);
2493 return (IMA_ERROR_INVALID_PARAMETER);
2496 (void) memset(&al_info, 0, sizeof (al_info));
2497 al_info.al_vers = ISCSI_INTERFACE_VERSION;
2498 al_info.al_in_cnt = 0;
2500 * Issue ioctl to get the number of discovery address.
2502 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) {
2503 syslog(LOG_USER|LOG_DEBUG,
2504 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d",
2505 ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
2506 (void) close(fd);
2507 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2510 if (al_info.al_out_cnt == 0) {
2511 (void) close(fd);
2512 return (IMA_ERROR_OBJECT_NOT_FOUND);
2515 addr_list_size = sizeof (iscsi_addr_list_t);
2516 if (al_info.al_out_cnt > 1) {
2517 addr_list_size += (sizeof (iscsi_addr_t) *
2518 (al_info.al_out_cnt - 1));
2521 idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size);
2522 if (idlp == NULL) {
2523 (void) close(fd);
2524 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2527 idlp->al_vers = ISCSI_INTERFACE_VERSION;
2528 idlp->al_in_cnt = al_info.al_out_cnt;
2530 /* issue the same ioctl to get all the discovery addresses */
2531 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) {
2532 syslog(LOG_USER|LOG_DEBUG,
2533 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d",
2534 ISCSI_DISCOVERY_ADDR_LIST_GET, errno);
2535 free(idlp);
2536 (void) close(fd);
2537 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2541 * find the matched discovery address
2543 for (i = 0; i < idlp->al_out_cnt; i++) {
2544 insize = idlp->al_addrs[i].a_addr.i_insize;
2545 if (insize != entry.e_insize) {
2546 continue;
2548 if (insize == sizeof (struct in_addr)) {
2549 if (idlp->al_addrs[i].a_addr.i_addr.in4.s_addr ==
2550 entry.e_u.u_in4.s_addr) {
2551 matched_addr = &(idlp->al_addrs[i]);
2552 break;
2555 if (insize == sizeof (struct in6_addr)) {
2556 if (bcmp(entry.e_u.u_in6.s6_addr,
2557 idlp->al_addrs[i].a_addr.i_addr.in6.s6_addr,
2558 insize) == 0) {
2559 matched_addr = &(idlp->al_addrs[i]);
2560 break;
2565 free(idlp);
2567 if (matched_addr == NULL) {
2568 (void) close(fd);
2569 return (IMA_ERROR_OBJECT_NOT_FOUND);
2572 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_CLEAR, &entry)) {
2573 status = errno;
2574 (void) close(fd);
2575 syslog(LOG_USER|LOG_DEBUG,
2576 "ISCSI_DISCOVERY_ADDR_CLEAR ioctl failed, errno: %d",
2577 errno);
2578 if (status == EBUSY) {
2579 return (IMA_ERROR_LU_IN_USE);
2580 } else {
2581 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2585 (void) close(fd);
2586 return (IMA_STATUS_SUCCESS);
2589 IMA_STATUS SUN_IMA_SetTargetAuthMethods(
2590 IMA_OID targetOid,
2591 IMA_UINT *methodCount,
2592 const IMA_AUTHMETHOD *pMethodList
2595 return (setAuthMethods(targetOid, methodCount, pMethodList));
2598 IMA_STATUS getNegotiatedDigest(
2599 int digestType,
2600 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm,
2601 SUN_IMA_CONN_PROPERTIES *connProps) {
2603 IMA_UINT digest;
2605 if (connProps->valuesValid == IMA_TRUE) {
2606 algorithm->negotiatedValid = IMA_TRUE;
2608 if (digestType == ISCSI_LOGIN_PARAM_HEADER_DIGEST) {
2609 digest = connProps->headerDigest;
2610 } else {
2611 digest = connProps->dataDigest;
2614 switch (digest) {
2615 case ISCSI_DIGEST_NONE:
2616 algorithm->negotiatedAlgorithms[0] =
2617 ISCSI_DIGEST_NONE;
2618 algorithm->negotiatedAlgorithmCount = 1;
2619 break;
2620 case ISCSI_DIGEST_CRC32C:
2621 algorithm->negotiatedAlgorithms[0] =
2622 ISCSI_DIGEST_CRC32C;
2623 algorithm->negotiatedAlgorithmCount = 1;
2624 break;
2626 case ISCSI_DIGEST_CRC32C_NONE:
2627 algorithm->negotiatedAlgorithms[0] =
2628 ISCSI_DIGEST_CRC32C;
2629 algorithm->negotiatedAlgorithms[1] =
2630 ISCSI_DIGEST_NONE;
2631 algorithm->negotiatedAlgorithmCount = 2;
2632 break;
2633 case ISCSI_DIGEST_NONE_CRC32C:
2634 algorithm->negotiatedAlgorithms[0] =
2635 ISCSI_DIGEST_NONE;
2636 algorithm->negotiatedAlgorithms[1] =
2637 ISCSI_DIGEST_CRC32C;
2638 algorithm->negotiatedAlgorithmCount = 2;
2639 break;
2640 default:
2641 syslog(LOG_USER|LOG_DEBUG,
2642 "Invalid negotiated digest: %d",
2643 digest);
2644 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2646 } else {
2647 algorithm->negotiatedValid = IMA_FALSE;
2649 return (IMA_STATUS_SUCCESS);
2653 * Non-IMA defined function.
2655 IMA_API IMA_STATUS SUN_IMA_GetISNSServerAddressPropertiesList(
2656 SUN_IMA_DISC_ADDR_PROP_LIST **ppList
2659 char isns_server_addr_str[256];
2660 int fd;
2661 int i;
2662 int isns_server_addr_list_size;
2663 int status;
2664 int out_cnt;
2665 iscsi_addr_list_t *ialp;
2666 /* LINTED */
2667 IMA_IP_ADDRESS *ipAddr;
2669 if ((status = open_driver(&fd))) {
2670 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2673 ialp = (iscsi_addr_list_t *)calloc(1, sizeof (iscsi_addr_list_t));
2674 if (ialp == NULL) {
2675 (void) close(fd);
2676 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2678 ialp->al_vers = ISCSI_INTERFACE_VERSION;
2679 ialp->al_in_cnt = ialp->al_out_cnt = 1;
2682 * Issue ioctl to retrieve the isns server addresses. Space has been
2683 * allocted for one entry. If more than one entry should be returned,
2684 * we will re-issue the entry with the right amount of space allocted
2686 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_LIST_GET, ialp) != 0) {
2687 (void) close(fd);
2688 syslog(LOG_USER|LOG_DEBUG,
2689 "ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl failed, errno: %d",
2690 errno);
2691 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2694 isns_server_addr_list_size = sizeof (iscsi_addr_list_t);
2695 if (ialp->al_out_cnt > 1) {
2696 out_cnt = ialp->al_out_cnt;
2697 free(ialp);
2699 isns_server_addr_list_size += (sizeof (iscsi_addr_t) *
2700 out_cnt - 1);
2701 ialp = (iscsi_addr_list_t *)calloc(1,
2702 isns_server_addr_list_size);
2703 if (ialp == NULL) {
2704 (void) close(fd);
2705 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2707 ialp->al_vers = ISCSI_INTERFACE_VERSION;
2708 ialp->al_in_cnt = out_cnt;
2711 * Issue ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl again to obtain
2712 * the list of all the iSNS server addresses
2714 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_LIST_GET, ialp) != 0) {
2715 free(ialp);
2716 (void) close(fd);
2717 syslog(LOG_USER|LOG_DEBUG,
2718 "ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl failed, "
2719 "errno: %d", errno);
2720 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2725 *ppList = (SUN_IMA_DISC_ADDR_PROP_LIST *)calloc(1,
2726 sizeof (SUN_IMA_DISC_ADDR_PROP_LIST) +
2727 ialp->al_out_cnt * sizeof (IMA_DISCOVERY_ADDRESS_PROPERTIES));
2728 if (*ppList == NULL) {
2729 free(ialp);
2730 (void) close(fd);
2731 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2733 (*ppList)->discAddrCount = ialp->al_out_cnt;
2735 for (i = 0; i < ialp->al_out_cnt; i++) {
2736 if (ialp->al_addrs[i].a_addr.i_insize ==
2737 sizeof (struct in_addr)) {
2738 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.
2739 id.ipAddress.ipv4Address = IMA_TRUE;
2740 } else if (ialp->al_addrs[i].a_addr.i_insize ==
2741 sizeof (struct in6_addr)) {
2742 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.
2743 id.ipAddress.ipv4Address = IMA_FALSE;
2744 } else {
2745 (void) strlcpy(isns_server_addr_str, "unknown",
2746 sizeof (isns_server_addr_str));
2749 ipAddr = &(*ppList)->props[i].discoveryAddress.
2750 hostnameIpAddress.id.ipAddress;
2751 bcopy(&ialp->al_addrs[i].a_addr.i_addr,
2752 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.id.
2753 ipAddress.ipAddress,
2754 sizeof (ipAddr->ipAddress));
2755 (*ppList)->props[i].discoveryAddress.portNumber =
2756 ialp->al_addrs[i].a_port;
2759 free(ialp);
2760 (void) close(fd);
2761 return (IMA_STATUS_SUCCESS);
2764 /*ARGSUSED*/
2766 * Remove iSNS Server Address
2768 IMA_API IMA_STATUS SUN_IMA_RemoveISNSServerAddress(
2769 SUN_IMA_TARGET_ADDRESS isnsServerAddress
2772 entry_t entry;
2773 int fd, status;
2775 if ((status = open_driver(&fd))) {
2776 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2779 if (prepare_discovery_entry(isnsServerAddress, &entry) !=
2780 DISC_ADDR_OK) {
2781 (void) close(fd);
2782 return (IMA_ERROR_INVALID_PARAMETER);
2785 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_CLEAR, &entry)) {
2786 status = errno;
2787 (void) close(fd);
2788 syslog(LOG_USER|LOG_DEBUG,
2789 "ISCSI_ISNS_SERVER_ADDR_CLEAR ioctl failed, errno: %d",
2790 status);
2791 if (status == EBUSY) {
2792 return (IMA_ERROR_LU_IN_USE);
2793 } else {
2794 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2798 (void) close(fd);
2799 return (IMA_STATUS_SUCCESS);
2802 /*ARGSUSED*/
2803 IMA_API IMA_STATUS SUN_IMA_AddISNSServerAddress(
2804 const SUN_IMA_TARGET_ADDRESS isnsServerAddress
2807 entry_t entry;
2808 int fd;
2809 int status;
2811 if ((status = open_driver(&fd))) {
2812 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2815 if (prepare_discovery_entry(isnsServerAddress, &entry) !=
2816 DISC_ADDR_OK) {
2817 (void) close(fd);
2818 return (IMA_ERROR_INVALID_PARAMETER);
2821 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_SET, &entry)) {
2823 * Encountered problem setting the discovery address.
2825 (void) close(fd);
2826 syslog(LOG_USER|LOG_DEBUG,
2827 "ISCSI_ISNS_SERVER_ADDR_SET ioctl failed, errno: %d",
2828 errno);
2829 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2832 (void) close(fd);
2833 return (IMA_STATUS_SUCCESS);
2836 IMA_STATUS SUN_IMA_RetrieveISNSServerTargets(
2837 IMA_TARGET_ADDRESS serverAddress,
2838 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList
2841 int fd;
2842 int ctr;
2843 int server_pg_list_sz;
2844 int status;
2845 isns_server_portal_group_list_t *server_pg_list = NULL;
2846 isns_portal_group_list_t *pg_list = NULL;
2847 IMA_BOOL retry = IMA_TRUE;
2848 entry_t entry;
2850 #define ISNS_SERVER_DEFAULT_NUM_TARGETS 50
2852 server_pg_list_sz = sizeof (*server_pg_list) +
2853 ((ISNS_SERVER_DEFAULT_NUM_TARGETS - 1) *
2854 sizeof (isns_portal_group_t));
2856 server_pg_list = (isns_server_portal_group_list_t *)calloc(1,
2857 server_pg_list_sz);
2858 if (server_pg_list == NULL) {
2859 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2861 server_pg_list->addr_port_list.pg_in_cnt =
2862 ISNS_SERVER_DEFAULT_NUM_TARGETS;
2864 if ((prepare_discovery_entry_IMA(serverAddress, &entry)
2865 != DISC_ADDR_OK)) {
2866 free(server_pg_list);
2867 return (IMA_ERROR_INVALID_PARAMETER);
2869 server_pg_list->addr.a_port = entry.e_port;
2870 server_pg_list->addr.a_addr.i_insize = entry.e_insize;
2871 if (entry.e_insize == sizeof (struct in_addr)) {
2872 server_pg_list->addr.a_addr.i_addr.in4.s_addr =
2873 (entry.e_u.u_in4.s_addr);
2874 } else if (entry.e_insize == sizeof (struct in6_addr)) {
2875 bcopy(&entry.e_u.u_in6.s6_addr,
2876 server_pg_list->addr.a_addr.i_addr.in6.s6_addr, 16);
2879 if ((status = open_driver(&fd))) {
2880 free(server_pg_list);
2881 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
2884 retry_isns:
2886 * Issue ioctl to obtain the ISNS Portal Group List list
2888 if (ioctl(fd, ISCSI_ISNS_SERVER_GET, server_pg_list) != 0) {
2889 int tmp_errno = errno;
2890 IMA_STATUS return_status;
2892 syslog(LOG_USER|LOG_DEBUG,
2893 "ISCSI_ISNS_SERVER_GET ioctl failed, errno: %d", tmp_errno);
2894 if (tmp_errno == EACCES) {
2895 return_status = IMA_ERROR_OBJECT_NOT_FOUND;
2896 } else {
2897 return_status = IMA_ERROR_UNEXPECTED_OS_ERROR;
2899 (void) close(fd);
2900 free(server_pg_list);
2901 return (return_status);
2903 pg_list = &server_pg_list->addr_port_list;
2905 /* check if all targets received */
2906 if (pg_list->pg_in_cnt < pg_list->pg_out_cnt) {
2907 if (retry == IMA_TRUE) {
2908 server_pg_list_sz = sizeof (*server_pg_list) +
2909 ((pg_list->pg_out_cnt - 1) *
2910 sizeof (isns_server_portal_group_list_t));
2911 server_pg_list = (isns_server_portal_group_list_t *)
2912 realloc(server_pg_list, server_pg_list_sz);
2913 if (server_pg_list == NULL) {
2914 (void) close(fd);
2915 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2917 pg_list = &server_pg_list->addr_port_list;
2918 pg_list->pg_in_cnt = pg_list->pg_out_cnt;
2919 retry = IMA_FALSE;
2920 goto retry_isns;
2921 } else {
2923 * don't retry after 2 attempts. The target list
2924 * shouldn't continue growing. Just continue
2925 * on and display what was found.
2927 syslog(LOG_USER|LOG_DEBUG,
2928 "ISCSI_SENDTGTS_GET overflow: "
2929 "failed to obtain all targets");
2930 pg_list->pg_out_cnt = pg_list->pg_in_cnt;
2934 (void) close(fd);
2936 /* allocate for caller return buffer */
2937 *ppList = (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *)calloc(1,
2938 sizeof (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES) +
2939 pg_list->pg_out_cnt * sizeof (SUN_IMA_DISC_ADDRESS_KEY));
2940 if (*ppList == NULL) {
2941 free(server_pg_list);
2942 return (IMA_ERROR_INSUFFICIENT_MEMORY);
2945 (*ppList)->keyCount = pg_list->pg_out_cnt;
2947 for (ctr = 0; ctr < pg_list->pg_out_cnt; ctr++) {
2948 (void) mbstowcs((*ppList)->keys[ctr].name,
2949 (char *)pg_list->pg_list[ctr].pg_iscsi_name,
2950 IMA_NODE_NAME_LEN);
2952 (*ppList)->keys[ctr].tpgt = pg_list->pg_list[ctr].pg_tag;
2954 (*ppList)->keys[ctr].address.portNumber =
2955 pg_list->pg_list[ctr].pg_port;
2957 if (pg_list->pg_list[ctr].insize == sizeof (struct in_addr)) {
2958 (*ppList)->keys[ctr].address.ipAddress.ipv4Address =
2959 IMA_TRUE;
2960 } else if (pg_list->pg_list[ctr].insize ==
2961 sizeof (struct in6_addr)) {
2962 (*ppList)->keys[ctr].address.ipAddress.ipv4Address =
2963 IMA_FALSE;
2964 } else {
2965 free(pg_list);
2966 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
2969 (void) memcpy(&(*ppList)->keys[ctr].address.ipAddress.ipAddress,
2970 &(pg_list->pg_list[ctr].pg_ip_addr),
2971 pg_list->pg_list[ctr].insize);
2973 free(server_pg_list);
2975 return (IMA_STATUS_SUCCESS);
2978 /* ARGSUSED */
2979 IMA_STATUS SUN_IMA_GetSessionOidList(
2980 IMA_OID initiatorOid,
2981 IMA_OID_LIST **ppList
2984 return (get_target_oid_list(ISCSI_TGT_OID_LIST, ppList));
2987 /*ARGSUSED*/
2988 IMA_API IMA_STATUS SUN_IMA_GetTargetAuthParms(
2989 IMA_OID oid,
2990 IMA_AUTHMETHOD method,
2991 IMA_INITIATOR_AUTHPARMS *pParms
2994 int fd;
2995 iscsi_chap_props_t chap_p;
2997 if (pParms == NULL) {
2998 return (IMA_ERROR_INVALID_PARAMETER);
3001 if (oid.objectType != IMA_OBJECT_TYPE_TARGET) {
3002 return (IMA_ERROR_INCORRECT_OBJECT_TYPE);
3005 if (method != IMA_AUTHMETHOD_CHAP) {
3006 return (IMA_ERROR_INVALID_PARAMETER);
3009 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3010 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)",
3011 ISCSI_DRIVER_DEVCTL, errno);
3012 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3015 (void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t));
3016 chap_p.c_vers = ISCSI_INTERFACE_VERSION;
3017 chap_p.c_oid = (uint32_t)oid.objectSequenceNumber;
3019 if (ioctl(fd, ISCSI_CHAP_GET, &chap_p) != 0) {
3020 syslog(LOG_USER|LOG_DEBUG,
3022 "ISCSI_CHAP_GET ioctl failed, errno: %d",
3023 errno);
3024 (void) close(fd);
3025 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3028 (void) memcpy(pParms->chapParms.name, chap_p.c_user,
3029 chap_p.c_user_len);
3031 pParms->chapParms.nameLength = chap_p.c_user_len;
3032 (void) memcpy(pParms->chapParms.challengeSecret, chap_p.c_secret,
3033 chap_p.c_secret_len);
3035 pParms->chapParms.challengeSecretLength = chap_p.c_secret_len;
3037 return (IMA_STATUS_SUCCESS);
3040 IMA_API IMA_STATUS SUN_IMA_GetBootTargetName(
3041 IMA_NODE_NAME tgtName
3044 int fd;
3045 IMA_STATUS rtn;
3046 iscsi_boot_property_t bootProp;
3048 bootProp.tgt_name.n_name[0] = '\0';
3049 bootProp.tgt_chap.c_user[0] = '\0';
3050 tgtName[0] = L'\0';
3051 rtn = IMA_ERROR_UNEXPECTED_OS_ERROR;
3052 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3053 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)",
3054 ISCSI_DRIVER_DEVCTL, errno);
3055 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3058 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) {
3059 syslog(LOG_USER|LOG_DEBUG,
3060 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d",
3061 errno);
3062 (void) close(fd);
3063 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3066 if ((bootProp.tgt_name.n_name[0] != '\0') && (tgtName != NULL)) {
3067 if (mbstowcs(tgtName, (const char *)bootProp.tgt_name.n_name,
3068 IMA_NODE_NAME_LEN) == (size_t)-1) {
3069 syslog(LOG_USER|LOG_DEBUG,
3070 "ISCSI Target name covert to WCHAR fail");
3071 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3072 } else {
3073 rtn = IMA_STATUS_SUCCESS;
3077 return (rtn);
3080 IMA_API IMA_STATUS SUN_IMA_GetBootTargetAuthParams(
3081 IMA_INITIATOR_AUTHPARMS *pTgtCHAP
3084 int fd;
3085 IMA_STATUS rtn;
3086 iscsi_boot_property_t bootProp;
3088 bootProp.tgt_name.n_name[0] = '\0';
3089 bootProp.tgt_chap.c_user[0] = '\0';
3090 bootProp.tgt_chap.c_secret[0] = '\0';
3091 rtn = IMA_ERROR_UNEXPECTED_OS_ERROR;
3092 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3093 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)",
3094 ISCSI_DRIVER_DEVCTL, errno);
3095 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3098 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) {
3099 syslog(LOG_USER|LOG_DEBUG,
3100 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d",
3101 errno);
3102 (void) close(fd);
3103 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3106 if (pTgtCHAP != NULL) {
3107 if (bootProp.tgt_chap.c_user[0] != '\0') {
3108 (void) memcpy(pTgtCHAP->chapParms.name,
3109 bootProp.tgt_chap.c_user, ISCSI_MAX_NAME_LEN);
3110 } else {
3111 pTgtCHAP->chapParms.name[0] = '\0';
3113 if (bootProp.tgt_chap.c_secret[0] != '\0') {
3114 (void) memcpy(pTgtCHAP->chapParms.challengeSecret,
3115 bootProp.tgt_chap.c_secret, MAX_CHAP_SECRET_LEN);
3116 } else {
3117 pTgtCHAP->chapParms.challengeSecret[0] = '\0';
3119 rtn = IMA_STATUS_SUCCESS;
3121 return (rtn);
3124 IMA_STATUS SUN_IMA_GetBootMpxio(
3125 IMA_BOOL *pMpxioEnabled
3128 int fd;
3129 iscsi_boot_property_t bootProp;
3131 bootProp.hba_mpxio_enabled = B_FALSE;
3132 *pMpxioEnabled = IMA_UNKNOWN;
3134 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3135 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)",
3136 ISCSI_DRIVER_DEVCTL, errno);
3137 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3140 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) {
3141 syslog(LOG_USER|LOG_DEBUG,
3142 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d",
3143 errno);
3144 (void) close(fd);
3145 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3148 if (bootProp.hba_mpxio_enabled) {
3149 *pMpxioEnabled = IMA_TRUE;
3150 } else {
3151 *pMpxioEnabled = IMA_FALSE;
3154 (void) close(fd);
3155 return (IMA_STATUS_SUCCESS);
3158 IMA_STATUS SUN_IMA_GetBootIscsi(
3159 IMA_BOOL *pIscsiBoot
3162 int fd;
3163 iscsi_boot_property_t bootProp;
3165 bootProp.iscsiboot = 0;
3166 *pIscsiBoot = 0;
3168 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3169 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)",
3170 ISCSI_DRIVER_DEVCTL, errno);
3171 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3174 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) {
3175 syslog(LOG_USER|LOG_DEBUG,
3176 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d",
3177 errno);
3178 (void) close(fd);
3179 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3182 *pIscsiBoot = bootProp.iscsiboot;
3184 (void) close(fd);
3185 return (IMA_STATUS_SUCCESS);
3188 IMA_STATUS SUN_IMA_GetSvcStatus(
3189 IMA_BOOL *pSvcEnabled)
3191 int fd;
3192 uint32_t status = ISCSI_SERVICE_DISABLED;
3194 if (pSvcEnabled == NULL)
3195 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3196 *pSvcEnabled = 0;
3198 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) {
3199 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)",
3200 ISCSI_DRIVER_DEVCTL, errno);
3201 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3204 if (ioctl(fd, ISCSI_SMF_GET, &status) != 0) {
3205 syslog(LOG_USER|LOG_DEBUG,
3206 "ISCSI_SVC_GET ioctl failed, errno: %d",
3207 errno);
3208 (void) close(fd);
3209 return (IMA_ERROR_UNEXPECTED_OS_ERROR);
3212 if (status == ISCSI_SERVICE_ENABLED) {
3213 *pSvcEnabled = 1;
3216 (void) close(fd);
3217 return (IMA_STATUS_SUCCESS);
3220 IMA_STATUS SUN_IMA_ReEnumeration(
3221 IMA_OID targetId
3224 int fd;
3225 int status;
3226 iscsi_reen_t reet;
3228 reet.re_ver = ISCSI_INTERFACE_VERSION;
3229 reet.re_oid = (uint32_t)targetId.objectSequenceNumber;
3231 if ((status = open_driver(&fd))) {
3232 return (SUN_IMA_ERROR_SYSTEM_ERROR | status);
3235 (void) ioctl(fd, ISCSI_TARGET_REENUM, &reet);
3237 (void) close(fd);
3239 return (IMA_STATUS_SUCCESS);