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 37 #include <fcntl.h> 38 #include <stdio.h> 39 #include <time.h> 40 #include <libdevinfo.h> 41 42 #include <sys/scsi/adapters/iscsi_if.h> 43 #include <sys/scsi/adapters/iscsi_door.h> 44 #include <sys/iscsi_protocol.h> 45 #include <ima.h> 46 #include "iscsiadm.h" 47 #include "sun_ima.h" 48 49 #define LIBRARY_PROPERTY_SUPPORTED_IMA_VERSION 1 50 #define LIBRARY_PROPERTY_IMPLEMENTATION_VERSION L"1.0.0" 51 #define LIBRARY_PROPERTY_VENDOR L"Sun Microsystems, Inc." 52 #define DEFAULT_NODE_NAME_FORMAT "iqn.2003-13.com.ima.%s" 53 #define PLUGIN_OWNER 1 54 #define MAX_CHAP_SECRET_LEN 16 55 56 /* LINTED E_STATIC_UNUSED */ 57 static IMA_INT32 number_of_plugins = -1; 58 /* LINTED E_STATIC_UNUSED */ 59 static IMA_NODE_NAME sharedNodeName; 60 /* LINTED E_STATIC_UNUSED */ 61 static IMA_NODE_ALIAS sharedNodeAlias; 62 /* LINTED E_STATIC_UNUSED */ 63 static IMA_PLUGIN_PROPERTIES PluginProperties; 64 65 /* LINTED E_STATIC_UNUSED */ 66 static IMA_OID pluginOid; 67 static IMA_OID lhbaObjectId; 68 /* LINTED E_STATIC_UNUSED */ 69 static boolean_t pluginInit = B_FALSE; 70 71 /* Forward declaration */ 72 #define BOOL_PARAM 1 73 #define MIN_MAX_PARAM 2 74 #define PARAM_OP_OK 0 75 #define PARAM_OP_FAILED 1 76 77 static int open_driver(int *fd); 78 static IMA_STATUS getISCSINodeParameter(int paramType, 79 IMA_OID *oid, 80 void *pProps, 81 uint32_t paramIndex); 82 static IMA_STATUS setISCSINodeParameter(int paramType, 83 IMA_OID *oid, 84 void *pProps, 85 uint32_t paramIndex); 86 static IMA_STATUS getDigest(IMA_OID oid, int ioctlCmd, 87 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm); 88 static IMA_STATUS setAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount, 89 const IMA_AUTHMETHOD *pMethodList); 90 static IMA_STATUS getAuthMethods(IMA_OID oid, IMA_UINT *pMethodCount, 91 IMA_AUTHMETHOD *pMethodList); 92 IMA_STATUS getNegotiatedDigest(int digestType, 93 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm, 94 SUN_IMA_CONN_PROPERTIES *connProps); 95 96 /* OK */ 97 #define DISC_ADDR_OK 0 98 /* Incorrect IP address */ 99 #define DISC_ADDR_INTEGRITY_ERROR 1 100 /* Error converting text IP address to numeric binary form */ 101 #define DISC_ADDR_IP_CONV_ERROR 2 102 static int prepare_discovery_entry(SUN_IMA_TARGET_ADDRESS discoveryAddress, 103 entry_t *entry); 104 static int prepare_discovery_entry_IMA(IMA_TARGET_ADDRESS discoveryAddress, 105 entry_t *entry); 106 107 /* LINTED E_STATIC_UNUSED */ 108 static IMA_STATUS configure_discovery_method(IMA_BOOL enable, 109 iSCSIDiscoveryMethod_t method); 110 111 static IMA_STATUS get_target_oid_list(uint32_t targetListType, 112 IMA_OID_LIST **ppList); 113 114 static IMA_STATUS get_target_lun_oid_list(IMA_OID * targetOid, 115 iscsi_lun_list_t **ppLunList); 116 117 static int get_lun_devlink(di_devlink_t link, void *arg); 118 119 static IMA_STATUS getConnOidList( 120 IMA_OID *oid, 121 iscsi_conn_list_t **ppConnList); 122 123 static IMA_STATUS getConnProps( 124 iscsi_if_conn_t *pConn, 125 iscsi_conn_props_t **ppConnProps); 126 127 /* LINTED E_STATIC_UNUSED */ 128 static void libSwprintf(wchar_t *wcs, const wchar_t *lpszFormat, ...) 129 { 130 va_list args; 131 va_start(args, lpszFormat); 132 (void) vswprintf(wcs, 255, lpszFormat, args); 133 va_end(args); 134 } 135 136 137 char * 138 _strlwr(char *s) 139 { 140 char *t = s; 141 while (t != NULL && *t) { 142 if (*t >= 'A' && *t <= 'Z') 143 *t += 32; 144 t++; 145 } 146 return (s); 147 } 148 149 /* LINTED E_STATIC_UNUSED */ 150 static void GetBuildTime(IMA_DATETIME* pdatetime) 151 { 152 #if defined(BUILD_DATE) 153 if (strptime(BUILD_DATE, "%Y/%m/%d %T %Z", pdatetime) == NULL) { 154 (void) memset(pdatetime, 0, sizeof (IMA_DATETIME)); 155 } 156 #else 157 (void) memset(pdatetime, 0, sizeof (IMA_DATETIME)); 158 #endif 159 } 160 161 /* 162 * Non-IMA defined function. 163 */ 164 IMA_API IMA_STATUS SUN_IMA_GetDiscoveryAddressPropertiesList( 165 SUN_IMA_DISC_ADDR_PROP_LIST **ppList 166 ) 167 { 168 char discovery_addr_str[256]; 169 int fd; 170 int i; 171 int discovery_addr_list_size; 172 int status; 173 int out_cnt; 174 iscsi_addr_list_t *ialp; 175 /* LINTED E_FUNC_SET_NOT_USED */ 176 IMA_IP_ADDRESS *ipAddr; 177 178 if ((status = open_driver(&fd))) { 179 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 180 } 181 182 ialp = (iscsi_addr_list_t *)calloc(1, sizeof (iscsi_addr_list_t)); 183 if (ialp == NULL) { 184 (void) close(fd); 185 return (IMA_ERROR_INSUFFICIENT_MEMORY); 186 } 187 188 ialp->al_vers = ISCSI_INTERFACE_VERSION; 189 ialp->al_in_cnt = ialp->al_out_cnt = 1; 190 191 /* 192 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl 193 * We have allocated space for one entry, if more than one 194 * address is going to be returned, we will re-issue the ioctl 195 */ 196 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, ialp) != 0) { 197 (void) close(fd); 198 syslog(LOG_USER|LOG_DEBUG, 199 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno: %d", 200 errno); 201 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 202 } 203 204 if (ialp->al_out_cnt > 1) { 205 /* 206 * we need to allocate more space, save off the out_cnt 207 * and free ialp 208 */ 209 out_cnt = ialp->al_out_cnt; 210 free(ialp); 211 212 discovery_addr_list_size = sizeof (iscsi_addr_list_t); 213 discovery_addr_list_size += (sizeof (iscsi_addr_t) * 214 out_cnt - 1); 215 ialp = (iscsi_addr_list_t *)calloc(1, discovery_addr_list_size); 216 if (ialp == NULL) { 217 (void) close(fd); 218 return (IMA_ERROR_INSUFFICIENT_MEMORY); 219 } 220 ialp->al_vers = ISCSI_INTERFACE_VERSION; 221 ialp->al_in_cnt = out_cnt; 222 223 /* 224 * Issue ISCSI_DISCOVERY_ADDR_LIST_GET ioctl again to obtain all 225 * the discovery addresses. 226 */ 227 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, ialp) != 0) { 228 #define ERROR_STR "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno :%d" 229 free(ialp); 230 (void) close(fd); 231 syslog(LOG_USER|LOG_DEBUG, 232 ERROR_STR, errno); 233 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 234 #undef ERROR_STR 235 236 } 237 } 238 239 *ppList = (SUN_IMA_DISC_ADDR_PROP_LIST *)calloc(1, 240 sizeof (SUN_IMA_DISC_ADDR_PROP_LIST) + 241 ialp->al_out_cnt * sizeof (IMA_DISCOVERY_ADDRESS_PROPERTIES)); 242 if (*ppList == NULL) { 243 free(ialp); 244 (void) close(fd); 245 return (IMA_ERROR_INSUFFICIENT_MEMORY); 246 } 247 (*ppList)->discAddrCount = ialp->al_out_cnt; 248 249 for (i = 0; i < ialp->al_out_cnt; i++) { 250 if (ialp->al_addrs[i].a_addr.i_insize == 251 sizeof (struct in_addr)) { 252 253 (*ppList)->props[i].discoveryAddress.hostnameIpAddress. 254 id.ipAddress.ipv4Address = IMA_TRUE; 255 256 } else if (ialp->al_addrs[i].a_addr.i_insize == 257 sizeof (struct in6_addr)) { 258 259 (*ppList)->props[i].discoveryAddress.hostnameIpAddress. 260 id.ipAddress.ipv4Address = IMA_FALSE; 261 262 } else { 263 (void) strlcpy(discovery_addr_str, "unknown", 264 sizeof (discovery_addr_str)); 265 } 266 267 ipAddr = &(*ppList)->props[i].discoveryAddress. 268 hostnameIpAddress.id.ipAddress; 269 270 bcopy(&ialp->al_addrs[i].a_addr.i_addr, 271 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.id. 272 ipAddress.ipAddress, 273 sizeof (ipAddr->ipAddress)); 274 275 (*ppList)->props[i].discoveryAddress.portNumber = 276 ialp->al_addrs[i].a_port; 277 } 278 279 free(ialp); 280 (void) close(fd); 281 return (IMA_STATUS_SUCCESS); 282 } 283 284 IMA_API IMA_STATUS SUN_IMA_GetStaticTargetProperties( 285 IMA_OID staticTargetOid, 286 SUN_IMA_STATIC_TARGET_PROPERTIES *pProps 287 ) 288 { 289 int fd; 290 int status; 291 iscsi_static_property_t prop; 292 /* LINTED */ 293 IMA_IP_ADDRESS *ipAddr; 294 295 if ((status = open_driver(&fd))) { 296 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 297 } 298 299 (void) memset(&prop, 0, sizeof (iscsi_static_property_t)); 300 prop.p_vers = ISCSI_INTERFACE_VERSION; 301 prop.p_oid = (uint32_t)staticTargetOid.objectSequenceNumber; 302 if (ioctl(fd, ISCSI_STATIC_GET, &prop) != 0) { 303 status = errno; 304 (void) close(fd); 305 syslog(LOG_USER|LOG_DEBUG, 306 "ISCSI_STATIC_GET ioctl failed, errno: %d", status); 307 if (status == ENOENT) { 308 return (IMA_ERROR_OBJECT_NOT_FOUND); 309 } else { 310 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 311 } 312 } 313 (void) close(fd); 314 315 (void) mbstowcs(pProps->staticTarget.targetName, (char *)prop.p_name, 316 sizeof (pProps->staticTarget.targetName)/sizeof (IMA_WCHAR)); 317 318 if (prop.p_addr_list.al_addrs[0].a_addr.i_insize == 319 sizeof (struct in_addr)) { 320 /* IPv4 */ 321 pProps->staticTarget.targetAddress.imaStruct.hostnameIpAddress. 322 id.ipAddress.ipv4Address = IMA_TRUE; 323 } else if (prop.p_addr_list.al_addrs[0].a_addr.i_insize == 324 sizeof (struct in6_addr)) { 325 /* IPv6 */ 326 pProps->staticTarget.targetAddress.imaStruct.hostnameIpAddress. 327 id.ipAddress.ipv4Address = IMA_FALSE; 328 } else { 329 /* Should not happen */ 330 syslog(LOG_USER|LOG_DEBUG, 331 "ISCSI_STATIC_GET returned bad address"); 332 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 333 } 334 335 ipAddr = &pProps->staticTarget.targetAddress.imaStruct. 336 hostnameIpAddress.id.ipAddress; 337 338 bcopy(&prop.p_addr_list.al_addrs[0].a_addr.i_addr, 339 pProps->staticTarget.targetAddress.imaStruct.hostnameIpAddress.id. 340 ipAddress.ipAddress, sizeof (ipAddr->ipAddress)); 341 342 pProps->staticTarget.targetAddress.imaStruct.portNumber = 343 prop.p_addr_list.al_addrs[0].a_port; 344 345 346 if (prop.p_addr_list.al_tpgt == (uint32_t)ISCSI_DEFAULT_TPGT) { 347 pProps->staticTarget.targetAddress.defaultTpgt = IMA_TRUE; 348 pProps->staticTarget.targetAddress.tpgt = 0; 349 } else { 350 pProps->staticTarget.targetAddress.defaultTpgt = IMA_FALSE; 351 pProps->staticTarget.targetAddress.tpgt = 352 prop.p_addr_list.al_tpgt; 353 } 354 355 return (IMA_STATUS_SUCCESS); 356 } 357 358 /*ARGSUSED*/ 359 IMA_API IMA_STATUS SUN_IMA_AddStaticTarget( 360 IMA_OID lhbaOid, 361 const SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig, 362 IMA_OID *pTargetOid 363 ) 364 { 365 iscsi_target_entry_t target; 366 int fd; 367 int target_in_addr_size; 368 int status; 369 union { 370 struct in_addr u_in4; 371 struct in6_addr u_in6; 372 } target_in; 373 374 /* 375 * staticConfig.address may come in with port number at its trailer. 376 * Parse it to separate the IP address and port number. 377 * Also translate the hostname to IP address if needed. 378 */ 379 380 if (staticConfig.targetAddress.imaStruct.hostnameIpAddress.id.ipAddress. 381 ipv4Address == IMA_FALSE) { 382 383 bcopy(staticConfig.targetAddress.imaStruct.hostnameIpAddress. 384 id.ipAddress.ipAddress, &target_in.u_in6, 385 sizeof (target_in.u_in6)); 386 387 target_in_addr_size = sizeof (struct in6_addr); 388 } else { 389 390 bcopy(staticConfig.targetAddress.imaStruct.hostnameIpAddress. 391 id.ipAddress.ipAddress, &target_in.u_in4, 392 sizeof (target_in.u_in4)); 393 394 target_in_addr_size = sizeof (struct in_addr); 395 } 396 397 (void) memset(&target, 0, sizeof (iscsi_target_entry_t)); 398 target.te_entry.e_vers = ISCSI_INTERFACE_VERSION; 399 target.te_entry.e_oid = ISCSI_OID_NOTSET; 400 401 (void) wcstombs((char *)target.te_name, staticConfig.targetName, 402 ISCSI_MAX_NAME_LEN); 403 404 target.te_entry.e_insize = target_in_addr_size; 405 if (target.te_entry.e_insize == sizeof (struct in_addr)) { 406 target.te_entry.e_u.u_in4.s_addr = target_in.u_in4.s_addr; 407 } else if (target.te_entry.e_insize == sizeof (struct in6_addr)) { 408 bcopy(target_in.u_in6.s6_addr, 409 target.te_entry.e_u.u_in6.s6_addr, 410 sizeof (struct in6_addr)); 411 } else { 412 return (IMA_ERROR_INVALID_PARAMETER); 413 } 414 415 target.te_entry.e_port = 416 staticConfig.targetAddress.imaStruct.portNumber; 417 418 if (staticConfig.targetAddress.defaultTpgt == IMA_TRUE) { 419 target.te_entry.e_tpgt = ISCSI_DEFAULT_TPGT; 420 } else { 421 target.te_entry.e_tpgt = staticConfig.targetAddress.tpgt; 422 } 423 424 if ((status = open_driver(&fd))) { 425 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 426 } 427 428 if (ioctl(fd, ISCSI_STATIC_SET, &target)) { 429 /* 430 * Encountered problem setting the IP address and port for 431 * the target just added. 432 */ 433 syslog(LOG_USER|LOG_DEBUG, 434 "ISCSI_STATIC_SET ioctl failed, errno: %d", errno); 435 (void) close(fd); 436 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 437 } 438 439 pTargetOid->objectType = IMA_OBJECT_TYPE_TARGET; 440 pTargetOid->ownerId = 1; 441 pTargetOid->objectSequenceNumber = target.te_entry.e_oid; 442 443 (void) close(fd); 444 return (IMA_STATUS_SUCCESS); 445 } 446 447 IMA_API IMA_STATUS SUN_IMA_GetTargetProperties( 448 IMA_OID targetId, 449 SUN_IMA_TARGET_PROPERTIES *pProps 450 ) 451 { 452 int fd; 453 int status; 454 iscsi_property_t prop; 455 456 if ((status = open_driver(&fd))) { 457 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 458 } 459 460 (void) memset(&prop, 0, sizeof (iscsi_property_t)); 461 prop.p_vers = ISCSI_INTERFACE_VERSION; 462 prop.p_oid = (uint32_t)targetId.objectSequenceNumber; 463 464 if (ioctl(fd, ISCSI_TARGET_PROPS_GET, &prop) != 0) { 465 syslog(LOG_USER|LOG_DEBUG, 466 "ISCSI_TARGET_PROPS_GET ioctl failed, errno: %d", errno); 467 (void) close(fd); 468 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 469 } 470 471 (void) mbstowcs(pProps->imaProps.name, 472 (char *)prop.p_name, IMA_NODE_NAME_LEN); 473 (void) memset(pProps->imaProps.alias, 0, 474 (sizeof (IMA_WCHAR) * SUN_IMA_NODE_ALIAS_LEN)); 475 if (prop.p_alias_len > 0) { 476 (void) mbstowcs(pProps->imaProps.alias, (char *)prop.p_alias, 477 SUN_IMA_NODE_ALIAS_LEN); 478 } 479 480 /* Initialize the discovery method to unknown method. */ 481 pProps->imaProps.discoveryMethodFlags = 482 IMA_TARGET_DISCOVERY_METHOD_UNKNOWN; 483 if (!((prop.p_discovery & iSCSIDiscoveryMethodStatic) ^ 484 iSCSIDiscoveryMethodStatic)) { 485 pProps->imaProps.discoveryMethodFlags |= 486 IMA_TARGET_DISCOVERY_METHOD_STATIC; 487 } 488 489 if (!((prop.p_discovery & iSCSIDiscoveryMethodSLP) ^ 490 iSCSIDiscoveryMethodSLP)) { 491 pProps->imaProps.discoveryMethodFlags |= 492 IMA_TARGET_DISCOVERY_METHOD_SLP; 493 } 494 495 if (!((prop.p_discovery & iSCSIDiscoveryMethodISNS) ^ 496 iSCSIDiscoveryMethodISNS)) { 497 pProps->imaProps.discoveryMethodFlags |= 498 iSCSIDiscoveryMethodISNS; 499 } 500 501 if (!((prop.p_discovery & iSCSIDiscoveryMethodSendTargets) ^ 502 iSCSIDiscoveryMethodSendTargets)) { 503 pProps->imaProps.discoveryMethodFlags |= 504 iSCSIDiscoveryMethodSendTargets; 505 } 506 507 if (prop.p_tpgt_conf == ISCSI_DEFAULT_TPGT) { 508 pProps->defaultTpgtConf = IMA_TRUE; 509 pProps->tpgtConf = 0; 510 } else { 511 pProps->defaultTpgtConf = IMA_FALSE; 512 pProps->tpgtConf = prop.p_tpgt_conf; 513 } 514 515 if (prop.p_tpgt_nego == ISCSI_DEFAULT_TPGT) { 516 pProps->defaultTpgtNego = IMA_TRUE; 517 pProps->tpgtNego = 0; 518 } else { 519 pProps->defaultTpgtNego = IMA_FALSE; 520 pProps->tpgtNego = prop.p_tpgt_nego; 521 } 522 523 bcopy(prop.p_isid, pProps->isid, ISCSI_ISID_LEN); 524 525 (void) close(fd); 526 return (IMA_STATUS_SUCCESS); 527 } 528 529 /* 530 * This function only sets CHAP params since we only support CHAP for now. 531 */ 532 IMA_STATUS SUN_IMA_SetTargetAuthParams( 533 IMA_OID targetOid, 534 IMA_AUTHMETHOD method, 535 const IMA_INITIATOR_AUTHPARMS *pParms 536 ) 537 { 538 int fd; 539 iscsi_chap_props_t chap_p; 540 541 if (method != IMA_AUTHMETHOD_CHAP) 542 return (IMA_ERROR_INVALID_PARAMETER); 543 544 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 545 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)", 546 ISCSI_DRIVER_DEVCTL, errno); 547 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 548 } 549 550 (void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t)); 551 chap_p.c_vers = ISCSI_INTERFACE_VERSION; 552 chap_p.c_oid = (uint32_t)targetOid.objectSequenceNumber; 553 554 chap_p.c_user_len = 555 pParms->chapParms.nameLength; 556 (void) memcpy(chap_p.c_user, 557 pParms->chapParms.name, chap_p.c_user_len); 558 559 chap_p.c_secret_len = 560 pParms->chapParms.challengeSecretLength; 561 (void) memcpy(chap_p.c_secret, 562 pParms->chapParms.challengeSecret, 563 chap_p.c_secret_len); 564 565 if (ioctl(fd, ISCSI_CHAP_SET, &chap_p) != 0) { 566 syslog(LOG_USER|LOG_DEBUG, 567 "ISCSI_CHAP_SET ioctl failed, errno: %d", errno); 568 (void) close(fd); 569 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 570 } 571 572 return (IMA_STATUS_SUCCESS); 573 } 574 575 IMA_STATUS SUN_IMA_GetTargetAuthMethods( 576 IMA_OID lhbaOid, 577 IMA_OID targetOid, 578 IMA_UINT *pMethodCount, 579 IMA_AUTHMETHOD *pMethodList 580 ) 581 { 582 if (getAuthMethods(targetOid, pMethodCount, pMethodList) 583 != IMA_STATUS_SUCCESS) { 584 return (getAuthMethods(lhbaOid, pMethodCount, pMethodList)); 585 } 586 return (IMA_STATUS_SUCCESS); 587 } 588 589 IMA_STATUS SUN_IMA_SetInitiatorRadiusConfig( 590 IMA_OID lhbaOid, 591 SUN_IMA_RADIUS_CONFIG *config 592 ) 593 { 594 int af; 595 int fd; 596 int status; 597 iscsi_radius_props_t radius; 598 union { 599 struct in_addr u_in4; 600 struct in6_addr u_in6; 601 } radius_in; 602 603 if ((status = open_driver(&fd))) { 604 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 605 } 606 607 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t)); 608 radius.r_vers = ISCSI_INTERFACE_VERSION; 609 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber; 610 /* Get first because other data fields may already exist */ 611 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) { 612 /* EMPTY */ 613 /* It's fine if other data fields are not there. */ 614 } 615 616 if (config->isIpv6 == IMA_TRUE) { 617 af = AF_INET6; 618 } else { 619 af = AF_INET; 620 } 621 622 if (inet_pton(af, config->hostnameIpAddress, &radius_in.u_in4) != 1) { 623 return (IMA_ERROR_INVALID_PARAMETER); 624 } 625 626 switch (af) { 627 case AF_INET: 628 radius.r_addr.u_in4.s_addr = radius_in.u_in4.s_addr; 629 radius.r_insize = sizeof (struct in_addr); 630 break; 631 case AF_INET6: 632 (void) memcpy(radius.r_addr.u_in6.s6_addr, 633 radius_in.u_in6.s6_addr, 16); 634 radius.r_insize = sizeof (struct in6_addr); 635 break; 636 } 637 radius.r_port = config->port; 638 radius.r_radius_config_valid = B_TRUE; 639 /* Allow resetting the RADIUS shared secret to NULL */ 640 if (config->sharedSecretValid == IMA_TRUE) { 641 radius.r_shared_secret_len = config->sharedSecretLength; 642 (void) memset(&radius.r_shared_secret[0], 0, 643 MAX_RAD_SHARED_SECRET_LEN); 644 (void) memcpy(&radius.r_shared_secret[0], config->sharedSecret, 645 config->sharedSecretLength); 646 } 647 648 if (ioctl(fd, ISCSI_RADIUS_SET, &radius) != 0) { 649 syslog(LOG_USER|LOG_DEBUG, 650 "ISCSI_RADIUS_SET ioctl failed, errno: %d", errno); 651 (void) close(fd); 652 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 653 } 654 655 (void) close(fd); 656 return (IMA_STATUS_SUCCESS); 657 } 658 659 IMA_STATUS SUN_IMA_GetInitiatorRadiusConfig( 660 IMA_OID lhbaOid, 661 SUN_IMA_RADIUS_CONFIG *config 662 ) 663 { 664 int af; 665 int fd; 666 int status; 667 iscsi_radius_props_t radius; 668 669 if ((status = open_driver(&fd))) { 670 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 671 } 672 673 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t)); 674 radius.r_vers = ISCSI_INTERFACE_VERSION; 675 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber; 676 677 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) { 678 (void) close(fd); 679 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 680 } 681 682 (void) memset(config, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 683 if (radius.r_insize == sizeof (struct in_addr)) { 684 /* IPv4 */ 685 af = AF_INET; 686 } else if (radius.r_insize == sizeof (struct in6_addr)) { 687 /* IPv6 */ 688 af = AF_INET6; 689 } else { 690 /* 691 * It's legitimate that the existing RADIUS record does not 692 * have configuration data. 693 */ 694 config->hostnameIpAddress[0] = '\0'; 695 config->port = 0; 696 (void) close(fd); 697 return (IMA_STATUS_SUCCESS); 698 } 699 (void) inet_ntop(af, (void *)&radius.r_addr.u_in4, 700 config->hostnameIpAddress, 256); 701 config->port = radius.r_port; 702 (void) memcpy(config->sharedSecret, &radius.r_shared_secret[0], 703 radius.r_shared_secret_len); 704 config->sharedSecretLength = radius.r_shared_secret_len; 705 config->sharedSecretValid = B_TRUE; 706 707 (void) close(fd); 708 return (IMA_STATUS_SUCCESS); 709 } 710 711 IMA_STATUS SUN_IMA_SetInitiatorRadiusAccess( 712 IMA_OID lhbaOid, 713 IMA_BOOL radiusAccess 714 ) 715 { 716 int fd; 717 int status; 718 iscsi_radius_props_t radius; 719 720 if ((status = open_driver(&fd))) { 721 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 722 } 723 724 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t)); 725 radius.r_vers = ISCSI_INTERFACE_VERSION; 726 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber; 727 /* Get first because other data fields may already exist */ 728 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) { 729 if (radiusAccess == IMA_TRUE) { 730 /* 731 * Cannot enable RADIUS if no RADIUS configuration 732 * can be found. 733 */ 734 syslog(LOG_USER|LOG_DEBUG, 735 "RADIUS config data not found - " 736 "cannot enable RADIUS, errno: %d", errno); 737 (void) close(fd); 738 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 739 } else { 740 /* EMPTY */ 741 /* Otherwise it's fine to disable RADIUS */ 742 } 743 } 744 745 if ((radius.r_insize != sizeof (struct in_addr)) && 746 (radius.r_insize != sizeof (struct in6_addr))) { 747 /* 748 * Cannot enable RADIUS if no RADIUS configuration 749 * can be found. 750 */ 751 if (radiusAccess == IMA_TRUE) { 752 syslog(LOG_USER|LOG_DEBUG, 753 "RADIUS config data not found - " 754 "cannot enable RADIUS"); 755 (void) close(fd); 756 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 757 } 758 } 759 760 radius.r_radius_access = (radiusAccess == IMA_TRUE) ? 761 B_TRUE : B_FALSE; 762 763 if (ioctl(fd, ISCSI_RADIUS_SET, &radius) != 0) { 764 syslog(LOG_USER|LOG_DEBUG, 765 "ISCSI_RADIUS_SET ioctl failed, errno: %d", errno); 766 (void) close(fd); 767 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 768 } 769 770 (void) close(fd); 771 return (IMA_STATUS_SUCCESS); 772 } 773 774 IMA_STATUS SUN_IMA_GetInitiatorRadiusAccess( 775 IMA_OID lhbaOid, 776 IMA_BOOL *radiusAccess 777 ) 778 { 779 int fd; 780 int status; 781 iscsi_radius_props_t radius; 782 783 if ((status = open_driver(&fd))) { 784 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 785 } 786 787 (void) memset(&radius, 0, sizeof (iscsi_radius_props_t)); 788 radius.r_vers = ISCSI_INTERFACE_VERSION; 789 radius.r_oid = (uint32_t)lhbaOid.objectSequenceNumber; 790 791 if (ioctl(fd, ISCSI_RADIUS_GET, &radius) != 0) { 792 (void) close(fd); 793 if (errno == ENOENT) { 794 return (IMA_ERROR_OBJECT_NOT_FOUND); 795 } else { 796 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 797 } 798 } 799 800 *radiusAccess = (radius.r_radius_access == B_TRUE) ? 801 IMA_TRUE : IMA_FALSE; 802 803 (void) close(fd); 804 return (IMA_STATUS_SUCCESS); 805 } 806 807 IMA_STATUS SUN_IMA_SendTargets( 808 IMA_NODE_NAME nodeName, 809 IMA_TARGET_ADDRESS address, 810 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList 811 ) 812 { 813 char *colonPos; 814 char discAddrStr[256]; 815 char nodeNameStr[ISCSI_MAX_NAME_LEN]; 816 int fd; 817 int ctr; 818 int stl_sz; 819 int status; 820 iscsi_sendtgts_list_t *stl_hdr = NULL; 821 IMA_BOOL retry = IMA_TRUE; 822 /* LINTED */ 823 IMA_IP_ADDRESS *ipAddr; 824 825 #define SENDTGTS_DEFAULT_NUM_TARGETS 10 826 827 stl_sz = sizeof (*stl_hdr) + ((SENDTGTS_DEFAULT_NUM_TARGETS - 1) * 828 sizeof (iscsi_sendtgts_entry_t)); 829 stl_hdr = (iscsi_sendtgts_list_t *)calloc(1, stl_sz); 830 if (stl_hdr == NULL) { 831 return (IMA_ERROR_INSUFFICIENT_MEMORY); 832 } 833 stl_hdr->stl_entry.e_vers = ISCSI_INTERFACE_VERSION; 834 stl_hdr->stl_in_cnt = SENDTGTS_DEFAULT_NUM_TARGETS; 835 836 (void) wcstombs(nodeNameStr, nodeName, ISCSI_MAX_NAME_LEN); 837 838 colonPos = strchr(discAddrStr, ':'); 839 if (colonPos == NULL) { 840 /* IPv4 */ 841 stl_hdr->stl_entry.e_insize = sizeof (struct in_addr); 842 } else { 843 /* IPv6 */ 844 stl_hdr->stl_entry.e_insize = sizeof (struct in6_addr); 845 } 846 847 ipAddr = &address.hostnameIpAddress.id.ipAddress; 848 849 bcopy(address.hostnameIpAddress.id.ipAddress.ipAddress, 850 &stl_hdr->stl_entry.e_u, sizeof (ipAddr->ipAddress)); 851 852 stl_hdr->stl_entry.e_port = address.portNumber; 853 854 if ((status = open_driver(&fd))) { 855 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 856 } 857 858 retry_sendtgts: 859 /* 860 * Issue ioctl to obtain the SendTargets list 861 */ 862 if (ioctl(fd, ISCSI_SENDTGTS_GET, stl_hdr) != 0) { 863 syslog(LOG_USER|LOG_DEBUG, 864 "ISCSI_SENDTGTS_GET ioctl failed, errno: %d", errno); 865 (void) close(fd); 866 free(stl_hdr); 867 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 868 } 869 870 /* check if all targets received */ 871 if (stl_hdr->stl_in_cnt < stl_hdr->stl_out_cnt) { 872 if (retry == IMA_TRUE) { 873 stl_sz = sizeof (*stl_hdr) + 874 ((stl_hdr->stl_out_cnt - 1) * 875 sizeof (iscsi_sendtgts_entry_t)); 876 stl_hdr = (iscsi_sendtgts_list_t *) 877 realloc(stl_hdr, stl_sz); 878 if (stl_hdr == NULL) { 879 (void) close(fd); 880 return (IMA_ERROR_INSUFFICIENT_MEMORY); 881 } 882 stl_hdr->stl_in_cnt = stl_hdr->stl_out_cnt; 883 retry = IMA_FALSE; 884 goto retry_sendtgts; 885 } else { 886 /* 887 * don't retry after 2 attempts. The target list 888 * shouldn't continue to growing. Justs continue 889 * on and display what was found. 890 */ 891 syslog(LOG_USER|LOG_DEBUG, 892 "ISCSI_SENDTGTS_GET overflow: " 893 "failed to obtain all targets"); 894 stl_hdr->stl_out_cnt = stl_hdr->stl_in_cnt; 895 } 896 } 897 898 (void) close(fd); 899 900 /* allocate for caller return buffer */ 901 *ppList = (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *)calloc(1, 902 sizeof (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES) + 903 stl_hdr->stl_out_cnt * sizeof (SUN_IMA_DISC_ADDRESS_KEY)); 904 if (*ppList == NULL) { 905 free(stl_hdr); 906 return (IMA_ERROR_INSUFFICIENT_MEMORY); 907 } 908 909 (*ppList)->keyCount = stl_hdr->stl_out_cnt; 910 911 for (ctr = 0; ctr < stl_hdr->stl_out_cnt; ctr++) { 912 (void) mbstowcs((*ppList)->keys[ctr].name, 913 (char *)stl_hdr->stl_list[ctr].ste_name, 914 IMA_NODE_NAME_LEN); 915 916 (*ppList)->keys[ctr].tpgt = stl_hdr->stl_list[ctr].ste_tpgt; 917 918 (*ppList)->keys[ctr].address.portNumber = 919 stl_hdr->stl_list[ctr].ste_ipaddr.a_port; 920 921 if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize == 922 sizeof (struct in_addr)) { 923 (*ppList)->keys[ctr].address.ipAddress.ipv4Address = 924 IMA_TRUE; 925 } else if (stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize == 926 sizeof (struct in6_addr)) { 927 (*ppList)->keys[ctr].address.ipAddress.ipv4Address = 928 IMA_FALSE; 929 } else { 930 free(stl_hdr); 931 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 932 } 933 934 (void) memcpy(&(*ppList)->keys[ctr].address.ipAddress.ipAddress, 935 &(stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_addr), 936 stl_hdr->stl_list[ctr].ste_ipaddr.a_addr.i_insize); 937 } 938 free(stl_hdr); 939 940 return (IMA_STATUS_SUCCESS); 941 } 942 943 IMA_STATUS SUN_IMA_SetTargetBidirAuthFlag( 944 IMA_OID targetOid, 945 IMA_BOOL *bidirAuthFlag 946 ) 947 { 948 int fd; 949 int status; 950 iscsi_auth_props_t auth; 951 952 if ((status = open_driver(&fd))) { 953 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 954 } 955 956 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t)); 957 auth.a_vers = ISCSI_INTERFACE_VERSION; 958 auth.a_oid = (uint32_t)targetOid.objectSequenceNumber; 959 /* Get first because other data fields may already exist */ 960 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) { 961 /* EMPTY */ 962 /* It is fine if there is no other data fields. */ 963 } 964 auth.a_bi_auth = (*bidirAuthFlag == IMA_TRUE) ? B_TRUE : B_FALSE; 965 if (ioctl(fd, ISCSI_AUTH_SET, &auth) != 0) { 966 syslog(LOG_USER|LOG_DEBUG, 967 "ISCSI_AUTH_SET ioctl failed, errno: %d", errno); 968 (void) close(fd); 969 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 970 } 971 972 (void) close(fd); 973 return (IMA_STATUS_SUCCESS); 974 } 975 976 IMA_STATUS SUN_IMA_GetTargetBidirAuthFlag( 977 IMA_OID targetOid, 978 IMA_BOOL *bidirAuthFlag 979 ) 980 { 981 int fd; 982 int status; 983 iscsi_auth_props_t auth; 984 985 if ((status = open_driver(&fd))) { 986 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 987 } 988 989 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t)); 990 auth.a_vers = ISCSI_INTERFACE_VERSION; 991 auth.a_oid = (uint32_t)targetOid.objectSequenceNumber; 992 993 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) { 994 (void) close(fd); 995 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 996 } 997 998 *bidirAuthFlag = (auth.a_bi_auth == B_TRUE) ? 999 IMA_TRUE : IMA_FALSE; 1000 1001 (void) close(fd); 1002 return (IMA_STATUS_SUCCESS); 1003 } 1004 1005 IMA_STATUS SUN_IMA_CreateTargetOid( 1006 IMA_NODE_NAME targetName, 1007 IMA_OID *targetOid 1008 ) 1009 { 1010 int fd; 1011 int status; 1012 iscsi_oid_t oid; 1013 1014 if ((status = open_driver(&fd))) { 1015 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1016 } 1017 1018 (void) memset(&oid, 0, sizeof (iscsi_oid_t)); 1019 (void) wcstombs((char *)oid.o_name, targetName, ISCSI_MAX_NAME_LEN); 1020 oid.o_tpgt = ISCSI_DEFAULT_TPGT; 1021 oid.o_vers = ISCSI_INTERFACE_VERSION; 1022 if (ioctl(fd, ISCSI_CREATE_OID, &oid) == -1) { 1023 syslog(LOG_USER|LOG_DEBUG, 1024 "ISCSI_CREATE_OID ioctl failed, errno: %d", errno); 1025 (void) close(fd); 1026 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1027 } 1028 1029 targetOid->objectType = IMA_OBJECT_TYPE_TARGET; 1030 targetOid->ownerId = 1; 1031 targetOid->objectSequenceNumber = oid.o_oid; 1032 1033 (void) close(fd); 1034 return (IMA_STATUS_SUCCESS); 1035 } 1036 1037 IMA_STATUS SUN_IMA_RemoveTargetParam( 1038 IMA_OID targetOid 1039 ) 1040 { 1041 entry_t entry; 1042 int fd; 1043 int status; 1044 iscsi_auth_props_t auth_p; 1045 iscsi_chap_props_t chap_p; 1046 1047 if ((status = open_driver(&fd))) { 1048 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1049 } 1050 1051 (void) memset(&entry, 0, sizeof (entry_t)); 1052 entry.e_vers = ISCSI_INTERFACE_VERSION; 1053 entry.e_oid = (uint32_t)targetOid.objectSequenceNumber; 1054 if (ioctl(fd, ISCSI_TARGET_PARAM_CLEAR, &entry)) { 1055 /* 1056 * It could be that the target exists but the associated 1057 * target_param does not, and that is legitimate. 1058 */ 1059 syslog(LOG_USER|LOG_DEBUG, 1060 "ISCSI_TARGET_PARAM_CLEAR ioctl failed, errno: %d", errno); 1061 } 1062 1063 /* Issue ISCSI_CHAP_CLEAR ioctl */ 1064 (void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t)); 1065 chap_p.c_vers = ISCSI_INTERFACE_VERSION; 1066 chap_p.c_oid = (uint32_t)targetOid.objectSequenceNumber; 1067 if (ioctl(fd, ISCSI_CHAP_CLEAR, &chap_p) != 0) { 1068 /* 1069 * It could be that the CHAP of this target has never 1070 * been set. 1071 */ 1072 syslog(LOG_USER|LOG_DEBUG, 1073 "ISCSI_CHAP_CLEAR ioctl failed, errno: %d", errno); 1074 } 1075 1076 /* 1077 * Issue ISCSI_AUTH_CLEAR ioctl, in which the authentication information 1078 * is removed and the target that is not discovered by initiator 1079 * is removed from the memory. So this ioctl should be called at last 1080 */ 1081 (void) memset(&auth_p, 0, sizeof (iscsi_auth_props_t)); 1082 auth_p.a_vers = ISCSI_INTERFACE_VERSION; 1083 auth_p.a_oid = (uint32_t)targetOid.objectSequenceNumber; 1084 if (ioctl(fd, ISCSI_AUTH_CLEAR, &auth_p) != 0) { 1085 /* 1086 * It could be that the auth data of this target has 1087 * never been set. 1088 */ 1089 syslog(LOG_USER|LOG_DEBUG, 1090 "ISCSI_AUTH_CLEAR ioctl failed, errno: %d", errno); 1091 } 1092 1093 (void) close(fd); 1094 return (IMA_STATUS_SUCCESS); 1095 } 1096 1097 IMA_API IMA_STATUS SUN_IMA_SetHeaderDigest( 1098 IMA_OID oid, 1099 IMA_UINT algorithmCount, 1100 const SUN_IMA_DIGEST_ALGORITHM *algorithmList 1101 ) 1102 { 1103 IMA_MIN_MAX_VALUE mv; 1104 uint32_t digest_algorithm; 1105 1106 /* We only support one preference of digest algorithm. */ 1107 if (algorithmCount > 1) { 1108 syslog(LOG_USER|LOG_DEBUG, 1109 "More than one digest algorithm specified."); 1110 return (IMA_ERROR_NOT_SUPPORTED); 1111 } 1112 switch (algorithmList[0]) { 1113 case SUN_IMA_DIGEST_NONE: 1114 digest_algorithm = ISCSI_DIGEST_NONE; 1115 break; 1116 case SUN_IMA_DIGEST_CRC32: 1117 digest_algorithm = ISCSI_DIGEST_CRC32C; 1118 break; 1119 default: 1120 digest_algorithm = ISCSI_DIGEST_NONE; 1121 break; 1122 } 1123 mv.currentValue = digest_algorithm; 1124 return (setISCSINodeParameter(MIN_MAX_PARAM, &oid, &mv, 1125 ISCSI_LOGIN_PARAM_HEADER_DIGEST)); 1126 } 1127 1128 IMA_API IMA_STATUS SUN_IMA_SetDataDigest( 1129 IMA_OID oid, 1130 IMA_UINT algorithmCount, 1131 const SUN_IMA_DIGEST_ALGORITHM *algorithmList 1132 ) 1133 { 1134 IMA_MIN_MAX_VALUE mv; 1135 uint32_t digest_algorithm; 1136 1137 /* We only support one preference of digest algorithm. */ 1138 if (algorithmCount > 1) { 1139 syslog(LOG_USER|LOG_DEBUG, 1140 "More than one digest algorithm specified."); 1141 return (IMA_ERROR_NOT_SUPPORTED); 1142 } 1143 switch (algorithmList[0]) { 1144 case SUN_IMA_DIGEST_NONE: 1145 digest_algorithm = ISCSI_DIGEST_NONE; 1146 break; 1147 case SUN_IMA_DIGEST_CRC32: 1148 digest_algorithm = ISCSI_DIGEST_CRC32C; 1149 break; 1150 default: 1151 digest_algorithm = ISCSI_DIGEST_NONE; 1152 break; 1153 } 1154 mv.currentValue = digest_algorithm; 1155 return (setISCSINodeParameter(MIN_MAX_PARAM, &oid, &mv, 1156 ISCSI_LOGIN_PARAM_DATA_DIGEST)); 1157 } 1158 1159 IMA_API IMA_STATUS SUN_IMA_GetHeaderDigest( 1160 IMA_OID oid, 1161 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm 1162 ) 1163 { 1164 return (getDigest(oid, ISCSI_LOGIN_PARAM_HEADER_DIGEST, algorithm)); 1165 } 1166 1167 IMA_API IMA_STATUS SUN_IMA_GetDataDigest( 1168 IMA_OID oid, 1169 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm 1170 ) 1171 { 1172 return (getDigest(oid, ISCSI_LOGIN_PARAM_DATA_DIGEST, algorithm)); 1173 } 1174 1175 typedef struct walk_devlink { 1176 char *path; 1177 size_t len; 1178 char **linkpp; 1179 } walk_devlink_t; 1180 1181 IMA_STATUS SUN_IMA_GetLuProperties( 1182 IMA_OID luId, 1183 SUN_IMA_LU_PROPERTIES *pProps 1184 ) 1185 { 1186 IMA_STATUS status; 1187 iscsi_lun_list_t *pLunList; 1188 int j; 1189 IMA_BOOL lunMatch = IMA_FALSE; 1190 int fd; 1191 int openStatus; 1192 iscsi_lun_props_t lun; 1193 di_devlink_handle_t hdl; 1194 walk_devlink_t warg; 1195 char *minor_path, *devlinkp, lunpath[MAXPATHLEN]; 1196 1197 if (luId.objectType != IMA_OBJECT_TYPE_LU) { 1198 return (IMA_ERROR_INCORRECT_OBJECT_TYPE); 1199 } 1200 1201 /* 1202 * get list of lun oids for all targets 1203 */ 1204 status = get_target_lun_oid_list(NULL, &pLunList); 1205 if (!IMA_SUCCESS(status)) { 1206 return (status); 1207 } 1208 for (j = 0; j < pLunList->ll_out_cnt; j++) { 1209 /* 1210 * for each lun, check if match is found 1211 */ 1212 if (pLunList->ll_luns[j].l_oid == luId.objectSequenceNumber) { 1213 /* 1214 * match found, break out of lun loop 1215 */ 1216 lunMatch = IMA_TRUE; 1217 break; 1218 } 1219 } 1220 1221 if (lunMatch == IMA_TRUE) { 1222 (void) memset(&lun, 0, sizeof (iscsi_lun_props_t)); 1223 lun.lp_vers = ISCSI_INTERFACE_VERSION; 1224 lun.lp_tgt_oid = pLunList->ll_luns[j].l_tgt_oid; 1225 lun.lp_oid = pLunList->ll_luns[j].l_oid; 1226 } 1227 1228 free(pLunList); 1229 1230 if (lunMatch == IMA_FALSE) { 1231 return (IMA_ERROR_OBJECT_NOT_FOUND); 1232 } 1233 1234 /* 1235 * get lun properties 1236 */ 1237 if ((openStatus = open_driver(&fd))) { 1238 return (SUN_IMA_ERROR_SYSTEM_ERROR | openStatus); 1239 } 1240 1241 if (ioctl(fd, ISCSI_LUN_PROPS_GET, &lun)) { 1242 syslog(LOG_USER|LOG_DEBUG, 1243 "ISCSI_LUN_PROPS_GET ioctl failed, errno: %d", errno); 1244 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1245 } 1246 1247 (void) close(fd); 1248 1249 /* 1250 * set property values 1251 */ 1252 pProps->imaProps.associatedTargetOid.objectType = 1253 IMA_OBJECT_TYPE_TARGET; 1254 pProps->imaProps.associatedTargetOid.ownerId = 1; 1255 pProps->imaProps.associatedTargetOid.objectSequenceNumber = lun.lp_oid; 1256 pProps->imaProps.targetLun = (IMA_UINT64)lun.lp_num; 1257 (void) strncpy(pProps->vendorId, lun.lp_vid, SUN_IMA_LU_VENDOR_ID_LEN); 1258 (void) strncpy(pProps->productId, lun.lp_pid, 1259 SUN_IMA_LU_PRODUCT_ID_LEN); 1260 /* 1261 * lun.lp_status is defined as 1262 * LunValid = 0 1263 * LunDoesNotExist = 1 1264 * IMA_LU_PROPS.exposedtoOS is defined as an IMA_BOOL 1265 * IMA_TRUE = 1 1266 * IMA_FALSE = 0 1267 */ 1268 pProps->imaProps.exposedToOs = !lun.lp_status; 1269 if (gmtime_r(&lun.lp_time_online, &pProps->imaProps.timeExposedToOs) 1270 == NULL) { 1271 (void) memset(&pProps->imaProps.timeExposedToOs, 0, 1272 sizeof (pProps->imaProps.timeExposedToOs)); 1273 } 1274 1275 if (lun.lp_status == LunValid) { 1276 if ((strlen(lun.lp_pathname) + strlen("/devices")) > 1277 (MAXPATHLEN -1)) { 1278 /* 1279 * lun.lp_pathname length too long 1280 */ 1281 pProps->imaProps.osDeviceNameValid = IMA_FALSE; 1282 pProps->imaProps.osParallelIdsValid = IMA_FALSE; 1283 return (IMA_STATUS_SUCCESS); 1284 } 1285 if ((strstr(lun.lp_pathname, "st@") != NULL) || 1286 (strstr(lun.lp_pathname, "tape@") != NULL)) { 1287 (void) strlcat(lun.lp_pathname, ":n", MAXPATHLEN); 1288 } else if ((strstr(lun.lp_pathname, "sd@") != NULL) || 1289 (strstr(lun.lp_pathname, "ssd@") != NULL) || 1290 (strstr(lun.lp_pathname, "disk@") != NULL)) { 1291 /* 1292 * modify returned pathname to obtain the 2nd slice 1293 * of the raw disk 1294 */ 1295 (void) strlcat(lun.lp_pathname, ":c,raw", MAXPATHLEN); 1296 } else if ((strstr(lun.lp_pathname, "ses@") != NULL) || 1297 (strstr(lun.lp_pathname, "enclosure@") != NULL)) { 1298 (void) strlcat(lun.lp_pathname, ":0", MAXPATHLEN); 1299 } 1300 1301 (void) snprintf(lunpath, sizeof (lun.lp_pathname), 1302 "/devices%s", lun.lp_pathname); 1303 if (strchr(lunpath, ':')) { 1304 minor_path = lunpath; 1305 if (strstr(minor_path, "/devices") != NULL) { 1306 minor_path = lunpath + 1307 strlen("/devices"); 1308 } else { 1309 minor_path = lunpath; 1310 } 1311 warg.path = NULL; 1312 } else { 1313 minor_path = NULL; 1314 warg.len = strlen(lunpath); 1315 warg.path = lunpath; 1316 } 1317 devlinkp = NULL; 1318 warg.linkpp = &devlinkp; 1319 1320 /* 1321 * Pathname returned by driver is the physical device path. 1322 * This name needs to be converted to the OS device name. 1323 */ 1324 if (hdl = di_devlink_init(lun.lp_pathname, DI_MAKE_LINK)) { 1325 pProps->imaProps.osDeviceName[0] = L'\0'; 1326 (void) di_devlink_walk(hdl, NULL, minor_path, 1327 DI_PRIMARY_LINK, (void *)&warg, get_lun_devlink); 1328 if (devlinkp != NULL) { 1329 /* OS device name synchronously made */ 1330 (void) mbstowcs(pProps->imaProps.osDeviceName, 1331 devlinkp, MAXPATHLEN); 1332 free(devlinkp); 1333 pProps->imaProps.osDeviceNameValid = IMA_TRUE; 1334 } else { 1335 pProps->imaProps.osDeviceNameValid = IMA_FALSE; 1336 } 1337 1338 (void) di_devlink_fini(&hdl); 1339 1340 } else { 1341 pProps->imaProps.osDeviceNameValid = IMA_FALSE; 1342 } 1343 1344 } else { 1345 pProps->imaProps.osDeviceNameValid = IMA_FALSE; 1346 } 1347 1348 pProps->imaProps.osParallelIdsValid = IMA_FALSE; 1349 1350 return (IMA_STATUS_SUCCESS); 1351 } 1352 1353 static int 1354 get_lun_devlink(di_devlink_t link, void *arg) 1355 { 1356 walk_devlink_t *warg = (walk_devlink_t *)arg; 1357 if (warg->path) { 1358 char *content = (char *)di_devlink_content(link); 1359 char *start = strstr(content, "/devices"); 1360 if (start == NULL || 1361 strncmp(start, warg->path, warg->len) != 0 || 1362 start[warg->len] != ':') 1363 return (DI_WALK_CONTINUE); 1364 } 1365 1366 *(warg->linkpp) = strdup(di_devlink_path(link)); 1367 return (DI_WALK_TERMINATE); 1368 1369 } 1370 1371 /* 1372 * SUN_IMA_GetConnectionOidList - 1373 * 1374 * Non-IMA defined function. 1375 */ 1376 IMA_API IMA_STATUS SUN_IMA_GetConnOidList( 1377 IMA_OID *oid, 1378 IMA_OID_LIST **ppList 1379 ) 1380 { 1381 IMA_STATUS imaStatus; 1382 IMA_OID_LIST *imaOidList; 1383 iscsi_conn_list_t *iscsiConnList = NULL; 1384 int i; 1385 size_t allocLen; 1386 1387 if ((lhbaObjectId.objectType == oid->objectType) && 1388 (lhbaObjectId.ownerId == oid->ownerId) && 1389 (lhbaObjectId.objectSequenceNumber == oid->objectSequenceNumber)) { 1390 imaStatus = getConnOidList(NULL, &iscsiConnList); 1391 } else { 1392 if (oid->objectType == IMA_OBJECT_TYPE_TARGET) { 1393 imaStatus = getConnOidList(oid, &iscsiConnList); 1394 } else { 1395 return (IMA_ERROR_INCORRECT_OBJECT_TYPE); 1396 } 1397 } 1398 if (imaStatus != IMA_STATUS_SUCCESS) { 1399 return (imaStatus); 1400 } 1401 1402 /* 1403 * Based on the results a SUN_IMA_CONN_LIST structure is allocated. 1404 */ 1405 allocLen = iscsiConnList->cl_out_cnt * sizeof (IMA_OID); 1406 allocLen += sizeof (IMA_OID_LIST) - sizeof (IMA_OID); 1407 imaOidList = (IMA_OID_LIST *)calloc(1, allocLen); 1408 1409 if (imaOidList == NULL) { 1410 free(iscsiConnList); 1411 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1412 } 1413 1414 /* The data is transfered from iscsiConnList to imaConnList. */ 1415 imaOidList->oidCount = iscsiConnList->cl_out_cnt; 1416 for (i = 0; i < iscsiConnList->cl_out_cnt; i++) { 1417 imaOidList->oids[i].objectType = SUN_IMA_OBJECT_TYPE_CONN; 1418 imaOidList->oids[i].ownerId = 1; 1419 imaOidList->oids[i].objectSequenceNumber = 1420 iscsiConnList->cl_list[i].c_oid; 1421 } 1422 /* The pointer to the SUN_IMA_CONN_LIST structure is returned. */ 1423 *ppList = imaOidList; 1424 1425 free(iscsiConnList); 1426 return (IMA_STATUS_SUCCESS); 1427 } 1428 1429 /* 1430 * SUN_IMA_GetConnProperties - 1431 * 1432 * Non-IMA defined function. 1433 */ 1434 IMA_API IMA_STATUS SUN_IMA_GetConnProperties( 1435 IMA_OID *connOid, 1436 SUN_IMA_CONN_PROPERTIES **pProps 1437 ) 1438 { 1439 iscsi_conn_list_t *pConnList; 1440 iscsi_conn_props_t *pConnProps; 1441 /* LINTED */ 1442 struct sockaddr_in6 *addrIn6; 1443 /* LINTED */ 1444 struct sockaddr_in *addrIn; 1445 SUN_IMA_CONN_PROPERTIES *pImaConnProps; 1446 IMA_STATUS imaStatus; 1447 int i; 1448 1449 /* If there is any error *pProps should be set to NULL */ 1450 *pProps = NULL; 1451 1452 pImaConnProps = (SUN_IMA_CONN_PROPERTIES *)calloc(1, 1453 sizeof (SUN_IMA_CONN_PROPERTIES)); 1454 1455 if (pImaConnProps == NULL) { 1456 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1457 } 1458 1459 imaStatus = getConnOidList(NULL, &pConnList); 1460 1461 if (imaStatus != IMA_STATUS_SUCCESS) { 1462 free(pImaConnProps); 1463 return (imaStatus); 1464 } 1465 1466 /* 1467 * Walk the list returned to find our connection. 1468 */ 1469 for (i = 0; i < pConnList->cl_out_cnt; i++) { 1470 1471 if (pConnList->cl_list[i].c_oid == 1472 (uint32_t)connOid->objectSequenceNumber) { 1473 1474 /* This is our connection. */ 1475 imaStatus = getConnProps(&pConnList->cl_list[i], 1476 &pConnProps); 1477 1478 if (imaStatus != IMA_STATUS_SUCCESS) { 1479 free(pConnList); 1480 free(pImaConnProps); 1481 return (imaStatus); 1482 } 1483 pImaConnProps->connectionID = pConnProps->cp_cid; 1484 1485 /* 1486 * Local Propeties 1487 */ 1488 if (pConnProps->cp_local.soa4.sin_family == AF_INET) { 1489 1490 pImaConnProps->local.ipAddress.ipv4Address = 1491 IMA_TRUE; 1492 pImaConnProps->local.portNumber = 1493 pConnProps->cp_local.soa4.sin_port; 1494 addrIn = &(pConnProps->cp_local.soa4); 1495 bcopy(&pConnProps->cp_local.soa4.sin_addr, 1496 pImaConnProps->local.ipAddress.ipAddress, 1497 sizeof (addrIn->sin_addr)); 1498 1499 } else { 1500 pImaConnProps->local.ipAddress.ipv4Address = 1501 IMA_FALSE; 1502 pImaConnProps->local.portNumber = 1503 pConnProps->cp_local.soa6.sin6_port; 1504 addrIn6 = &(pConnProps->cp_local.soa6); 1505 bcopy(&pConnProps->cp_local.soa6.sin6_addr, 1506 pImaConnProps->local.ipAddress.ipAddress, 1507 sizeof (addrIn6->sin6_addr)); 1508 1509 } 1510 1511 /* 1512 * Peer Propeties 1513 */ 1514 if (pConnProps->cp_peer.soa4.sin_family == AF_INET) { 1515 1516 pImaConnProps->peer.ipAddress.ipv4Address = 1517 IMA_TRUE; 1518 pImaConnProps->peer.portNumber = 1519 pConnProps->cp_peer.soa4.sin_port; 1520 addrIn = &(pConnProps->cp_local.soa4); 1521 bcopy(&pConnProps->cp_peer.soa4.sin_addr, 1522 pImaConnProps->peer.ipAddress.ipAddress, 1523 sizeof (addrIn->sin_addr)); 1524 1525 } else { 1526 pImaConnProps->peer.ipAddress.ipv4Address = 1527 IMA_FALSE; 1528 pImaConnProps->peer.portNumber = 1529 pConnProps->cp_peer.soa6.sin6_port; 1530 1531 addrIn6 = &pConnProps->cp_local.soa6; 1532 bcopy(&pConnProps->cp_peer.soa6.sin6_addr, 1533 pImaConnProps->peer.ipAddress.ipAddress, 1534 sizeof (addrIn6->sin6_addr)); 1535 } 1536 1537 1538 pImaConnProps->valuesValid = 1539 pConnProps->cp_params_valid; 1540 pImaConnProps->defaultTime2Retain = 1541 pConnProps->cp_params.default_time_to_retain; 1542 pImaConnProps->defaultTime2Wait = 1543 pConnProps->cp_params.default_time_to_wait; 1544 pImaConnProps->errorRecoveryLevel = 1545 pConnProps->cp_params.error_recovery_level; 1546 pImaConnProps->firstBurstLength = 1547 pConnProps->cp_params.first_burst_length; 1548 pImaConnProps->maxBurstLength = 1549 pConnProps->cp_params.max_burst_length; 1550 pImaConnProps->maxConnections = 1551 pConnProps->cp_params.max_connections; 1552 pImaConnProps->maxOutstandingR2T = 1553 pConnProps->cp_params.max_outstanding_r2t; 1554 pImaConnProps->maxRecvDataSegmentLength = 1555 pConnProps->cp_params.max_recv_data_seg_len; 1556 1557 pImaConnProps->dataPduInOrder = 1558 pConnProps->cp_params.data_pdu_in_order; 1559 pImaConnProps->dataSequenceInOrder = 1560 pConnProps->cp_params.data_sequence_in_order; 1561 pImaConnProps->immediateData = 1562 pConnProps->cp_params.immediate_data; 1563 pImaConnProps->initialR2T = 1564 pConnProps->cp_params.initial_r2t; 1565 1566 pImaConnProps->headerDigest = 1567 pConnProps->cp_params.header_digest; 1568 pImaConnProps->dataDigest = 1569 pConnProps->cp_params.data_digest; 1570 1571 free(pConnProps); 1572 break; 1573 } 1574 } 1575 free(pConnList); 1576 *pProps = pImaConnProps; 1577 return (IMA_STATUS_SUCCESS); 1578 } 1579 1580 1581 /* 1582 * SUN_IMA_GetConfigSessions - 1583 * 1584 * Non-IMA defined function. 1585 */ 1586 IMA_API IMA_STATUS SUN_IMA_GetConfigSessions( 1587 IMA_OID targetOid, 1588 SUN_IMA_CONFIG_SESSIONS **pConfigSessions 1589 ) 1590 { 1591 int fd; 1592 int status; 1593 iscsi_config_sess_t *ics; 1594 int size, idx; 1595 1596 /* Allocate and setup initial buffer */ 1597 size = sizeof (*ics); 1598 ics = (iscsi_config_sess_t *)calloc(1, size); 1599 if (ics == NULL) { 1600 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1601 } 1602 ics->ics_ver = ISCSI_INTERFACE_VERSION; 1603 ics->ics_oid = targetOid.objectSequenceNumber; 1604 ics->ics_in = 1; 1605 1606 /* Open driver devctl for ioctl */ 1607 if ((status = open_driver(&fd))) { 1608 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1609 } 1610 1611 /* Issue ioctl request */ 1612 if (ioctl(fd, ISCSI_GET_CONFIG_SESSIONS, ics) != 0) { 1613 syslog(LOG_USER|LOG_DEBUG, 1614 "ISCSI_GET_CONFIG_SESSIONS ioctl failed, errno: %d", 1615 errno); 1616 (void) close(fd); 1617 free(ics); 1618 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1619 } 1620 1621 /* Check if we need to collect more information */ 1622 idx = ics->ics_out; 1623 if (idx > 1) { 1624 1625 /* Free old buffer and reallocate re-sized buffer */ 1626 free(ics); 1627 size = ISCSI_SESSION_CONFIG_SIZE(idx); 1628 ics = (iscsi_config_sess_t *)calloc(1, size); 1629 if (ics == NULL) { 1630 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1631 } 1632 ics->ics_ver = ISCSI_INTERFACE_VERSION; 1633 ics->ics_oid = targetOid.objectSequenceNumber; 1634 ics->ics_in = idx; 1635 1636 /* Issue ioctl request */ 1637 if (ioctl(fd, ISCSI_GET_CONFIG_SESSIONS, ics) != 0) { 1638 syslog(LOG_USER|LOG_DEBUG, 1639 "ISCSI_GET_CONFIG_SESSIONS ioctl failed, errno: %d", 1640 errno); 1641 (void) close(fd); 1642 free(ics); 1643 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1644 } 1645 } 1646 (void) close(fd); 1647 1648 /* Allocate output buffer */ 1649 size = sizeof (SUN_IMA_CONFIG_SESSIONS) + 1650 ((ics->ics_out - 1) * sizeof (IMA_ADDRESS_KEY)); 1651 *pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 1652 if ((*pConfigSessions) == NULL) { 1653 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1654 } 1655 1656 /* Copy output information */ 1657 (*pConfigSessions)->bound = 1658 (ics->ics_bound == B_TRUE ? IMA_TRUE : IMA_FALSE); 1659 (*pConfigSessions)->in = ics->ics_in; 1660 (*pConfigSessions)->out = ics->ics_out; 1661 for (idx = 0; idx < ics->ics_in; idx++) { 1662 if (ics->ics_bindings[idx].i_insize == 1663 sizeof (struct in_addr)) { 1664 (*pConfigSessions)->bindings[idx].ipAddress. 1665 ipv4Address = IMA_TRUE; 1666 bcopy(&ics->ics_bindings[idx].i_addr.in4, 1667 (*pConfigSessions)->bindings[idx].ipAddress. 1668 ipAddress, sizeof (struct in_addr)); 1669 } else { 1670 (*pConfigSessions)->bindings[idx].ipAddress. 1671 ipv4Address = IMA_FALSE; 1672 bcopy(&ics->ics_bindings[idx].i_addr.in6, 1673 (*pConfigSessions)->bindings[idx].ipAddress. 1674 ipAddress, sizeof (struct in6_addr)); 1675 } 1676 } 1677 1678 free(ics); 1679 return (IMA_STATUS_SUCCESS); 1680 } 1681 1682 /* 1683 * SUN_IMA_SetConfigSessions - 1684 * 1685 * Non-IMA defined function. 1686 */ 1687 IMA_API IMA_STATUS SUN_IMA_SetConfigSessions( 1688 IMA_OID targetOid, 1689 SUN_IMA_CONFIG_SESSIONS *pConfigSessions 1690 ) 1691 { 1692 int fd; 1693 int status; 1694 iscsi_config_sess_t *ics; 1695 int idx, size; 1696 1697 /* verify allowed range of sessions */ 1698 if ((pConfigSessions->in < ISCSI_MIN_CONFIG_SESSIONS) || 1699 (pConfigSessions->in > ISCSI_MAX_CONFIG_SESSIONS)) { 1700 return (IMA_ERROR_INVALID_PARAMETER); 1701 } 1702 1703 /* allocate record config_sess size */ 1704 size = ISCSI_SESSION_CONFIG_SIZE(pConfigSessions->in); 1705 ics = (iscsi_config_sess_t *)malloc(size); 1706 1707 /* setup config_sess information */ 1708 (void) memset(ics, 0, sizeof (iscsi_config_sess_t)); 1709 ics->ics_ver = ISCSI_INTERFACE_VERSION; 1710 ics->ics_oid = targetOid.objectSequenceNumber; 1711 ics->ics_bound = 1712 (pConfigSessions->bound == IMA_TRUE ? B_TRUE : B_FALSE); 1713 ics->ics_in = pConfigSessions->in; 1714 for (idx = 0; idx < ics->ics_in; idx++) { 1715 if (pConfigSessions->bindings[idx].ipAddress. 1716 ipv4Address == IMA_TRUE) { 1717 ics->ics_bindings[idx].i_insize = 1718 sizeof (struct in_addr); 1719 bcopy(pConfigSessions->bindings[idx]. 1720 ipAddress.ipAddress, 1721 &ics->ics_bindings[idx].i_addr.in4, 1722 sizeof (struct in_addr)); 1723 } else { 1724 ics->ics_bindings[idx].i_insize = 1725 sizeof (struct in6_addr); 1726 bcopy(pConfigSessions->bindings[idx]. 1727 ipAddress.ipAddress, 1728 &ics->ics_bindings[idx].i_addr.in6, 1729 sizeof (struct in6_addr)); 1730 } 1731 } 1732 1733 /* open driver */ 1734 if ((status = open_driver(&fd))) { 1735 free(ics); 1736 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1737 } 1738 1739 /* issue ioctl request */ 1740 if (ioctl(fd, ISCSI_SET_CONFIG_SESSIONS, ics) != 0) { 1741 syslog(LOG_USER|LOG_DEBUG, 1742 "ISCSI_SET_CONFIG_SESSIONS ioctl failed, errno: %d", 1743 errno); 1744 (void) close(fd); 1745 free(ics); 1746 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1747 } 1748 (void) close(fd); 1749 free(ics); 1750 return (IMA_STATUS_SUCCESS); 1751 } 1752 1753 /* A helper function to obtain iSCSI node parameters. */ 1754 static IMA_STATUS 1755 getISCSINodeParameter( 1756 int paramType, 1757 IMA_OID *oid, 1758 void *pProps, 1759 uint32_t paramIndex 1760 ) 1761 { 1762 int fd; 1763 int status; 1764 iscsi_param_get_t pg; 1765 1766 if ((status = open_driver(&fd))) { 1767 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1768 } 1769 1770 (void) memset(&pg, 0, sizeof (iscsi_param_get_t)); 1771 pg.g_vers = ISCSI_INTERFACE_VERSION; 1772 pg.g_oid = (uint32_t)oid->objectSequenceNumber; 1773 pg.g_param = paramIndex; 1774 pg.g_param_type = ISCSI_SESS_PARAM; 1775 1776 if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) { 1777 syslog(LOG_USER|LOG_DEBUG, 1778 "ISCSI_PARAM_GET ioctl failed, errno: %d", errno); 1779 (void) close(fd); 1780 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1781 } 1782 1783 switch (paramType) { 1784 IMA_BOOL_VALUE *bp; 1785 IMA_MIN_MAX_VALUE *mp; 1786 1787 case MIN_MAX_PARAM: 1788 mp = (IMA_MIN_MAX_VALUE *)pProps; 1789 1790 mp->currentValueValid = 1791 (pg.g_value.v_valid == B_TRUE) ? 1792 IMA_TRUE : IMA_FALSE; 1793 mp->currentValue = pg.g_value.v_integer.i_current; 1794 mp->defaultValue = pg.g_value.v_integer.i_default; 1795 mp->minimumValue = pg.g_value.v_integer.i_min; 1796 mp->maximumValue = pg.g_value.v_integer.i_max; 1797 mp->incrementValue = pg.g_value.v_integer.i_incr; 1798 break; 1799 1800 case BOOL_PARAM: 1801 bp = (IMA_BOOL_VALUE *)pProps; 1802 bp->currentValueValid = 1803 (pg.g_value.v_valid == B_TRUE) ? 1804 IMA_TRUE : IMA_FALSE; 1805 bp->currentValue = pg.g_value.v_bool.b_current; 1806 bp->defaultValue = pg.g_value.v_bool.b_default; 1807 break; 1808 1809 default: 1810 break; 1811 } 1812 1813 /* Issue ISCSI_PARAM_GET ioctl again to obtain connection parameters. */ 1814 pg.g_param_type = ISCSI_CONN_PARAM; 1815 if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) { 1816 syslog(LOG_USER|LOG_DEBUG, 1817 "ISCSI_PARAM_GET ioctl failed, errno: %d", errno); 1818 (void) close(fd); 1819 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1820 } 1821 1822 (void) close(fd); 1823 return (IMA_STATUS_SUCCESS); 1824 } 1825 1826 /* A helper function to set iSCSI node parameters. */ 1827 static IMA_STATUS 1828 setISCSINodeParameter( 1829 int paramType, 1830 IMA_OID *oid, 1831 void *pProp, 1832 uint32_t paramIndex 1833 ) 1834 { 1835 int fd; 1836 int status; 1837 iscsi_param_set_t ps; 1838 1839 if ((status = open_driver(&fd))) { 1840 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1841 } 1842 1843 (void) memset(&ps, 0, sizeof (iscsi_param_set_t)); 1844 ps.s_vers = ISCSI_INTERFACE_VERSION; 1845 ps.s_oid = (uint32_t)oid->objectSequenceNumber; 1846 ps.s_param = paramIndex; 1847 1848 switch (paramType) { 1849 IMA_BOOL_VALUE *bp; 1850 IMA_MIN_MAX_VALUE *mp; 1851 1852 case MIN_MAX_PARAM: 1853 mp = (IMA_MIN_MAX_VALUE *)pProp; 1854 ps.s_value.v_integer = mp->currentValue; 1855 break; 1856 case BOOL_PARAM: 1857 bp = (IMA_BOOL_VALUE *)pProp; 1858 ps.s_value.v_bool = 1859 (bp->currentValue == IMA_TRUE) ? 1860 B_TRUE : B_FALSE; 1861 break; 1862 1863 default: 1864 break; 1865 } 1866 if (ioctl(fd, ISCSI_PARAM_SET, &ps)) { 1867 (void) close(fd); 1868 syslog(LOG_USER|LOG_DEBUG, 1869 "ISCSI_PARAM_SET ioctl failed, errno: %d", errno); 1870 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1871 } 1872 1873 (void) close(fd); 1874 return (IMA_STATUS_SUCCESS); 1875 } 1876 1877 static int 1878 prepare_discovery_entry( 1879 SUN_IMA_TARGET_ADDRESS discoveryAddress, 1880 entry_t *entry 1881 ) 1882 { 1883 return (prepare_discovery_entry_IMA(discoveryAddress.imaStruct, entry)); 1884 } 1885 1886 static int 1887 prepare_discovery_entry_IMA( 1888 IMA_TARGET_ADDRESS discoveryAddress, 1889 entry_t *entry 1890 ) 1891 { 1892 (void) memset(entry, 0, sizeof (entry_t)); 1893 entry->e_vers = ISCSI_INTERFACE_VERSION; 1894 entry->e_oid = ISCSI_OID_NOTSET; 1895 1896 if (discoveryAddress.hostnameIpAddress.id.ipAddress. 1897 ipv4Address == IMA_FALSE) { 1898 1899 bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress. 1900 ipAddress, entry->e_u.u_in6.s6_addr, 1901 sizeof (entry->e_u.u_in6.s6_addr)); 1902 1903 entry->e_insize = sizeof (struct in6_addr); 1904 } else { 1905 1906 bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress. 1907 ipAddress, &entry->e_u.u_in4.s_addr, 1908 sizeof (entry->e_u.u_in4.s_addr)); 1909 1910 entry->e_insize = sizeof (struct in_addr); 1911 } 1912 1913 entry->e_port = discoveryAddress.portNumber; 1914 entry->e_tpgt = 0; 1915 return (DISC_ADDR_OK); 1916 } 1917 1918 static IMA_STATUS configure_discovery_method( 1919 IMA_BOOL enable, 1920 iSCSIDiscoveryMethod_t method 1921 ) 1922 { 1923 int fd, status; 1924 1925 if ((status = open_driver(&fd))) { 1926 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1927 } 1928 1929 if (enable == IMA_FALSE) { 1930 if (ioctl(fd, ISCSI_DISCOVERY_CLEAR, &method)) { 1931 status = errno; 1932 (void) close(fd); 1933 syslog(LOG_USER|LOG_DEBUG, 1934 "ISCSI_DISCOVERY_CLEAR ioctl failed, errno: %d", 1935 status); 1936 if (status == EBUSY) { 1937 return (IMA_ERROR_LU_IN_USE); 1938 } else { 1939 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1940 } 1941 } 1942 1943 (void) close(fd); 1944 return (IMA_STATUS_SUCCESS); 1945 } else { 1946 /* Set the discovery method */ 1947 if (ioctl(fd, ISCSI_DISCOVERY_SET, &method)) { 1948 status = errno; 1949 (void) close(fd); 1950 syslog(LOG_USER|LOG_DEBUG, 1951 "ISCSI_DISCOVERY_SET ioctl failed, errno: %d", 1952 status); 1953 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1954 } 1955 1956 (void) close(fd); 1957 return (IMA_STATUS_SUCCESS); 1958 } 1959 } 1960 1961 /* LINTED E_STATIC_UNUSED */ 1962 static IMA_BOOL authMethodMatch( 1963 IMA_AUTHMETHOD matchingMethod, 1964 IMA_AUTHMETHOD *methodList, 1965 IMA_UINT maxEntries 1966 ) 1967 { 1968 IMA_UINT i; 1969 1970 for (i = 0; i < maxEntries; i++) { 1971 if (methodList[i] == matchingMethod) { 1972 return (IMA_TRUE); 1973 } 1974 } 1975 1976 return (IMA_FALSE); 1977 } 1978 1979 static IMA_STATUS get_target_oid_list( 1980 uint32_t targetListType, 1981 IMA_OID_LIST **ppList) 1982 { 1983 int fd; 1984 int i; 1985 int target_list_size; 1986 int status; 1987 int out_cnt; 1988 iscsi_target_list_t *idlp; 1989 1990 if ((status = open_driver(&fd))) { 1991 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1992 } 1993 1994 idlp = (iscsi_target_list_t *)calloc(1, sizeof (iscsi_target_list_t)); 1995 if (idlp == NULL) { 1996 (void) close(fd); 1997 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1998 } 1999 idlp->tl_vers = ISCSI_INTERFACE_VERSION; 2000 idlp->tl_in_cnt = idlp->tl_out_cnt = 1; 2001 idlp->tl_tgt_list_type = targetListType; 2002 2003 /* 2004 * Issue ioctl. Space has been allocted for one entry. 2005 * If more than one entry should be returned, we will re-issue the 2006 * entry with the right amount of space allocted 2007 */ 2008 if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) { 2009 (void) close(fd); 2010 syslog(LOG_USER|LOG_DEBUG, 2011 "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d", 2012 targetListType, errno); 2013 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2014 } 2015 if (idlp->tl_out_cnt > 1) { 2016 out_cnt = idlp->tl_out_cnt; 2017 free(idlp); 2018 2019 target_list_size = sizeof (iscsi_target_list_t); 2020 target_list_size += (sizeof (uint32_t) * out_cnt - 1); 2021 idlp = (iscsi_target_list_t *)calloc(1, target_list_size); 2022 if (idlp == NULL) { 2023 (void) close(fd); 2024 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2025 } 2026 idlp->tl_vers = ISCSI_INTERFACE_VERSION; 2027 idlp->tl_in_cnt = out_cnt; 2028 idlp->tl_tgt_list_type = targetListType; 2029 2030 /* Issue the same ioctl again to obtain all the OIDs. */ 2031 if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) { 2032 #define ERROR_STR "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno :%d" 2033 free(idlp); 2034 (void) close(fd); 2035 syslog(LOG_USER|LOG_DEBUG, 2036 ERROR_STR, targetListType, errno); 2037 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2038 #undef ERROR_STR 2039 2040 } 2041 } 2042 2043 *ppList = (IMA_OID_LIST *)calloc(1, sizeof (IMA_OID_LIST) + 2044 idlp->tl_out_cnt * sizeof (IMA_OID)); 2045 (*ppList)->oidCount = idlp->tl_out_cnt; 2046 for (i = 0; i < idlp->tl_out_cnt; i++) { 2047 (*ppList)->oids[i].objectType = IMA_OBJECT_TYPE_TARGET; 2048 (*ppList)->oids[i].ownerId = 1; 2049 (*ppList)->oids[i].objectSequenceNumber = idlp->tl_oid_list[i]; 2050 } 2051 2052 free(idlp); 2053 (void) close(fd); 2054 return (IMA_STATUS_SUCCESS); 2055 } 2056 2057 static IMA_STATUS get_target_lun_oid_list( 2058 IMA_OID * targetOid, 2059 iscsi_lun_list_t **ppLunList) 2060 { 2061 int fd; 2062 iscsi_lun_list_t *illp, *illp_saved; 2063 int lun_list_size; 2064 int status; 2065 2066 if ((status = open_driver(&fd))) { 2067 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2068 } 2069 2070 illp = (iscsi_lun_list_t *)calloc(1, sizeof (iscsi_lun_list_t)); 2071 if (illp == NULL) { 2072 (void) close(fd); 2073 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2074 } 2075 illp->ll_vers = ISCSI_INTERFACE_VERSION; 2076 if (targetOid == NULL) { 2077 /* get lun oid list for all targets */ 2078 illp->ll_all_tgts = B_TRUE; 2079 } else { 2080 /* get lun oid list for single target */ 2081 illp->ll_all_tgts = B_FALSE; 2082 illp->ll_tgt_oid = (uint32_t)targetOid->objectSequenceNumber; 2083 } 2084 illp->ll_in_cnt = illp->ll_out_cnt = 1; 2085 2086 /* 2087 * Issue ioctl to retrieve the target luns. Space has been allocted 2088 * for one entry. If more than one entry should be returned, we 2089 * will re-issue the entry with the right amount of space allocted 2090 */ 2091 if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) { 2092 (void) close(fd); 2093 syslog(LOG_USER|LOG_DEBUG, 2094 "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", errno); 2095 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2096 } 2097 2098 if (illp->ll_out_cnt > 1) { 2099 illp_saved = illp; 2100 lun_list_size = sizeof (iscsi_lun_list_t); 2101 lun_list_size += (sizeof (iscsi_if_lun_t) * 2102 (illp->ll_out_cnt - 1)); 2103 illp = (iscsi_lun_list_t *)calloc(1, lun_list_size); 2104 if (illp == NULL) { 2105 (void) close(fd); 2106 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2107 } 2108 illp->ll_vers = ISCSI_INTERFACE_VERSION; 2109 illp->ll_all_tgts = illp_saved->ll_all_tgts; 2110 illp->ll_tgt_oid = illp_saved->ll_tgt_oid; 2111 illp->ll_in_cnt = illp_saved->ll_out_cnt; 2112 2113 free(illp_saved); 2114 2115 /* Issue the same ioctl again to get all the target LUN list */ 2116 if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) { 2117 free(illp); 2118 (void) close(fd); 2119 syslog(LOG_USER|LOG_DEBUG, 2120 "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", 2121 errno); 2122 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2123 2124 } 2125 } 2126 *ppLunList = illp; 2127 2128 2129 (void) close(fd); 2130 return (IMA_STATUS_SUCCESS); 2131 } 2132 2133 /* A helper function to obtain digest algorithms. */ 2134 static IMA_STATUS 2135 getDigest( 2136 IMA_OID oid, 2137 int ioctlCmd, 2138 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm 2139 ) 2140 { 2141 IMA_MIN_MAX_VALUE pProps; 2142 IMA_STATUS status; 2143 2144 if ((status = getISCSINodeParameter(MIN_MAX_PARAM, &oid, &pProps, 2145 ioctlCmd)) != IMA_STATUS_SUCCESS) { 2146 return (status); 2147 } 2148 2149 switch (pProps.defaultValue) { 2150 case ISCSI_DIGEST_NONE: 2151 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_NONE; 2152 algorithm->defaultAlgorithmCount = 1; 2153 break; 2154 case ISCSI_DIGEST_CRC32C: 2155 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_CRC32C; 2156 algorithm->defaultAlgorithmCount = 1; 2157 break; 2158 2159 case ISCSI_DIGEST_CRC32C_NONE: 2160 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_CRC32C; 2161 algorithm->defaultAlgorithms[1] = ISCSI_DIGEST_NONE; 2162 algorithm->defaultAlgorithmCount = 2; 2163 break; 2164 case ISCSI_DIGEST_NONE_CRC32C: 2165 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_NONE; 2166 algorithm->defaultAlgorithms[1] = ISCSI_DIGEST_CRC32C; 2167 algorithm->defaultAlgorithmCount = 2; 2168 break; 2169 default: 2170 /* Error */ 2171 syslog(LOG_USER|LOG_DEBUG, 2172 "Invalid default digest: %d", pProps.defaultValue); 2173 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2174 } 2175 2176 /* The configured value */ 2177 if (pProps.currentValueValid == IMA_TRUE) { 2178 algorithm->currentValid = IMA_TRUE; 2179 2180 switch (pProps.currentValue) { 2181 case ISCSI_DIGEST_NONE: 2182 algorithm->currentAlgorithms[0] = 2183 ISCSI_DIGEST_NONE; 2184 algorithm->currentAlgorithmCount = 1; 2185 break; 2186 case ISCSI_DIGEST_CRC32C: 2187 algorithm->currentAlgorithms[0] = 2188 ISCSI_DIGEST_CRC32C; 2189 algorithm->currentAlgorithmCount = 1; 2190 break; 2191 2192 case ISCSI_DIGEST_CRC32C_NONE: 2193 algorithm->currentAlgorithms[0] = 2194 ISCSI_DIGEST_CRC32C; 2195 algorithm->currentAlgorithms[1] = 2196 ISCSI_DIGEST_NONE; 2197 algorithm->currentAlgorithmCount = 2; 2198 break; 2199 case ISCSI_DIGEST_NONE_CRC32C: 2200 algorithm->currentAlgorithms[0] = 2201 ISCSI_DIGEST_NONE; 2202 algorithm->currentAlgorithms[1] = 2203 ISCSI_DIGEST_CRC32C; 2204 algorithm->currentAlgorithmCount = 2; 2205 break; 2206 default: 2207 /* Error */ 2208 syslog(LOG_USER|LOG_DEBUG, 2209 "Invalid configured digest: %d", 2210 pProps.defaultValue); 2211 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2212 } 2213 2214 } else { 2215 algorithm->currentValid = IMA_FALSE; 2216 } 2217 2218 return (IMA_STATUS_SUCCESS); 2219 } 2220 2221 /* 2222 * getConnOidList - 2223 */ 2224 static IMA_STATUS getConnOidList( 2225 IMA_OID *sessOid, 2226 iscsi_conn_list_t **ppConnList 2227 ) 2228 { 2229 iscsi_conn_list_t *iscsiConnList = NULL; 2230 size_t allocLen; 2231 int fd; 2232 int status; 2233 int out_cnt; 2234 2235 /* Preset it to NULL to prepare for the case of failure */ 2236 *ppConnList = NULL; 2237 2238 /* We try to open the driver now. */ 2239 if ((status = open_driver(&fd))) { 2240 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2241 } 2242 2243 iscsiConnList = (iscsi_conn_list_t *)calloc(1, 2244 sizeof (iscsi_conn_list_t)); 2245 if (iscsiConnList == NULL) { 2246 (void) close(fd); 2247 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2248 } 2249 iscsiConnList->cl_vers = ISCSI_INTERFACE_VERSION; 2250 iscsiConnList->cl_in_cnt = iscsiConnList->cl_out_cnt = 1; 2251 if (sessOid == NULL) { 2252 iscsiConnList->cl_all_sess = B_TRUE; 2253 } else { 2254 iscsiConnList->cl_all_sess = B_FALSE; 2255 iscsiConnList->cl_sess_oid = 2256 (uint32_t)sessOid->objectSequenceNumber; 2257 } 2258 /* 2259 * Issue ioctl to retrieve the connection OIDs. Space has been 2260 * allocated for one entry. If more than one entry should be 2261 * returned, we will re-issue the entry with the right amount of 2262 * space allocted 2263 */ 2264 if (ioctl(fd, ISCSI_CONN_OID_LIST_GET, iscsiConnList) != 0) { 2265 syslog(LOG_USER|LOG_DEBUG, 2266 "ISCSI_CONN_OID_LIST_GET ioctl failed, errno: %d", errno); 2267 *ppConnList = NULL; 2268 (void) close(fd); 2269 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2270 } 2271 if (iscsiConnList->cl_out_cnt > 1) { 2272 out_cnt = iscsiConnList->cl_out_cnt; 2273 free(iscsiConnList); 2274 2275 allocLen = sizeof (iscsi_conn_list_t); 2276 allocLen += (sizeof (iscsi_if_conn_t) * out_cnt - 1); 2277 iscsiConnList = (iscsi_conn_list_t *)calloc(1, allocLen); 2278 if (iscsiConnList == NULL) { 2279 *ppConnList = NULL; 2280 (void) close(fd); 2281 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2282 } 2283 iscsiConnList->cl_vers = ISCSI_INTERFACE_VERSION; 2284 iscsiConnList->cl_in_cnt = out_cnt; 2285 if (sessOid == NULL) { 2286 iscsiConnList->cl_all_sess = B_TRUE; 2287 } else { 2288 iscsiConnList->cl_all_sess = B_FALSE; 2289 iscsiConnList->cl_sess_oid = 2290 (uint32_t)sessOid->objectSequenceNumber; 2291 } 2292 /* Issue the same ioctl again to obtain all the OIDs */ 2293 if (ioctl(fd, ISCSI_CONN_OID_LIST_GET, iscsiConnList) != 0) { 2294 2295 syslog(LOG_USER|LOG_DEBUG, 2296 "ISCSI_CONN_OID_LIST_GET ioctl failed, errno: %d", 2297 errno); 2298 *ppConnList = NULL; 2299 free(iscsiConnList); 2300 (void) close(fd); 2301 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2302 2303 } 2304 2305 if (out_cnt < iscsiConnList->cl_out_cnt) { 2306 /* 2307 * The connection list grew between the first and second 2308 * ioctls. 2309 */ 2310 syslog(LOG_USER|LOG_DEBUG, 2311 "The connection list has grown. There could be " 2312 "more connections than listed."); 2313 } 2314 } 2315 2316 2317 (void) close(fd); 2318 *ppConnList = iscsiConnList; 2319 return (IMA_STATUS_SUCCESS); 2320 } 2321 2322 /* 2323 * getConnProps - 2324 */ 2325 static IMA_STATUS getConnProps( 2326 iscsi_if_conn_t *pConn, 2327 iscsi_conn_props_t **ppConnProps 2328 ) 2329 { 2330 iscsi_conn_props_t *iscsiConnProps; 2331 int fd; 2332 int status; 2333 2334 /* We try to open the driver. */ 2335 if ((status = open_driver(&fd))) { 2336 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2337 } 2338 2339 iscsiConnProps = (iscsi_conn_props_t *)calloc(1, 2340 sizeof (*iscsiConnProps)); 2341 2342 if (iscsiConnProps == NULL) { 2343 (void) close(fd); 2344 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2345 } 2346 2347 iscsiConnProps->cp_vers = ISCSI_INTERFACE_VERSION; 2348 iscsiConnProps->cp_oid = pConn->c_oid; 2349 iscsiConnProps->cp_cid = pConn->c_cid; 2350 iscsiConnProps->cp_sess_oid = pConn->c_sess_oid; 2351 2352 /* The IOCTL is submitted. */ 2353 if (ioctl(fd, ISCSI_CONN_PROPS_GET, iscsiConnProps) != 0) { 2354 /* IOCTL failed */ 2355 syslog(LOG_USER|LOG_DEBUG, 2356 "ISCSI_AUTH_CLEAR ioctl failed, errno: %d", errno); 2357 free(iscsiConnProps); 2358 (void) close(fd); 2359 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2360 } 2361 (void) close(fd); 2362 *ppConnProps = iscsiConnProps; 2363 return (IMA_STATUS_SUCCESS); 2364 } 2365 2366 /* A helper function to set authentication method. */ 2367 static IMA_STATUS 2368 setAuthMethods( 2369 IMA_OID oid, 2370 IMA_UINT *pMethodCount, 2371 const IMA_AUTHMETHOD *pMethodList 2372 ) 2373 { 2374 int fd; 2375 int i; 2376 int status; 2377 iscsi_auth_props_t auth; 2378 2379 if ((status = open_driver(&fd))) { 2380 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2381 } 2382 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t)); 2383 auth.a_vers = ISCSI_INTERFACE_VERSION; 2384 auth.a_oid = (uint32_t)oid.objectSequenceNumber; 2385 2386 /* 2387 * Get the current auth fields so they don't need to be reset 2388 * here. 2389 */ 2390 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) { 2391 /* EMPTY */ 2392 /* Initializing auth structure with current settings */ 2393 } 2394 auth.a_auth_method = authMethodNone; 2395 2396 for (i = 0; i < *pMethodCount; i++) { 2397 switch (pMethodList[i]) { 2398 case IMA_AUTHMETHOD_CHAP: 2399 auth.a_auth_method |= authMethodCHAP; 2400 break; 2401 default: 2402 break; 2403 } 2404 } 2405 2406 if (ioctl(fd, ISCSI_AUTH_SET, &auth) != 0) { 2407 syslog(LOG_USER|LOG_DEBUG, 2408 "ISCSI_AUTH_SET failed, errno: %d", errno); 2409 (void) close(fd); 2410 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2411 } 2412 2413 (void) close(fd); 2414 return (IMA_STATUS_SUCCESS); 2415 } 2416 2417 /* A helper function to set authentication method. */ 2418 static IMA_STATUS getAuthMethods( 2419 IMA_OID oid, 2420 IMA_UINT *pMethodCount, 2421 IMA_AUTHMETHOD *pMethodList 2422 ) 2423 { 2424 int fd; 2425 int status; 2426 iscsi_auth_props_t auth; 2427 2428 if ((status = open_driver(&fd))) { 2429 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2430 } 2431 2432 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t)); 2433 auth.a_vers = ISCSI_INTERFACE_VERSION; 2434 auth.a_oid = (uint32_t)oid.objectSequenceNumber; 2435 2436 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) { 2437 syslog(LOG_USER|LOG_DEBUG, 2438 "ISCSI_AUTH_GET failed, errno: %d", errno); 2439 (void) close(fd); 2440 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2441 } 2442 2443 if (auth.a_auth_method == authMethodNone) { 2444 pMethodList[0] = IMA_AUTHMETHOD_NONE; 2445 *pMethodCount = 1; 2446 } else { 2447 int i = 0; 2448 if (!((auth.a_auth_method & authMethodCHAP)^authMethodCHAP)) { 2449 pMethodList[i++] = IMA_AUTHMETHOD_CHAP; 2450 } 2451 *pMethodCount = i; 2452 } 2453 2454 (void) close(fd); 2455 return (IMA_STATUS_SUCCESS); 2456 } 2457 2458 /* Helper function to open driver */ 2459 int open_driver( 2460 int *fd 2461 ) 2462 { 2463 int ret = 0; 2464 if ((*fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 2465 ret = errno; 2466 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)", 2467 ISCSI_DRIVER_DEVCTL, ret); 2468 } 2469 return (ret); 2470 } 2471 2472 /* 2473 * Iscsi driver does not support OID for discovery address. Create 2474 * a modified version of IMA_RemoveDiscoveryAddress that takes 2475 * discoveryAddress (instead of an OID) as input argument. 2476 */ 2477 IMA_API IMA_STATUS SUN_IMA_RemoveDiscoveryAddress( 2478 SUN_IMA_TARGET_ADDRESS discoveryAddress 2479 ) 2480 { 2481 entry_t entry; 2482 int fd; 2483 int status, i, addr_list_size, insize; 2484 iscsi_addr_list_t *idlp, al_info; 2485 iscsi_addr_t *matched_addr = NULL; 2486 2487 if ((status = open_driver(&fd))) { 2488 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2489 } 2490 2491 if (prepare_discovery_entry(discoveryAddress, &entry) != 2492 DISC_ADDR_OK) { 2493 (void) close(fd); 2494 return (IMA_ERROR_INVALID_PARAMETER); 2495 } 2496 2497 (void) memset(&al_info, 0, sizeof (al_info)); 2498 al_info.al_vers = ISCSI_INTERFACE_VERSION; 2499 al_info.al_in_cnt = 0; 2500 /* 2501 * Issue ioctl to get the number of discovery address. 2502 */ 2503 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) { 2504 syslog(LOG_USER|LOG_DEBUG, 2505 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d", 2506 ISCSI_DISCOVERY_ADDR_LIST_GET, errno); 2507 (void) close(fd); 2508 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2509 } 2510 2511 if (al_info.al_out_cnt == 0) { 2512 (void) close(fd); 2513 return (IMA_ERROR_OBJECT_NOT_FOUND); 2514 } 2515 2516 addr_list_size = sizeof (iscsi_addr_list_t); 2517 if (al_info.al_out_cnt > 1) { 2518 addr_list_size += (sizeof (iscsi_addr_t) * 2519 (al_info.al_out_cnt - 1)); 2520 } 2521 2522 idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size); 2523 if (idlp == NULL) { 2524 (void) close(fd); 2525 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2526 } 2527 2528 idlp->al_vers = ISCSI_INTERFACE_VERSION; 2529 idlp->al_in_cnt = al_info.al_out_cnt; 2530 2531 /* issue the same ioctl to get all the discovery addresses */ 2532 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) { 2533 syslog(LOG_USER|LOG_DEBUG, 2534 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d", 2535 ISCSI_DISCOVERY_ADDR_LIST_GET, errno); 2536 free(idlp); 2537 (void) close(fd); 2538 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2539 } 2540 2541 /* 2542 * find the matched discovery address 2543 */ 2544 for (i = 0; i < idlp->al_out_cnt; i++) { 2545 insize = idlp->al_addrs[i].a_addr.i_insize; 2546 if (insize != entry.e_insize) { 2547 continue; 2548 } 2549 if (insize == sizeof (struct in_addr)) { 2550 if (idlp->al_addrs[i].a_addr.i_addr.in4.s_addr == 2551 entry.e_u.u_in4.s_addr) { 2552 matched_addr = &(idlp->al_addrs[i]); 2553 break; 2554 } 2555 } 2556 if (insize == sizeof (struct in6_addr)) { 2557 if (bcmp(entry.e_u.u_in6.s6_addr, 2558 idlp->al_addrs[i].a_addr.i_addr.in6.s6_addr, 2559 insize) == 0) { 2560 matched_addr = &(idlp->al_addrs[i]); 2561 break; 2562 } 2563 } 2564 } 2565 2566 free(idlp); 2567 2568 if (matched_addr == NULL) { 2569 (void) close(fd); 2570 return (IMA_ERROR_OBJECT_NOT_FOUND); 2571 } 2572 2573 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_CLEAR, &entry)) { 2574 status = errno; 2575 (void) close(fd); 2576 syslog(LOG_USER|LOG_DEBUG, 2577 "ISCSI_DISCOVERY_ADDR_CLEAR ioctl failed, errno: %d", 2578 errno); 2579 if (status == EBUSY) { 2580 return (IMA_ERROR_LU_IN_USE); 2581 } else { 2582 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2583 } 2584 } 2585 2586 (void) close(fd); 2587 return (IMA_STATUS_SUCCESS); 2588 } 2589 2590 IMA_STATUS SUN_IMA_SetTargetAuthMethods( 2591 IMA_OID targetOid, 2592 IMA_UINT *methodCount, 2593 const IMA_AUTHMETHOD *pMethodList 2594 ) 2595 { 2596 return (setAuthMethods(targetOid, methodCount, pMethodList)); 2597 } 2598 2599 IMA_STATUS getNegotiatedDigest( 2600 int digestType, 2601 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm, 2602 SUN_IMA_CONN_PROPERTIES *connProps) { 2603 2604 IMA_UINT digest; 2605 2606 if (connProps->valuesValid == IMA_TRUE) { 2607 algorithm->negotiatedValid = IMA_TRUE; 2608 2609 if (digestType == ISCSI_LOGIN_PARAM_HEADER_DIGEST) { 2610 digest = connProps->headerDigest; 2611 } else { 2612 digest = connProps->dataDigest; 2613 } 2614 2615 switch (digest) { 2616 case ISCSI_DIGEST_NONE: 2617 algorithm->negotiatedAlgorithms[0] = 2618 ISCSI_DIGEST_NONE; 2619 algorithm->negotiatedAlgorithmCount = 1; 2620 break; 2621 case ISCSI_DIGEST_CRC32C: 2622 algorithm->negotiatedAlgorithms[0] = 2623 ISCSI_DIGEST_CRC32C; 2624 algorithm->negotiatedAlgorithmCount = 1; 2625 break; 2626 2627 case ISCSI_DIGEST_CRC32C_NONE: 2628 algorithm->negotiatedAlgorithms[0] = 2629 ISCSI_DIGEST_CRC32C; 2630 algorithm->negotiatedAlgorithms[1] = 2631 ISCSI_DIGEST_NONE; 2632 algorithm->negotiatedAlgorithmCount = 2; 2633 break; 2634 case ISCSI_DIGEST_NONE_CRC32C: 2635 algorithm->negotiatedAlgorithms[0] = 2636 ISCSI_DIGEST_NONE; 2637 algorithm->negotiatedAlgorithms[1] = 2638 ISCSI_DIGEST_CRC32C; 2639 algorithm->negotiatedAlgorithmCount = 2; 2640 break; 2641 default: 2642 syslog(LOG_USER|LOG_DEBUG, 2643 "Invalid negotiated digest: %d", 2644 digest); 2645 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2646 } 2647 } else { 2648 algorithm->negotiatedValid = IMA_FALSE; 2649 } 2650 return (IMA_STATUS_SUCCESS); 2651 } 2652 2653 /* 2654 * Non-IMA defined function. 2655 */ 2656 IMA_API IMA_STATUS SUN_IMA_GetISNSServerAddressPropertiesList( 2657 SUN_IMA_DISC_ADDR_PROP_LIST **ppList 2658 ) 2659 { 2660 char isns_server_addr_str[256]; 2661 int fd; 2662 int i; 2663 int isns_server_addr_list_size; 2664 int status; 2665 int out_cnt; 2666 iscsi_addr_list_t *ialp; 2667 /* LINTED */ 2668 IMA_IP_ADDRESS *ipAddr; 2669 2670 if ((status = open_driver(&fd))) { 2671 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2672 } 2673 2674 ialp = (iscsi_addr_list_t *)calloc(1, sizeof (iscsi_addr_list_t)); 2675 if (ialp == NULL) { 2676 (void) close(fd); 2677 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2678 } 2679 ialp->al_vers = ISCSI_INTERFACE_VERSION; 2680 ialp->al_in_cnt = ialp->al_out_cnt = 1; 2681 2682 /* 2683 * Issue ioctl to retrieve the isns server addresses. Space has been 2684 * allocted for one entry. If more than one entry should be returned, 2685 * we will re-issue the entry with the right amount of space allocted 2686 */ 2687 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_LIST_GET, ialp) != 0) { 2688 (void) close(fd); 2689 syslog(LOG_USER|LOG_DEBUG, 2690 "ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl failed, errno: %d", 2691 errno); 2692 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2693 } 2694 2695 isns_server_addr_list_size = sizeof (iscsi_addr_list_t); 2696 if (ialp->al_out_cnt > 1) { 2697 out_cnt = ialp->al_out_cnt; 2698 free(ialp); 2699 2700 isns_server_addr_list_size += (sizeof (iscsi_addr_t) * 2701 out_cnt - 1); 2702 ialp = (iscsi_addr_list_t *)calloc(1, 2703 isns_server_addr_list_size); 2704 if (ialp == NULL) { 2705 (void) close(fd); 2706 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2707 } 2708 ialp->al_vers = ISCSI_INTERFACE_VERSION; 2709 ialp->al_in_cnt = out_cnt; 2710 2711 /* 2712 * Issue ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl again to obtain 2713 * the list of all the iSNS server addresses 2714 */ 2715 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_LIST_GET, ialp) != 0) { 2716 free(ialp); 2717 (void) close(fd); 2718 syslog(LOG_USER|LOG_DEBUG, 2719 "ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl failed, " 2720 "errno: %d", errno); 2721 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2722 2723 } 2724 } 2725 2726 *ppList = (SUN_IMA_DISC_ADDR_PROP_LIST *)calloc(1, 2727 sizeof (SUN_IMA_DISC_ADDR_PROP_LIST) + 2728 ialp->al_out_cnt * sizeof (IMA_DISCOVERY_ADDRESS_PROPERTIES)); 2729 if (*ppList == NULL) { 2730 free(ialp); 2731 (void) close(fd); 2732 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2733 } 2734 (*ppList)->discAddrCount = ialp->al_out_cnt; 2735 2736 for (i = 0; i < ialp->al_out_cnt; i++) { 2737 if (ialp->al_addrs[i].a_addr.i_insize == 2738 sizeof (struct in_addr)) { 2739 (*ppList)->props[i].discoveryAddress.hostnameIpAddress. 2740 id.ipAddress.ipv4Address = IMA_TRUE; 2741 } else if (ialp->al_addrs[i].a_addr.i_insize == 2742 sizeof (struct in6_addr)) { 2743 (*ppList)->props[i].discoveryAddress.hostnameIpAddress. 2744 id.ipAddress.ipv4Address = IMA_FALSE; 2745 } else { 2746 (void) strlcpy(isns_server_addr_str, "unknown", 2747 sizeof (isns_server_addr_str)); 2748 } 2749 2750 ipAddr = &(*ppList)->props[i].discoveryAddress. 2751 hostnameIpAddress.id.ipAddress; 2752 bcopy(&ialp->al_addrs[i].a_addr.i_addr, 2753 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.id. 2754 ipAddress.ipAddress, 2755 sizeof (ipAddr->ipAddress)); 2756 (*ppList)->props[i].discoveryAddress.portNumber = 2757 ialp->al_addrs[i].a_port; 2758 } 2759 2760 free(ialp); 2761 (void) close(fd); 2762 return (IMA_STATUS_SUCCESS); 2763 } 2764 2765 /*ARGSUSED*/ 2766 /* 2767 * Remove iSNS Server Address 2768 */ 2769 IMA_API IMA_STATUS SUN_IMA_RemoveISNSServerAddress( 2770 SUN_IMA_TARGET_ADDRESS isnsServerAddress 2771 ) 2772 { 2773 entry_t entry; 2774 int fd, status; 2775 2776 if ((status = open_driver(&fd))) { 2777 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2778 } 2779 2780 if (prepare_discovery_entry(isnsServerAddress, &entry) != 2781 DISC_ADDR_OK) { 2782 (void) close(fd); 2783 return (IMA_ERROR_INVALID_PARAMETER); 2784 } 2785 2786 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_CLEAR, &entry)) { 2787 status = errno; 2788 (void) close(fd); 2789 syslog(LOG_USER|LOG_DEBUG, 2790 "ISCSI_ISNS_SERVER_ADDR_CLEAR ioctl failed, errno: %d", 2791 status); 2792 if (status == EBUSY) { 2793 return (IMA_ERROR_LU_IN_USE); 2794 } else { 2795 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2796 } 2797 } 2798 2799 (void) close(fd); 2800 return (IMA_STATUS_SUCCESS); 2801 } 2802 2803 /*ARGSUSED*/ 2804 IMA_API IMA_STATUS SUN_IMA_AddISNSServerAddress( 2805 const SUN_IMA_TARGET_ADDRESS isnsServerAddress 2806 ) 2807 { 2808 entry_t entry; 2809 int fd; 2810 int status; 2811 2812 if ((status = open_driver(&fd))) { 2813 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2814 } 2815 2816 if (prepare_discovery_entry(isnsServerAddress, &entry) != 2817 DISC_ADDR_OK) { 2818 (void) close(fd); 2819 return (IMA_ERROR_INVALID_PARAMETER); 2820 } 2821 2822 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_SET, &entry)) { 2823 /* 2824 * Encountered problem setting the discovery address. 2825 */ 2826 (void) close(fd); 2827 syslog(LOG_USER|LOG_DEBUG, 2828 "ISCSI_ISNS_SERVER_ADDR_SET ioctl failed, errno: %d", 2829 errno); 2830 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2831 } 2832 2833 (void) close(fd); 2834 return (IMA_STATUS_SUCCESS); 2835 } 2836 2837 IMA_STATUS SUN_IMA_RetrieveISNSServerTargets( 2838 IMA_TARGET_ADDRESS serverAddress, 2839 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList 2840 ) 2841 { 2842 int fd; 2843 int ctr; 2844 int server_pg_list_sz; 2845 int status; 2846 isns_server_portal_group_list_t *server_pg_list = NULL; 2847 isns_portal_group_list_t *pg_list = NULL; 2848 IMA_BOOL retry = IMA_TRUE; 2849 entry_t entry; 2850 2851 #define ISNS_SERVER_DEFAULT_NUM_TARGETS 50 2852 2853 server_pg_list_sz = sizeof (*server_pg_list) + 2854 ((ISNS_SERVER_DEFAULT_NUM_TARGETS - 1) * 2855 sizeof (isns_portal_group_t)); 2856 2857 server_pg_list = (isns_server_portal_group_list_t *)calloc(1, 2858 server_pg_list_sz); 2859 if (server_pg_list == NULL) { 2860 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2861 } 2862 server_pg_list->addr_port_list.pg_in_cnt = 2863 ISNS_SERVER_DEFAULT_NUM_TARGETS; 2864 2865 if ((prepare_discovery_entry_IMA(serverAddress, &entry) 2866 != DISC_ADDR_OK)) { 2867 free(server_pg_list); 2868 return (IMA_ERROR_INVALID_PARAMETER); 2869 } 2870 server_pg_list->addr.a_port = entry.e_port; 2871 server_pg_list->addr.a_addr.i_insize = entry.e_insize; 2872 if (entry.e_insize == sizeof (struct in_addr)) { 2873 server_pg_list->addr.a_addr.i_addr.in4.s_addr = 2874 (entry.e_u.u_in4.s_addr); 2875 } else if (entry.e_insize == sizeof (struct in6_addr)) { 2876 bcopy(&entry.e_u.u_in6.s6_addr, 2877 server_pg_list->addr.a_addr.i_addr.in6.s6_addr, 16); 2878 } 2879 2880 if ((status = open_driver(&fd))) { 2881 free(server_pg_list); 2882 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2883 } 2884 2885 retry_isns: 2886 /* 2887 * Issue ioctl to obtain the ISNS Portal Group List list 2888 */ 2889 if (ioctl(fd, ISCSI_ISNS_SERVER_GET, server_pg_list) != 0) { 2890 int tmp_errno = errno; 2891 IMA_STATUS return_status; 2892 2893 syslog(LOG_USER|LOG_DEBUG, 2894 "ISCSI_ISNS_SERVER_GET ioctl failed, errno: %d", tmp_errno); 2895 if (tmp_errno == EACCES) { 2896 return_status = IMA_ERROR_OBJECT_NOT_FOUND; 2897 } else { 2898 return_status = IMA_ERROR_UNEXPECTED_OS_ERROR; 2899 } 2900 (void) close(fd); 2901 free(server_pg_list); 2902 return (return_status); 2903 } 2904 pg_list = &server_pg_list->addr_port_list; 2905 2906 /* check if all targets received */ 2907 if (pg_list->pg_in_cnt < pg_list->pg_out_cnt) { 2908 if (retry == IMA_TRUE) { 2909 server_pg_list_sz = sizeof (*server_pg_list) + 2910 ((pg_list->pg_out_cnt - 1) * 2911 sizeof (isns_server_portal_group_list_t)); 2912 server_pg_list = (isns_server_portal_group_list_t *) 2913 realloc(server_pg_list, server_pg_list_sz); 2914 if (server_pg_list == NULL) { 2915 (void) close(fd); 2916 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2917 } 2918 pg_list = &server_pg_list->addr_port_list; 2919 pg_list->pg_in_cnt = pg_list->pg_out_cnt; 2920 retry = IMA_FALSE; 2921 goto retry_isns; 2922 } else { 2923 /* 2924 * don't retry after 2 attempts. The target list 2925 * shouldn't continue growing. Just continue 2926 * on and display what was found. 2927 */ 2928 syslog(LOG_USER|LOG_DEBUG, 2929 "ISCSI_SENDTGTS_GET overflow: " 2930 "failed to obtain all targets"); 2931 pg_list->pg_out_cnt = pg_list->pg_in_cnt; 2932 } 2933 } 2934 2935 (void) close(fd); 2936 2937 /* allocate for caller return buffer */ 2938 *ppList = (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *)calloc(1, 2939 sizeof (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES) + 2940 pg_list->pg_out_cnt * sizeof (SUN_IMA_DISC_ADDRESS_KEY)); 2941 if (*ppList == NULL) { 2942 free(server_pg_list); 2943 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2944 } 2945 2946 (*ppList)->keyCount = pg_list->pg_out_cnt; 2947 2948 for (ctr = 0; ctr < pg_list->pg_out_cnt; ctr++) { 2949 (void) mbstowcs((*ppList)->keys[ctr].name, 2950 (char *)pg_list->pg_list[ctr].pg_iscsi_name, 2951 IMA_NODE_NAME_LEN); 2952 2953 (*ppList)->keys[ctr].tpgt = pg_list->pg_list[ctr].pg_tag; 2954 2955 (*ppList)->keys[ctr].address.portNumber = 2956 pg_list->pg_list[ctr].pg_port; 2957 2958 if (pg_list->pg_list[ctr].insize == sizeof (struct in_addr)) { 2959 (*ppList)->keys[ctr].address.ipAddress.ipv4Address = 2960 IMA_TRUE; 2961 } else if (pg_list->pg_list[ctr].insize == 2962 sizeof (struct in6_addr)) { 2963 (*ppList)->keys[ctr].address.ipAddress.ipv4Address = 2964 IMA_FALSE; 2965 } else { 2966 free(pg_list); 2967 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2968 } 2969 2970 (void) memcpy(&(*ppList)->keys[ctr].address.ipAddress.ipAddress, 2971 &(pg_list->pg_list[ctr].pg_ip_addr), 2972 pg_list->pg_list[ctr].insize); 2973 } 2974 free(server_pg_list); 2975 2976 return (IMA_STATUS_SUCCESS); 2977 } 2978 2979 /* ARGSUSED */ 2980 IMA_STATUS SUN_IMA_GetSessionOidList( 2981 IMA_OID initiatorOid, 2982 IMA_OID_LIST **ppList 2983 ) 2984 { 2985 return (get_target_oid_list(ISCSI_TGT_OID_LIST, ppList)); 2986 } 2987 2988 /*ARGSUSED*/ 2989 IMA_API IMA_STATUS SUN_IMA_GetTargetAuthParms( 2990 IMA_OID oid, 2991 IMA_AUTHMETHOD method, 2992 IMA_INITIATOR_AUTHPARMS *pParms 2993 ) 2994 { 2995 int fd; 2996 iscsi_chap_props_t chap_p; 2997 2998 if (pParms == NULL) { 2999 return (IMA_ERROR_INVALID_PARAMETER); 3000 } 3001 3002 if (oid.objectType != IMA_OBJECT_TYPE_TARGET) { 3003 return (IMA_ERROR_INCORRECT_OBJECT_TYPE); 3004 } 3005 3006 if (method != IMA_AUTHMETHOD_CHAP) { 3007 return (IMA_ERROR_INVALID_PARAMETER); 3008 } 3009 3010 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3011 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)", 3012 ISCSI_DRIVER_DEVCTL, errno); 3013 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3014 } 3015 3016 (void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t)); 3017 chap_p.c_vers = ISCSI_INTERFACE_VERSION; 3018 chap_p.c_oid = (uint32_t)oid.objectSequenceNumber; 3019 3020 if (ioctl(fd, ISCSI_CHAP_GET, &chap_p) != 0) { 3021 syslog(LOG_USER|LOG_DEBUG, 3022 3023 "ISCSI_CHAP_GET ioctl failed, errno: %d", 3024 errno); 3025 (void) close(fd); 3026 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3027 } 3028 3029 (void) memcpy(pParms->chapParms.name, chap_p.c_user, 3030 chap_p.c_user_len); 3031 3032 pParms->chapParms.nameLength = chap_p.c_user_len; 3033 (void) memcpy(pParms->chapParms.challengeSecret, chap_p.c_secret, 3034 chap_p.c_secret_len); 3035 3036 pParms->chapParms.challengeSecretLength = chap_p.c_secret_len; 3037 3038 return (IMA_STATUS_SUCCESS); 3039 } 3040 3041 IMA_API IMA_STATUS SUN_IMA_GetBootTargetName( 3042 IMA_NODE_NAME tgtName 3043 ) 3044 { 3045 int fd; 3046 IMA_STATUS rtn; 3047 iscsi_boot_property_t bootProp; 3048 3049 bootProp.tgt_name.n_name[0] = '\0'; 3050 bootProp.tgt_chap.c_user[0] = '\0'; 3051 tgtName[0] = L'\0'; 3052 rtn = IMA_ERROR_UNEXPECTED_OS_ERROR; 3053 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3054 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3055 ISCSI_DRIVER_DEVCTL, errno); 3056 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3057 } 3058 3059 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3060 syslog(LOG_USER|LOG_DEBUG, 3061 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3062 errno); 3063 (void) close(fd); 3064 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3065 } 3066 3067 if ((bootProp.tgt_name.n_name[0] != '\0') && (tgtName != NULL)) { 3068 if (mbstowcs(tgtName, (const char *)bootProp.tgt_name.n_name, 3069 IMA_NODE_NAME_LEN) == (size_t)-1) { 3070 syslog(LOG_USER|LOG_DEBUG, 3071 "ISCSI Target name covert to WCHAR fail"); 3072 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3073 } else { 3074 rtn = IMA_STATUS_SUCCESS; 3075 } 3076 } 3077 3078 return (rtn); 3079 } 3080 3081 IMA_API IMA_STATUS SUN_IMA_GetBootTargetAuthParams( 3082 IMA_INITIATOR_AUTHPARMS *pTgtCHAP 3083 ) 3084 { 3085 int fd; 3086 IMA_STATUS rtn; 3087 iscsi_boot_property_t bootProp; 3088 3089 bootProp.tgt_name.n_name[0] = '\0'; 3090 bootProp.tgt_chap.c_user[0] = '\0'; 3091 bootProp.tgt_chap.c_secret[0] = '\0'; 3092 rtn = IMA_ERROR_UNEXPECTED_OS_ERROR; 3093 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3094 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3095 ISCSI_DRIVER_DEVCTL, errno); 3096 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3097 } 3098 3099 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3100 syslog(LOG_USER|LOG_DEBUG, 3101 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3102 errno); 3103 (void) close(fd); 3104 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3105 } 3106 3107 if (pTgtCHAP != NULL) { 3108 if (bootProp.tgt_chap.c_user[0] != '\0') { 3109 (void) memcpy(pTgtCHAP->chapParms.name, 3110 bootProp.tgt_chap.c_user, ISCSI_MAX_NAME_LEN); 3111 } else { 3112 pTgtCHAP->chapParms.name[0] = '\0'; 3113 } 3114 if (bootProp.tgt_chap.c_secret[0] != '\0') { 3115 (void) memcpy(pTgtCHAP->chapParms.challengeSecret, 3116 bootProp.tgt_chap.c_secret, MAX_CHAP_SECRET_LEN); 3117 } else { 3118 pTgtCHAP->chapParms.challengeSecret[0] = '\0'; 3119 } 3120 rtn = IMA_STATUS_SUCCESS; 3121 } 3122 return (rtn); 3123 } 3124 3125 IMA_STATUS SUN_IMA_GetBootMpxio( 3126 IMA_BOOL *pMpxioEnabled 3127 ) 3128 { 3129 int fd; 3130 iscsi_boot_property_t bootProp; 3131 3132 bootProp.hba_mpxio_enabled = B_FALSE; 3133 *pMpxioEnabled = IMA_UNKNOWN; 3134 3135 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3136 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3137 ISCSI_DRIVER_DEVCTL, errno); 3138 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3139 } 3140 3141 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3142 syslog(LOG_USER|LOG_DEBUG, 3143 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3144 errno); 3145 (void) close(fd); 3146 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3147 } 3148 3149 if (bootProp.hba_mpxio_enabled) { 3150 *pMpxioEnabled = IMA_TRUE; 3151 } else { 3152 *pMpxioEnabled = IMA_FALSE; 3153 } 3154 3155 (void) close(fd); 3156 return (IMA_STATUS_SUCCESS); 3157 } 3158 3159 IMA_STATUS SUN_IMA_GetBootIscsi( 3160 IMA_BOOL *pIscsiBoot 3161 ) 3162 { 3163 int fd; 3164 iscsi_boot_property_t bootProp; 3165 3166 bootProp.iscsiboot = 0; 3167 *pIscsiBoot = 0; 3168 3169 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3170 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3171 ISCSI_DRIVER_DEVCTL, errno); 3172 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3173 } 3174 3175 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3176 syslog(LOG_USER|LOG_DEBUG, 3177 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3178 errno); 3179 (void) close(fd); 3180 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3181 } 3182 3183 *pIscsiBoot = bootProp.iscsiboot; 3184 3185 (void) close(fd); 3186 return (IMA_STATUS_SUCCESS); 3187 } 3188 3189 IMA_STATUS SUN_IMA_GetSvcStatus( 3190 IMA_BOOL *pSvcEnabled) 3191 { 3192 int fd; 3193 uint32_t status = ISCSI_SERVICE_DISABLED; 3194 3195 if (pSvcEnabled == NULL) 3196 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3197 *pSvcEnabled = 0; 3198 3199 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3200 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3201 ISCSI_DRIVER_DEVCTL, errno); 3202 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3203 } 3204 3205 if (ioctl(fd, ISCSI_SMF_GET, &status) != 0) { 3206 syslog(LOG_USER|LOG_DEBUG, 3207 "ISCSI_SVC_GET ioctl failed, errno: %d", 3208 errno); 3209 (void) close(fd); 3210 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3211 } 3212 3213 if (status == ISCSI_SERVICE_ENABLED) { 3214 *pSvcEnabled = 1; 3215 } 3216 3217 (void) close(fd); 3218 return (IMA_STATUS_SUCCESS); 3219 } 3220