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