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 2008 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 *osDeviceName); 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 /* Issue ISCSI_AUTH_CLEAR ioctl */ 1076 (void) memset(&auth_p, 0, sizeof (iscsi_auth_props_t)); 1077 auth_p.a_vers = ISCSI_INTERFACE_VERSION; 1078 auth_p.a_oid = (uint32_t)targetOid.objectSequenceNumber; 1079 if (ioctl(fd, ISCSI_AUTH_CLEAR, &auth_p) != 0) { 1080 /* 1081 * It could be that the auth data of this target has 1082 * never been set. 1083 */ 1084 syslog(LOG_USER|LOG_DEBUG, 1085 "ISCSI_AUTH_CLEAR ioctl failed, errno: %d", errno); 1086 } 1087 1088 (void) close(fd); 1089 return (IMA_STATUS_SUCCESS); 1090 } 1091 1092 IMA_API IMA_STATUS SUN_IMA_SetHeaderDigest( 1093 IMA_OID oid, 1094 IMA_UINT algorithmCount, 1095 const SUN_IMA_DIGEST_ALGORITHM *algorithmList 1096 ) 1097 { 1098 IMA_MIN_MAX_VALUE mv; 1099 uint32_t digest_algorithm; 1100 1101 /* We only support one preference of digest algorithm. */ 1102 if (algorithmCount > 1) { 1103 syslog(LOG_USER|LOG_DEBUG, 1104 "More than one digest algorithm specified."); 1105 return (IMA_ERROR_NOT_SUPPORTED); 1106 } 1107 switch (algorithmList[0]) { 1108 case SUN_IMA_DIGEST_NONE: 1109 digest_algorithm = ISCSI_DIGEST_NONE; 1110 break; 1111 case SUN_IMA_DIGEST_CRC32: 1112 digest_algorithm = ISCSI_DIGEST_CRC32C; 1113 break; 1114 default: 1115 digest_algorithm = ISCSI_DIGEST_NONE; 1116 break; 1117 } 1118 mv.currentValue = digest_algorithm; 1119 return (setISCSINodeParameter(MIN_MAX_PARAM, &oid, &mv, 1120 ISCSI_LOGIN_PARAM_HEADER_DIGEST)); 1121 } 1122 1123 IMA_API IMA_STATUS SUN_IMA_SetDataDigest( 1124 IMA_OID oid, 1125 IMA_UINT algorithmCount, 1126 const SUN_IMA_DIGEST_ALGORITHM *algorithmList 1127 ) 1128 { 1129 IMA_MIN_MAX_VALUE mv; 1130 uint32_t digest_algorithm; 1131 1132 /* We only support one preference of digest algorithm. */ 1133 if (algorithmCount > 1) { 1134 syslog(LOG_USER|LOG_DEBUG, 1135 "More than one digest algorithm specified."); 1136 return (IMA_ERROR_NOT_SUPPORTED); 1137 } 1138 switch (algorithmList[0]) { 1139 case SUN_IMA_DIGEST_NONE: 1140 digest_algorithm = ISCSI_DIGEST_NONE; 1141 break; 1142 case SUN_IMA_DIGEST_CRC32: 1143 digest_algorithm = ISCSI_DIGEST_CRC32C; 1144 break; 1145 default: 1146 digest_algorithm = ISCSI_DIGEST_NONE; 1147 break; 1148 } 1149 mv.currentValue = digest_algorithm; 1150 return (setISCSINodeParameter(MIN_MAX_PARAM, &oid, &mv, 1151 ISCSI_LOGIN_PARAM_DATA_DIGEST)); 1152 } 1153 1154 IMA_API IMA_STATUS SUN_IMA_GetHeaderDigest( 1155 IMA_OID oid, 1156 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm 1157 ) 1158 { 1159 return (getDigest(oid, ISCSI_LOGIN_PARAM_HEADER_DIGEST, algorithm)); 1160 } 1161 1162 IMA_API IMA_STATUS SUN_IMA_GetDataDigest( 1163 IMA_OID oid, 1164 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm 1165 ) 1166 { 1167 return (getDigest(oid, ISCSI_LOGIN_PARAM_DATA_DIGEST, algorithm)); 1168 } 1169 1170 IMA_STATUS SUN_IMA_GetLuProperties( 1171 IMA_OID luId, 1172 SUN_IMA_LU_PROPERTIES *pProps 1173 ) 1174 { 1175 IMA_STATUS status; 1176 iscsi_lun_list_t *pLunList; 1177 int j; 1178 IMA_BOOL lunMatch = IMA_FALSE; 1179 int fd; 1180 int openStatus; 1181 iscsi_lun_props_t lun; 1182 di_devlink_handle_t hdl; 1183 1184 if (luId.objectType != IMA_OBJECT_TYPE_LU) { 1185 return (IMA_ERROR_INCORRECT_OBJECT_TYPE); 1186 } 1187 1188 /* 1189 * get list of lun oids for all targets 1190 */ 1191 status = get_target_lun_oid_list(NULL, &pLunList); 1192 if (!IMA_SUCCESS(status)) { 1193 return (status); 1194 } 1195 for (j = 0; j < pLunList->ll_out_cnt; j++) { 1196 /* 1197 * for each lun, check if match is found 1198 */ 1199 if (pLunList->ll_luns[j].l_oid == luId.objectSequenceNumber) { 1200 /* 1201 * match found, break out of lun loop 1202 */ 1203 lunMatch = IMA_TRUE; 1204 break; 1205 } 1206 } 1207 1208 if (lunMatch == IMA_TRUE) { 1209 (void) memset(&lun, 0, sizeof (iscsi_lun_props_t)); 1210 lun.lp_vers = ISCSI_INTERFACE_VERSION; 1211 lun.lp_tgt_oid = pLunList->ll_luns[j].l_tgt_oid; 1212 lun.lp_oid = pLunList->ll_luns[j].l_oid; 1213 } 1214 1215 free(pLunList); 1216 1217 if (lunMatch == IMA_FALSE) { 1218 return (IMA_ERROR_OBJECT_NOT_FOUND); 1219 } 1220 1221 /* 1222 * get lun properties 1223 */ 1224 if ((openStatus = open_driver(&fd))) { 1225 return (SUN_IMA_ERROR_SYSTEM_ERROR | openStatus); 1226 } 1227 1228 if (ioctl(fd, ISCSI_LUN_PROPS_GET, &lun)) { 1229 syslog(LOG_USER|LOG_DEBUG, 1230 "ISCSI_LUN_PROPS_GET ioctl failed, errno: %d", errno); 1231 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1232 } 1233 1234 (void) close(fd); 1235 1236 /* 1237 * set property values 1238 */ 1239 pProps->imaProps.associatedTargetOid.objectType = 1240 IMA_OBJECT_TYPE_TARGET; 1241 pProps->imaProps.associatedTargetOid.ownerId = 1; 1242 pProps->imaProps.associatedTargetOid.objectSequenceNumber = lun.lp_oid; 1243 pProps->imaProps.targetLun = (IMA_UINT64)lun.lp_num; 1244 (void) strncpy(pProps->vendorId, lun.lp_vid, SUN_IMA_LU_VENDOR_ID_LEN); 1245 (void) strncpy(pProps->productId, lun.lp_pid, 1246 SUN_IMA_LU_PRODUCT_ID_LEN); 1247 /* 1248 * lun.lp_status is defined as 1249 * LunValid = 0 1250 * LunDoesNotExist = 1 1251 * IMA_LU_PROPS.exposedtoOS is defined as an IMA_BOOL 1252 * IMA_TRUE = 1 1253 * IMA_FALSE = 0 1254 */ 1255 pProps->imaProps.exposedToOs = !lun.lp_status; 1256 if (gmtime_r(&lun.lp_time_online, &pProps->imaProps.timeExposedToOs) 1257 == NULL) { 1258 (void) memset(&pProps->imaProps.timeExposedToOs, 0, 1259 sizeof (pProps->imaProps.timeExposedToOs)); 1260 } 1261 1262 if (lun.lp_status == LunValid) { 1263 1264 /* add minor device delimiter */ 1265 (void) strcat(lun.lp_pathname, ":"); 1266 1267 if ((strstr(lun.lp_pathname, "sd@") != NULL) || 1268 (strstr(lun.lp_pathname, "ssd@") != NULL) || 1269 (strstr(lun.lp_pathname, "disk@") != NULL)) { 1270 /* 1271 * modify returned pathname to obtain the 2nd slice 1272 * of the raw disk 1273 */ 1274 (void) strcat(lun.lp_pathname, "c,raw"); 1275 } 1276 1277 /* 1278 * Pathname returned by driver is the physical device path. 1279 * This name needs to be converted to the OS device name. 1280 */ 1281 if (hdl = di_devlink_init(lun.lp_pathname, DI_MAKE_LINK)) { 1282 pProps->imaProps.osDeviceName[0] = L'\0'; 1283 (void) di_devlink_walk(hdl, NULL, lun.lp_pathname, 1284 DI_PRIMARY_LINK, 1285 (void *)pProps->imaProps.osDeviceName, 1286 get_lun_devlink); 1287 if (pProps->imaProps.osDeviceName[0] != L'\0') { 1288 /* OS device name synchronously made */ 1289 pProps->imaProps.osDeviceNameValid = IMA_TRUE; 1290 } else { 1291 pProps->imaProps.osDeviceNameValid = IMA_FALSE; 1292 } 1293 1294 (void) di_devlink_fini(&hdl); 1295 1296 } else { 1297 pProps->imaProps.osDeviceNameValid = IMA_FALSE; 1298 } 1299 1300 } else { 1301 pProps->imaProps.osDeviceNameValid = IMA_FALSE; 1302 } 1303 1304 pProps->imaProps.osParallelIdsValid = IMA_FALSE; 1305 1306 return (IMA_STATUS_SUCCESS); 1307 } 1308 1309 #define IMA_DISK_DEVICE_NAME_PREFIX "/dev/rdsk/" 1310 #define IMA_TAPE_DEVICE_NAME_PREFIX "/dev/rmt/" 1311 1312 static int 1313 get_lun_devlink(di_devlink_t link, void *osDeviceName) 1314 { 1315 if ((strncmp(IMA_DISK_DEVICE_NAME_PREFIX, di_devlink_path(link), 1316 strlen(IMA_DISK_DEVICE_NAME_PREFIX)) == 0) || 1317 (strncmp(IMA_TAPE_DEVICE_NAME_PREFIX, di_devlink_path(link), 1318 strlen(IMA_TAPE_DEVICE_NAME_PREFIX)) == 0)) { 1319 (void) mbstowcs((wchar_t *)osDeviceName, di_devlink_path(link), 1320 MAXPATHLEN); 1321 return (DI_WALK_TERMINATE); 1322 } 1323 1324 return (DI_WALK_CONTINUE); 1325 } 1326 1327 /* 1328 * SUN_IMA_GetConnectionOidList - 1329 * 1330 * Non-IMA defined function. 1331 */ 1332 IMA_API IMA_STATUS SUN_IMA_GetConnOidList( 1333 IMA_OID *oid, 1334 IMA_OID_LIST **ppList 1335 ) 1336 { 1337 IMA_STATUS imaStatus; 1338 IMA_OID_LIST *imaOidList; 1339 iscsi_conn_list_t *iscsiConnList = NULL; 1340 int i; 1341 size_t allocLen; 1342 1343 if ((lhbaObjectId.objectType == oid->objectType) && 1344 (lhbaObjectId.ownerId == oid->ownerId) && 1345 (lhbaObjectId.objectSequenceNumber == oid->objectSequenceNumber)) { 1346 imaStatus = getConnOidList(NULL, &iscsiConnList); 1347 } else { 1348 if (oid->objectType == IMA_OBJECT_TYPE_TARGET) { 1349 imaStatus = getConnOidList(oid, &iscsiConnList); 1350 } else { 1351 return (IMA_ERROR_INCORRECT_OBJECT_TYPE); 1352 } 1353 } 1354 if (imaStatus != IMA_STATUS_SUCCESS) { 1355 return (imaStatus); 1356 } 1357 1358 /* 1359 * Based on the results a SUN_IMA_CONN_LIST structure is allocated. 1360 */ 1361 allocLen = iscsiConnList->cl_out_cnt * sizeof (IMA_OID); 1362 allocLen += sizeof (IMA_OID_LIST) - sizeof (IMA_OID); 1363 imaOidList = (IMA_OID_LIST *)calloc(1, allocLen); 1364 1365 if (imaOidList == NULL) { 1366 free(iscsiConnList); 1367 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1368 } 1369 1370 /* The data is transfered from iscsiConnList to imaConnList. */ 1371 imaOidList->oidCount = iscsiConnList->cl_out_cnt; 1372 for (i = 0; i < iscsiConnList->cl_out_cnt; i++) { 1373 imaOidList->oids[i].objectType = SUN_IMA_OBJECT_TYPE_CONN; 1374 imaOidList->oids[i].ownerId = 1; 1375 imaOidList->oids[i].objectSequenceNumber = 1376 iscsiConnList->cl_list[i].c_oid; 1377 } 1378 /* The pointer to the SUN_IMA_CONN_LIST structure is returned. */ 1379 *ppList = imaOidList; 1380 1381 free(iscsiConnList); 1382 return (IMA_STATUS_SUCCESS); 1383 } 1384 1385 /* 1386 * SUN_IMA_GetConnProperties - 1387 * 1388 * Non-IMA defined function. 1389 */ 1390 IMA_API IMA_STATUS SUN_IMA_GetConnProperties( 1391 IMA_OID *connOid, 1392 SUN_IMA_CONN_PROPERTIES **pProps 1393 ) 1394 { 1395 iscsi_conn_list_t *pConnList; 1396 iscsi_conn_props_t *pConnProps; 1397 /* LINTED */ 1398 struct sockaddr_in6 *addrIn6; 1399 /* LINTED */ 1400 struct sockaddr_in *addrIn; 1401 SUN_IMA_CONN_PROPERTIES *pImaConnProps; 1402 IMA_STATUS imaStatus; 1403 int i; 1404 1405 /* If there is any error *pProps should be set to NULL */ 1406 *pProps = NULL; 1407 1408 pImaConnProps = (SUN_IMA_CONN_PROPERTIES *)calloc(1, 1409 sizeof (SUN_IMA_CONN_PROPERTIES)); 1410 1411 if (pImaConnProps == NULL) { 1412 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1413 } 1414 1415 imaStatus = getConnOidList(NULL, &pConnList); 1416 1417 if (imaStatus != IMA_STATUS_SUCCESS) { 1418 free(pImaConnProps); 1419 return (imaStatus); 1420 } 1421 1422 /* 1423 * Walk the list returned to find our connection. 1424 */ 1425 for (i = 0; i < pConnList->cl_out_cnt; i++) { 1426 1427 if (pConnList->cl_list[i].c_oid == 1428 (uint32_t)connOid->objectSequenceNumber) { 1429 1430 /* This is our connection. */ 1431 imaStatus = getConnProps(&pConnList->cl_list[i], 1432 &pConnProps); 1433 1434 if (imaStatus != IMA_STATUS_SUCCESS) { 1435 free(pConnList); 1436 free(pImaConnProps); 1437 return (imaStatus); 1438 } 1439 pImaConnProps->connectionID = pConnProps->cp_cid; 1440 1441 /* 1442 * Local Propeties 1443 */ 1444 if (pConnProps->cp_local.soa4.sin_family == AF_INET) { 1445 1446 pImaConnProps->local.ipAddress.ipv4Address = 1447 IMA_TRUE; 1448 pImaConnProps->local.portNumber = 1449 pConnProps->cp_local.soa4.sin_port; 1450 addrIn = &(pConnProps->cp_local.soa4); 1451 bcopy(&pConnProps->cp_local.soa4.sin_addr, 1452 pImaConnProps->local.ipAddress.ipAddress, 1453 sizeof (addrIn->sin_addr)); 1454 1455 } else { 1456 pImaConnProps->local.ipAddress.ipv4Address = 1457 IMA_FALSE; 1458 pImaConnProps->local.portNumber = 1459 pConnProps->cp_local.soa6.sin6_port; 1460 addrIn6 = &(pConnProps->cp_local.soa6); 1461 bcopy(&pConnProps->cp_local.soa6.sin6_addr, 1462 pImaConnProps->local.ipAddress.ipAddress, 1463 sizeof (addrIn6->sin6_addr)); 1464 1465 } 1466 1467 /* 1468 * Peer Propeties 1469 */ 1470 if (pConnProps->cp_peer.soa4.sin_family == AF_INET) { 1471 1472 pImaConnProps->peer.ipAddress.ipv4Address = 1473 IMA_TRUE; 1474 pImaConnProps->peer.portNumber = 1475 pConnProps->cp_peer.soa4.sin_port; 1476 addrIn = &(pConnProps->cp_local.soa4); 1477 bcopy(&pConnProps->cp_peer.soa4.sin_addr, 1478 pImaConnProps->peer.ipAddress.ipAddress, 1479 sizeof (addrIn->sin_addr)); 1480 1481 } else { 1482 pImaConnProps->peer.ipAddress.ipv4Address = 1483 IMA_FALSE; 1484 pImaConnProps->peer.portNumber = 1485 pConnProps->cp_peer.soa6.sin6_port; 1486 1487 addrIn6 = &pConnProps->cp_local.soa6; 1488 bcopy(&pConnProps->cp_peer.soa6.sin6_addr, 1489 pImaConnProps->peer.ipAddress.ipAddress, 1490 sizeof (addrIn6->sin6_addr)); 1491 } 1492 1493 1494 pImaConnProps->valuesValid = 1495 pConnProps->cp_params_valid; 1496 pImaConnProps->defaultTime2Retain = 1497 pConnProps->cp_params.default_time_to_retain; 1498 pImaConnProps->defaultTime2Wait = 1499 pConnProps->cp_params.default_time_to_wait; 1500 pImaConnProps->errorRecoveryLevel = 1501 pConnProps->cp_params.error_recovery_level; 1502 pImaConnProps->firstBurstLength = 1503 pConnProps->cp_params.first_burst_length; 1504 pImaConnProps->maxBurstLength = 1505 pConnProps->cp_params.max_burst_length; 1506 pImaConnProps->maxConnections = 1507 pConnProps->cp_params.max_connections; 1508 pImaConnProps->maxOutstandingR2T = 1509 pConnProps->cp_params.max_outstanding_r2t; 1510 pImaConnProps->maxRecvDataSegmentLength = 1511 pConnProps->cp_params.max_recv_data_seg_len; 1512 1513 pImaConnProps->dataPduInOrder = 1514 pConnProps->cp_params.data_pdu_in_order; 1515 pImaConnProps->dataSequenceInOrder = 1516 pConnProps->cp_params.data_sequence_in_order; 1517 pImaConnProps->immediateData = 1518 pConnProps->cp_params.immediate_data; 1519 pImaConnProps->initialR2T = 1520 pConnProps->cp_params.initial_r2t; 1521 1522 pImaConnProps->headerDigest = 1523 pConnProps->cp_params.header_digest; 1524 pImaConnProps->dataDigest = 1525 pConnProps->cp_params.data_digest; 1526 1527 free(pConnProps); 1528 break; 1529 } 1530 } 1531 free(pConnList); 1532 *pProps = pImaConnProps; 1533 return (IMA_STATUS_SUCCESS); 1534 } 1535 1536 1537 /* 1538 * SUN_IMA_GetConfigSessions - 1539 * 1540 * Non-IMA defined function. 1541 */ 1542 IMA_API IMA_STATUS SUN_IMA_GetConfigSessions( 1543 IMA_OID targetOid, 1544 SUN_IMA_CONFIG_SESSIONS **pConfigSessions 1545 ) 1546 { 1547 int fd; 1548 int status; 1549 iscsi_config_sess_t *ics; 1550 int size, idx; 1551 1552 /* Allocate and setup initial buffer */ 1553 size = sizeof (*ics); 1554 ics = (iscsi_config_sess_t *)calloc(1, size); 1555 if (ics == NULL) { 1556 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1557 } 1558 ics->ics_ver = ISCSI_INTERFACE_VERSION; 1559 ics->ics_oid = targetOid.objectSequenceNumber; 1560 ics->ics_in = 1; 1561 1562 /* Open driver devctl for ioctl */ 1563 if ((status = open_driver(&fd))) { 1564 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1565 } 1566 1567 /* Issue ioctl request */ 1568 if (ioctl(fd, ISCSI_GET_CONFIG_SESSIONS, ics) != 0) { 1569 syslog(LOG_USER|LOG_DEBUG, 1570 "ISCSI_GET_CONFIG_SESSIONS ioctl failed, errno: %d", 1571 errno); 1572 (void) close(fd); 1573 free(ics); 1574 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1575 } 1576 1577 /* Check if we need to collect more information */ 1578 idx = ics->ics_out; 1579 if (idx > 1) { 1580 1581 /* Free old buffer and reallocate re-sized buffer */ 1582 free(ics); 1583 size = ISCSI_SESSION_CONFIG_SIZE(idx); 1584 ics = (iscsi_config_sess_t *)calloc(1, size); 1585 if (ics == NULL) { 1586 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1587 } 1588 ics->ics_ver = ISCSI_INTERFACE_VERSION; 1589 ics->ics_oid = targetOid.objectSequenceNumber; 1590 ics->ics_in = idx; 1591 1592 /* Issue ioctl request */ 1593 if (ioctl(fd, ISCSI_GET_CONFIG_SESSIONS, ics) != 0) { 1594 syslog(LOG_USER|LOG_DEBUG, 1595 "ISCSI_GET_CONFIG_SESSIONS ioctl failed, errno: %d", 1596 errno); 1597 (void) close(fd); 1598 free(ics); 1599 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1600 } 1601 } 1602 (void) close(fd); 1603 1604 /* Allocate output buffer */ 1605 size = sizeof (SUN_IMA_CONFIG_SESSIONS) + 1606 ((ics->ics_out - 1) * sizeof (IMA_ADDRESS_KEY)); 1607 *pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 1608 if ((*pConfigSessions) == NULL) { 1609 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1610 } 1611 1612 /* Copy output information */ 1613 (*pConfigSessions)->bound = 1614 (ics->ics_bound == B_TRUE ? IMA_TRUE : IMA_FALSE); 1615 (*pConfigSessions)->in = ics->ics_in; 1616 (*pConfigSessions)->out = ics->ics_out; 1617 for (idx = 0; idx < ics->ics_in; idx++) { 1618 if (ics->ics_bindings[idx].i_insize == 1619 sizeof (struct in_addr)) { 1620 (*pConfigSessions)->bindings[idx].ipAddress. 1621 ipv4Address = IMA_TRUE; 1622 bcopy(&ics->ics_bindings[idx].i_addr.in4, 1623 (*pConfigSessions)->bindings[idx].ipAddress. 1624 ipAddress, sizeof (struct in_addr)); 1625 } else { 1626 (*pConfigSessions)->bindings[idx].ipAddress. 1627 ipv4Address = IMA_FALSE; 1628 bcopy(&ics->ics_bindings[idx].i_addr.in6, 1629 (*pConfigSessions)->bindings[idx].ipAddress. 1630 ipAddress, sizeof (struct in6_addr)); 1631 } 1632 } 1633 1634 free(ics); 1635 return (IMA_STATUS_SUCCESS); 1636 } 1637 1638 /* 1639 * SUN_IMA_SetConfigSessions - 1640 * 1641 * Non-IMA defined function. 1642 */ 1643 IMA_API IMA_STATUS SUN_IMA_SetConfigSessions( 1644 IMA_OID targetOid, 1645 SUN_IMA_CONFIG_SESSIONS *pConfigSessions 1646 ) 1647 { 1648 int fd; 1649 int status; 1650 iscsi_config_sess_t *ics; 1651 int idx, size; 1652 1653 /* verify allowed range of sessions */ 1654 if ((pConfigSessions->in < ISCSI_MIN_CONFIG_SESSIONS) || 1655 (pConfigSessions->in > ISCSI_MAX_CONFIG_SESSIONS)) { 1656 return (IMA_ERROR_INVALID_PARAMETER); 1657 } 1658 1659 /* allocate record config_sess size */ 1660 size = ISCSI_SESSION_CONFIG_SIZE(pConfigSessions->in); 1661 ics = (iscsi_config_sess_t *)malloc(size); 1662 1663 /* setup config_sess information */ 1664 (void) memset(ics, 0, sizeof (iscsi_config_sess_t)); 1665 ics->ics_ver = ISCSI_INTERFACE_VERSION; 1666 ics->ics_oid = targetOid.objectSequenceNumber; 1667 ics->ics_bound = 1668 (pConfigSessions->bound == IMA_TRUE ? B_TRUE : B_FALSE); 1669 ics->ics_in = pConfigSessions->in; 1670 for (idx = 0; idx < ics->ics_in; idx++) { 1671 if (pConfigSessions->bindings[idx].ipAddress. 1672 ipv4Address == IMA_TRUE) { 1673 ics->ics_bindings[idx].i_insize = 1674 sizeof (struct in_addr); 1675 bcopy(pConfigSessions->bindings[idx]. 1676 ipAddress.ipAddress, 1677 &ics->ics_bindings[idx].i_addr.in4, 1678 sizeof (struct in_addr)); 1679 } else { 1680 ics->ics_bindings[idx].i_insize = 1681 sizeof (struct in6_addr); 1682 bcopy(pConfigSessions->bindings[idx]. 1683 ipAddress.ipAddress, 1684 &ics->ics_bindings[idx].i_addr.in6, 1685 sizeof (struct in6_addr)); 1686 } 1687 } 1688 1689 /* open driver */ 1690 if ((status = open_driver(&fd))) { 1691 free(ics); 1692 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1693 } 1694 1695 /* issue ioctl request */ 1696 if (ioctl(fd, ISCSI_SET_CONFIG_SESSIONS, ics) != 0) { 1697 syslog(LOG_USER|LOG_DEBUG, 1698 "ISCSI_SET_CONFIG_SESSIONS ioctl failed, errno: %d", 1699 errno); 1700 (void) close(fd); 1701 free(ics); 1702 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1703 } 1704 (void) close(fd); 1705 free(ics); 1706 return (IMA_STATUS_SUCCESS); 1707 } 1708 1709 /* A helper function to obtain iSCSI node parameters. */ 1710 static IMA_STATUS 1711 getISCSINodeParameter( 1712 int paramType, 1713 IMA_OID *oid, 1714 void *pProps, 1715 uint32_t paramIndex 1716 ) 1717 { 1718 int fd; 1719 int status; 1720 iscsi_param_get_t pg; 1721 1722 if ((status = open_driver(&fd))) { 1723 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1724 } 1725 1726 (void) memset(&pg, 0, sizeof (iscsi_param_get_t)); 1727 pg.g_vers = ISCSI_INTERFACE_VERSION; 1728 pg.g_oid = (uint32_t)oid->objectSequenceNumber; 1729 pg.g_param = paramIndex; 1730 pg.g_param_type = ISCSI_SESS_PARAM; 1731 1732 if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) { 1733 syslog(LOG_USER|LOG_DEBUG, 1734 "ISCSI_PARAM_GET ioctl failed, errno: %d", errno); 1735 (void) close(fd); 1736 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1737 } 1738 1739 switch (paramType) { 1740 IMA_BOOL_VALUE *bp; 1741 IMA_MIN_MAX_VALUE *mp; 1742 1743 case MIN_MAX_PARAM: 1744 mp = (IMA_MIN_MAX_VALUE *)pProps; 1745 1746 mp->currentValueValid = 1747 (pg.g_value.v_valid == B_TRUE) ? 1748 IMA_TRUE : IMA_FALSE; 1749 mp->currentValue = pg.g_value.v_integer.i_current; 1750 mp->defaultValue = pg.g_value.v_integer.i_default; 1751 mp->minimumValue = pg.g_value.v_integer.i_min; 1752 mp->maximumValue = pg.g_value.v_integer.i_max; 1753 mp->incrementValue = pg.g_value.v_integer.i_incr; 1754 break; 1755 1756 case BOOL_PARAM: 1757 bp = (IMA_BOOL_VALUE *)pProps; 1758 bp->currentValueValid = 1759 (pg.g_value.v_valid == B_TRUE) ? 1760 IMA_TRUE : IMA_FALSE; 1761 bp->currentValue = pg.g_value.v_bool.b_current; 1762 bp->defaultValue = pg.g_value.v_bool.b_default; 1763 break; 1764 1765 default: 1766 break; 1767 } 1768 1769 /* Issue ISCSI_PARAM_GET ioctl again to obtain connection parameters. */ 1770 pg.g_param_type = ISCSI_CONN_PARAM; 1771 if (ioctl(fd, ISCSI_PARAM_GET, &pg) != 0) { 1772 syslog(LOG_USER|LOG_DEBUG, 1773 "ISCSI_PARAM_GET ioctl failed, errno: %d", errno); 1774 (void) close(fd); 1775 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1776 } 1777 1778 (void) close(fd); 1779 return (IMA_STATUS_SUCCESS); 1780 } 1781 1782 /* A helper function to set iSCSI node parameters. */ 1783 static IMA_STATUS 1784 setISCSINodeParameter( 1785 int paramType, 1786 IMA_OID *oid, 1787 void *pProp, 1788 uint32_t paramIndex 1789 ) 1790 { 1791 int fd; 1792 int status; 1793 iscsi_param_set_t ps; 1794 1795 if ((status = open_driver(&fd))) { 1796 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1797 } 1798 1799 (void) memset(&ps, 0, sizeof (iscsi_param_set_t)); 1800 ps.s_vers = ISCSI_INTERFACE_VERSION; 1801 ps.s_oid = (uint32_t)oid->objectSequenceNumber; 1802 ps.s_param = paramIndex; 1803 1804 switch (paramType) { 1805 IMA_BOOL_VALUE *bp; 1806 IMA_MIN_MAX_VALUE *mp; 1807 1808 case MIN_MAX_PARAM: 1809 mp = (IMA_MIN_MAX_VALUE *)pProp; 1810 ps.s_value.v_integer = mp->currentValue; 1811 break; 1812 case BOOL_PARAM: 1813 bp = (IMA_BOOL_VALUE *)pProp; 1814 ps.s_value.v_bool = 1815 (bp->currentValue == IMA_TRUE) ? 1816 B_TRUE : B_FALSE; 1817 break; 1818 1819 default: 1820 break; 1821 } 1822 if (ioctl(fd, ISCSI_PARAM_SET, &ps)) { 1823 (void) close(fd); 1824 syslog(LOG_USER|LOG_DEBUG, 1825 "ISCSI_PARAM_SET ioctl failed, errno: %d", errno); 1826 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1827 } 1828 1829 (void) close(fd); 1830 return (IMA_STATUS_SUCCESS); 1831 } 1832 1833 static int 1834 prepare_discovery_entry( 1835 SUN_IMA_TARGET_ADDRESS discoveryAddress, 1836 entry_t *entry 1837 ) 1838 { 1839 return (prepare_discovery_entry_IMA(discoveryAddress.imaStruct, entry)); 1840 } 1841 1842 static int 1843 prepare_discovery_entry_IMA( 1844 IMA_TARGET_ADDRESS discoveryAddress, 1845 entry_t *entry 1846 ) 1847 { 1848 (void) memset(entry, 0, sizeof (entry_t)); 1849 entry->e_vers = ISCSI_INTERFACE_VERSION; 1850 entry->e_oid = ISCSI_OID_NOTSET; 1851 1852 if (discoveryAddress.hostnameIpAddress.id.ipAddress. 1853 ipv4Address == IMA_FALSE) { 1854 1855 bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress. 1856 ipAddress, entry->e_u.u_in6.s6_addr, 1857 sizeof (entry->e_u.u_in6.s6_addr)); 1858 1859 entry->e_insize = sizeof (struct in6_addr); 1860 } else { 1861 1862 bcopy(discoveryAddress.hostnameIpAddress.id.ipAddress. 1863 ipAddress, &entry->e_u.u_in4.s_addr, 1864 sizeof (entry->e_u.u_in4.s_addr)); 1865 1866 entry->e_insize = sizeof (struct in_addr); 1867 } 1868 1869 entry->e_port = discoveryAddress.portNumber; 1870 entry->e_tpgt = 0; 1871 return (DISC_ADDR_OK); 1872 } 1873 1874 static IMA_STATUS configure_discovery_method( 1875 IMA_BOOL enable, 1876 iSCSIDiscoveryMethod_t method 1877 ) 1878 { 1879 int fd, status; 1880 1881 if ((status = open_driver(&fd))) { 1882 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1883 } 1884 1885 if (enable == IMA_FALSE) { 1886 if (ioctl(fd, ISCSI_DISCOVERY_CLEAR, &method)) { 1887 status = errno; 1888 (void) close(fd); 1889 syslog(LOG_USER|LOG_DEBUG, 1890 "ISCSI_DISCOVERY_CLEAR ioctl failed, errno: %d", 1891 status); 1892 if (status == EBUSY) { 1893 return (IMA_ERROR_LU_IN_USE); 1894 } else { 1895 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1896 } 1897 } 1898 1899 (void) close(fd); 1900 return (IMA_STATUS_SUCCESS); 1901 } else { 1902 /* Set the discovery method */ 1903 if (ioctl(fd, ISCSI_DISCOVERY_SET, &method)) { 1904 status = errno; 1905 (void) close(fd); 1906 syslog(LOG_USER|LOG_DEBUG, 1907 "ISCSI_DISCOVERY_SET ioctl failed, errno: %d", 1908 status); 1909 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1910 } 1911 1912 (void) close(fd); 1913 return (IMA_STATUS_SUCCESS); 1914 } 1915 } 1916 1917 /* LINTED E_STATIC_UNUSED */ 1918 static IMA_BOOL authMethodMatch( 1919 IMA_AUTHMETHOD matchingMethod, 1920 IMA_AUTHMETHOD *methodList, 1921 IMA_UINT maxEntries 1922 ) 1923 { 1924 IMA_UINT i; 1925 1926 for (i = 0; i < maxEntries; i++) { 1927 if (methodList[i] == matchingMethod) { 1928 return (IMA_TRUE); 1929 } 1930 } 1931 1932 return (IMA_FALSE); 1933 } 1934 1935 static IMA_STATUS get_target_oid_list( 1936 uint32_t targetListType, 1937 IMA_OID_LIST **ppList) 1938 { 1939 int fd; 1940 int i; 1941 int target_list_size; 1942 int status; 1943 int out_cnt; 1944 iscsi_target_list_t *idlp; 1945 1946 if ((status = open_driver(&fd))) { 1947 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 1948 } 1949 1950 idlp = (iscsi_target_list_t *)calloc(1, sizeof (iscsi_target_list_t)); 1951 if (idlp == NULL) { 1952 (void) close(fd); 1953 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1954 } 1955 idlp->tl_vers = ISCSI_INTERFACE_VERSION; 1956 idlp->tl_in_cnt = idlp->tl_out_cnt = 1; 1957 idlp->tl_tgt_list_type = targetListType; 1958 1959 /* 1960 * Issue ioctl. Space has been allocted for one entry. 1961 * If more than one entry should be returned, we will re-issue the 1962 * entry with the right amount of space allocted 1963 */ 1964 if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) { 1965 (void) close(fd); 1966 syslog(LOG_USER|LOG_DEBUG, 1967 "ISCSI_TARGET_OID_LIST_GET ioctl %d failed, errno: %d", 1968 targetListType, errno); 1969 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1970 } 1971 if (idlp->tl_out_cnt > 1) { 1972 out_cnt = idlp->tl_out_cnt; 1973 free(idlp); 1974 1975 target_list_size = sizeof (iscsi_target_list_t); 1976 target_list_size += (sizeof (uint32_t) * out_cnt - 1); 1977 idlp = (iscsi_target_list_t *)calloc(1, target_list_size); 1978 if (idlp == NULL) { 1979 (void) close(fd); 1980 return (IMA_ERROR_INSUFFICIENT_MEMORY); 1981 } 1982 idlp->tl_vers = ISCSI_INTERFACE_VERSION; 1983 idlp->tl_in_cnt = out_cnt; 1984 idlp->tl_tgt_list_type = targetListType; 1985 1986 /* Issue the same ioctl again to obtain all the OIDs. */ 1987 if (ioctl(fd, ISCSI_TARGET_OID_LIST_GET, idlp) != 0) { 1988 #define ERROR_STR "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl failed, errno :%d" 1989 free(idlp); 1990 (void) close(fd); 1991 syslog(LOG_USER|LOG_DEBUG, 1992 ERROR_STR, targetListType, errno); 1993 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 1994 #undef ERROR_STR 1995 1996 } 1997 } 1998 1999 *ppList = (IMA_OID_LIST *)calloc(1, sizeof (IMA_OID_LIST) + 2000 idlp->tl_out_cnt * sizeof (IMA_OID)); 2001 (*ppList)->oidCount = idlp->tl_out_cnt; 2002 for (i = 0; i < idlp->tl_out_cnt; i++) { 2003 (*ppList)->oids[i].objectType = IMA_OBJECT_TYPE_TARGET; 2004 (*ppList)->oids[i].ownerId = 1; 2005 (*ppList)->oids[i].objectSequenceNumber = idlp->tl_oid_list[i]; 2006 } 2007 2008 free(idlp); 2009 (void) close(fd); 2010 return (IMA_STATUS_SUCCESS); 2011 } 2012 2013 static IMA_STATUS get_target_lun_oid_list( 2014 IMA_OID * targetOid, 2015 iscsi_lun_list_t **ppLunList) 2016 { 2017 int fd; 2018 iscsi_lun_list_t *illp, *illp_saved; 2019 int lun_list_size; 2020 int status; 2021 2022 if ((status = open_driver(&fd))) { 2023 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2024 } 2025 2026 illp = (iscsi_lun_list_t *)calloc(1, sizeof (iscsi_lun_list_t)); 2027 if (illp == NULL) { 2028 (void) close(fd); 2029 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2030 } 2031 illp->ll_vers = ISCSI_INTERFACE_VERSION; 2032 if (targetOid == NULL) { 2033 /* get lun oid list for all targets */ 2034 illp->ll_all_tgts = B_TRUE; 2035 } else { 2036 /* get lun oid list for single target */ 2037 illp->ll_all_tgts = B_FALSE; 2038 illp->ll_tgt_oid = (uint32_t)targetOid->objectSequenceNumber; 2039 } 2040 illp->ll_in_cnt = illp->ll_out_cnt = 1; 2041 2042 /* 2043 * Issue ioctl to retrieve the target luns. Space has been allocted 2044 * for one entry. If more than one entry should be returned, we 2045 * will re-issue the entry with the right amount of space allocted 2046 */ 2047 if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) { 2048 (void) close(fd); 2049 syslog(LOG_USER|LOG_DEBUG, 2050 "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", errno); 2051 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2052 } 2053 2054 if (illp->ll_out_cnt > 1) { 2055 illp_saved = illp; 2056 lun_list_size = sizeof (iscsi_lun_list_t); 2057 lun_list_size += (sizeof (iscsi_if_lun_t) * 2058 (illp->ll_out_cnt - 1)); 2059 illp = (iscsi_lun_list_t *)calloc(1, lun_list_size); 2060 if (illp == NULL) { 2061 (void) close(fd); 2062 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2063 } 2064 illp->ll_vers = ISCSI_INTERFACE_VERSION; 2065 illp->ll_all_tgts = illp_saved->ll_all_tgts; 2066 illp->ll_tgt_oid = illp_saved->ll_tgt_oid; 2067 illp->ll_in_cnt = illp_saved->ll_out_cnt; 2068 2069 free(illp_saved); 2070 2071 /* Issue the same ioctl again to get all the target LUN list */ 2072 if (ioctl(fd, ISCSI_LUN_OID_LIST_GET, illp) != 0) { 2073 free(illp); 2074 (void) close(fd); 2075 syslog(LOG_USER|LOG_DEBUG, 2076 "ISCSI_LUN_LIST_GET ioctl failed, errno: %d", 2077 errno); 2078 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2079 2080 } 2081 } 2082 *ppLunList = illp; 2083 2084 2085 (void) close(fd); 2086 return (IMA_STATUS_SUCCESS); 2087 } 2088 2089 /* A helper function to obtain digest algorithms. */ 2090 static IMA_STATUS 2091 getDigest( 2092 IMA_OID oid, 2093 int ioctlCmd, 2094 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm 2095 ) 2096 { 2097 IMA_MIN_MAX_VALUE pProps; 2098 IMA_STATUS status; 2099 2100 if ((status = getISCSINodeParameter(MIN_MAX_PARAM, &oid, &pProps, 2101 ioctlCmd)) != IMA_STATUS_SUCCESS) { 2102 return (status); 2103 } 2104 2105 switch (pProps.defaultValue) { 2106 case ISCSI_DIGEST_NONE: 2107 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_NONE; 2108 algorithm->defaultAlgorithmCount = 1; 2109 break; 2110 case ISCSI_DIGEST_CRC32C: 2111 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_CRC32C; 2112 algorithm->defaultAlgorithmCount = 1; 2113 break; 2114 2115 case ISCSI_DIGEST_CRC32C_NONE: 2116 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_CRC32C; 2117 algorithm->defaultAlgorithms[1] = ISCSI_DIGEST_NONE; 2118 algorithm->defaultAlgorithmCount = 2; 2119 break; 2120 case ISCSI_DIGEST_NONE_CRC32C: 2121 algorithm->defaultAlgorithms[0] = ISCSI_DIGEST_NONE; 2122 algorithm->defaultAlgorithms[1] = ISCSI_DIGEST_CRC32C; 2123 algorithm->defaultAlgorithmCount = 2; 2124 break; 2125 default: 2126 /* Error */ 2127 syslog(LOG_USER|LOG_DEBUG, 2128 "Invalid default digest: %d", pProps.defaultValue); 2129 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2130 } 2131 2132 /* The configured value */ 2133 if (pProps.currentValueValid == IMA_TRUE) { 2134 algorithm->currentValid = IMA_TRUE; 2135 2136 switch (pProps.currentValue) { 2137 case ISCSI_DIGEST_NONE: 2138 algorithm->currentAlgorithms[0] = 2139 ISCSI_DIGEST_NONE; 2140 algorithm->currentAlgorithmCount = 1; 2141 break; 2142 case ISCSI_DIGEST_CRC32C: 2143 algorithm->currentAlgorithms[0] = 2144 ISCSI_DIGEST_CRC32C; 2145 algorithm->currentAlgorithmCount = 1; 2146 break; 2147 2148 case ISCSI_DIGEST_CRC32C_NONE: 2149 algorithm->currentAlgorithms[0] = 2150 ISCSI_DIGEST_CRC32C; 2151 algorithm->currentAlgorithms[1] = 2152 ISCSI_DIGEST_NONE; 2153 algorithm->currentAlgorithmCount = 2; 2154 break; 2155 case ISCSI_DIGEST_NONE_CRC32C: 2156 algorithm->currentAlgorithms[0] = 2157 ISCSI_DIGEST_NONE; 2158 algorithm->currentAlgorithms[1] = 2159 ISCSI_DIGEST_CRC32C; 2160 algorithm->currentAlgorithmCount = 2; 2161 break; 2162 default: 2163 /* Error */ 2164 syslog(LOG_USER|LOG_DEBUG, 2165 "Invalid configured digest: %d", 2166 pProps.defaultValue); 2167 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2168 } 2169 2170 } else { 2171 algorithm->currentValid = IMA_FALSE; 2172 } 2173 2174 return (IMA_STATUS_SUCCESS); 2175 } 2176 2177 /* 2178 * getConnOidList - 2179 */ 2180 static IMA_STATUS getConnOidList( 2181 IMA_OID *sessOid, 2182 iscsi_conn_list_t **ppConnList 2183 ) 2184 { 2185 iscsi_conn_list_t *iscsiConnList = NULL; 2186 size_t allocLen; 2187 int fd; 2188 int status; 2189 int out_cnt; 2190 2191 /* Preset it to NULL to prepare for the case of failure */ 2192 *ppConnList = NULL; 2193 2194 /* We try to open the driver now. */ 2195 if ((status = open_driver(&fd))) { 2196 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2197 } 2198 2199 iscsiConnList = (iscsi_conn_list_t *)calloc(1, 2200 sizeof (iscsi_conn_list_t)); 2201 if (iscsiConnList == NULL) { 2202 (void) close(fd); 2203 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2204 } 2205 iscsiConnList->cl_vers = ISCSI_INTERFACE_VERSION; 2206 iscsiConnList->cl_in_cnt = iscsiConnList->cl_out_cnt = 1; 2207 if (sessOid == NULL) { 2208 iscsiConnList->cl_all_sess = B_TRUE; 2209 } else { 2210 iscsiConnList->cl_all_sess = B_FALSE; 2211 iscsiConnList->cl_sess_oid = 2212 (uint32_t)sessOid->objectSequenceNumber; 2213 } 2214 /* 2215 * Issue ioctl to retrieve the connection OIDs. Space has been 2216 * allocated for one entry. If more than one entry should be 2217 * returned, we will re-issue the entry with the right amount of 2218 * space allocted 2219 */ 2220 if (ioctl(fd, ISCSI_CONN_OID_LIST_GET, iscsiConnList) != 0) { 2221 syslog(LOG_USER|LOG_DEBUG, 2222 "ISCSI_CONN_OID_LIST_GET ioctl failed, errno: %d", errno); 2223 *ppConnList = NULL; 2224 (void) close(fd); 2225 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2226 } 2227 if (iscsiConnList->cl_out_cnt > 1) { 2228 out_cnt = iscsiConnList->cl_out_cnt; 2229 free(iscsiConnList); 2230 2231 allocLen = sizeof (iscsi_conn_list_t); 2232 allocLen += (sizeof (iscsi_if_conn_t) * out_cnt - 1); 2233 iscsiConnList = (iscsi_conn_list_t *)calloc(1, allocLen); 2234 if (iscsiConnList == NULL) { 2235 *ppConnList = NULL; 2236 (void) close(fd); 2237 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2238 } 2239 iscsiConnList->cl_vers = ISCSI_INTERFACE_VERSION; 2240 iscsiConnList->cl_in_cnt = out_cnt; 2241 if (sessOid == NULL) { 2242 iscsiConnList->cl_all_sess = B_TRUE; 2243 } else { 2244 iscsiConnList->cl_all_sess = B_FALSE; 2245 iscsiConnList->cl_sess_oid = 2246 (uint32_t)sessOid->objectSequenceNumber; 2247 } 2248 /* Issue the same ioctl again to obtain all the OIDs */ 2249 if (ioctl(fd, ISCSI_CONN_OID_LIST_GET, iscsiConnList) != 0) { 2250 2251 syslog(LOG_USER|LOG_DEBUG, 2252 "ISCSI_CONN_OID_LIST_GET ioctl failed, errno: %d", 2253 errno); 2254 *ppConnList = NULL; 2255 free(iscsiConnList); 2256 (void) close(fd); 2257 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2258 2259 } 2260 2261 if (out_cnt < iscsiConnList->cl_out_cnt) { 2262 /* 2263 * The connection list grew between the first and second 2264 * ioctls. 2265 */ 2266 syslog(LOG_USER|LOG_DEBUG, 2267 "The connection list has grown. There could be " 2268 "more connections than listed."); 2269 } 2270 } 2271 2272 2273 (void) close(fd); 2274 *ppConnList = iscsiConnList; 2275 return (IMA_STATUS_SUCCESS); 2276 } 2277 2278 /* 2279 * getConnProps - 2280 */ 2281 static IMA_STATUS getConnProps( 2282 iscsi_if_conn_t *pConn, 2283 iscsi_conn_props_t **ppConnProps 2284 ) 2285 { 2286 iscsi_conn_props_t *iscsiConnProps; 2287 int fd; 2288 int status; 2289 2290 /* We try to open the driver. */ 2291 if ((status = open_driver(&fd))) { 2292 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2293 } 2294 2295 iscsiConnProps = (iscsi_conn_props_t *)calloc(1, 2296 sizeof (*iscsiConnProps)); 2297 2298 if (iscsiConnProps == NULL) { 2299 (void) close(fd); 2300 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2301 } 2302 2303 iscsiConnProps->cp_vers = ISCSI_INTERFACE_VERSION; 2304 iscsiConnProps->cp_oid = pConn->c_oid; 2305 iscsiConnProps->cp_cid = pConn->c_cid; 2306 iscsiConnProps->cp_sess_oid = pConn->c_sess_oid; 2307 2308 /* The IOCTL is submitted. */ 2309 if (ioctl(fd, ISCSI_CONN_PROPS_GET, iscsiConnProps) != 0) { 2310 /* IOCTL failed */ 2311 syslog(LOG_USER|LOG_DEBUG, 2312 "ISCSI_AUTH_CLEAR ioctl failed, errno: %d", errno); 2313 free(iscsiConnProps); 2314 (void) close(fd); 2315 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2316 } 2317 (void) close(fd); 2318 *ppConnProps = iscsiConnProps; 2319 return (IMA_STATUS_SUCCESS); 2320 } 2321 2322 /* A helper function to set authentication method. */ 2323 static IMA_STATUS 2324 setAuthMethods( 2325 IMA_OID oid, 2326 IMA_UINT *pMethodCount, 2327 const IMA_AUTHMETHOD *pMethodList 2328 ) 2329 { 2330 int fd; 2331 int i; 2332 int status; 2333 iscsi_auth_props_t auth; 2334 2335 if ((status = open_driver(&fd))) { 2336 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2337 } 2338 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t)); 2339 auth.a_vers = ISCSI_INTERFACE_VERSION; 2340 auth.a_oid = (uint32_t)oid.objectSequenceNumber; 2341 2342 /* 2343 * Get the current auth fields so they don't need to be reset 2344 * here. 2345 */ 2346 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) { 2347 /* EMPTY */ 2348 /* Initializing auth structure with current settings */ 2349 } 2350 auth.a_auth_method = authMethodNone; 2351 2352 for (i = 0; i < *pMethodCount; i++) { 2353 switch (pMethodList[i]) { 2354 case IMA_AUTHMETHOD_CHAP: 2355 auth.a_auth_method |= authMethodCHAP; 2356 break; 2357 default: 2358 break; 2359 } 2360 } 2361 2362 if (ioctl(fd, ISCSI_AUTH_SET, &auth) != 0) { 2363 syslog(LOG_USER|LOG_DEBUG, 2364 "ISCSI_AUTH_SET failed, errno: %d", errno); 2365 (void) close(fd); 2366 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2367 } 2368 2369 (void) close(fd); 2370 return (IMA_STATUS_SUCCESS); 2371 } 2372 2373 /* A helper function to set authentication method. */ 2374 static IMA_STATUS getAuthMethods( 2375 IMA_OID oid, 2376 IMA_UINT *pMethodCount, 2377 IMA_AUTHMETHOD *pMethodList 2378 ) 2379 { 2380 int fd; 2381 int status; 2382 iscsi_auth_props_t auth; 2383 2384 if ((status = open_driver(&fd))) { 2385 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2386 } 2387 2388 (void) memset(&auth, 0, sizeof (iscsi_auth_props_t)); 2389 auth.a_vers = ISCSI_INTERFACE_VERSION; 2390 auth.a_oid = (uint32_t)oid.objectSequenceNumber; 2391 2392 if (ioctl(fd, ISCSI_AUTH_GET, &auth) != 0) { 2393 syslog(LOG_USER|LOG_DEBUG, 2394 "ISCSI_AUTH_GET failed, errno: %d", errno); 2395 (void) close(fd); 2396 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2397 } 2398 2399 if (auth.a_auth_method == authMethodNone) { 2400 pMethodList[0] = IMA_AUTHMETHOD_NONE; 2401 *pMethodCount = 1; 2402 } else { 2403 int i = 0; 2404 if (!((auth.a_auth_method & authMethodCHAP)^authMethodCHAP)) { 2405 pMethodList[i++] = IMA_AUTHMETHOD_CHAP; 2406 } 2407 *pMethodCount = i; 2408 } 2409 2410 (void) close(fd); 2411 return (IMA_STATUS_SUCCESS); 2412 } 2413 2414 /* Helper function to open driver */ 2415 int open_driver( 2416 int *fd 2417 ) 2418 { 2419 int ret = 0; 2420 if ((*fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 2421 ret = errno; 2422 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)", 2423 ISCSI_DRIVER_DEVCTL, ret); 2424 } 2425 return (ret); 2426 } 2427 2428 /* 2429 * Iscsi driver does not support OID for discovery address. Create 2430 * a modified version of IMA_RemoveDiscoveryAddress that takes 2431 * discoveryAddress (instead of an OID) as input argument. 2432 */ 2433 IMA_API IMA_STATUS SUN_IMA_RemoveDiscoveryAddress( 2434 SUN_IMA_TARGET_ADDRESS discoveryAddress 2435 ) 2436 { 2437 entry_t entry; 2438 int fd; 2439 int status, i, addr_list_size, insize; 2440 iscsi_addr_list_t *idlp, al_info; 2441 iscsi_addr_t *matched_addr = NULL; 2442 2443 if ((status = open_driver(&fd))) { 2444 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2445 } 2446 2447 if (prepare_discovery_entry(discoveryAddress, &entry) != 2448 DISC_ADDR_OK) { 2449 (void) close(fd); 2450 return (IMA_ERROR_INVALID_PARAMETER); 2451 } 2452 2453 (void) memset(&al_info, 0, sizeof (al_info)); 2454 al_info.al_vers = ISCSI_INTERFACE_VERSION; 2455 al_info.al_in_cnt = 0; 2456 /* 2457 * Issue ioctl to get the number of discovery address. 2458 */ 2459 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, &al_info) != 0) { 2460 syslog(LOG_USER|LOG_DEBUG, 2461 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d", 2462 ISCSI_DISCOVERY_ADDR_LIST_GET, errno); 2463 (void) close(fd); 2464 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2465 } 2466 2467 if (al_info.al_out_cnt == 0) { 2468 (void) close(fd); 2469 return (IMA_ERROR_OBJECT_NOT_FOUND); 2470 } 2471 2472 addr_list_size = sizeof (iscsi_addr_list_t); 2473 if (al_info.al_out_cnt > 1) { 2474 addr_list_size += (sizeof (iscsi_addr_t) * 2475 (al_info.al_out_cnt - 1)); 2476 } 2477 2478 idlp = (iscsi_addr_list_t *)calloc(1, addr_list_size); 2479 if (idlp == NULL) { 2480 (void) close(fd); 2481 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2482 } 2483 2484 idlp->al_vers = ISCSI_INTERFACE_VERSION; 2485 idlp->al_in_cnt = al_info.al_out_cnt; 2486 2487 /* issue the same ioctl to get all the discovery addresses */ 2488 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_LIST_GET, idlp) != 0) { 2489 syslog(LOG_USER|LOG_DEBUG, 2490 "ISCSI_DISCOVERY_ADDR_LIST_GET ioctl %d failed, errno: %d", 2491 ISCSI_DISCOVERY_ADDR_LIST_GET, errno); 2492 free(idlp); 2493 (void) close(fd); 2494 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2495 } 2496 2497 /* 2498 * find the matched discovery address 2499 */ 2500 for (i = 0; i < idlp->al_out_cnt; i++) { 2501 insize = idlp->al_addrs[i].a_addr.i_insize; 2502 if (insize != entry.e_insize) { 2503 continue; 2504 } 2505 if (insize == sizeof (struct in_addr)) { 2506 if (idlp->al_addrs[i].a_addr.i_addr.in4.s_addr == 2507 entry.e_u.u_in4.s_addr) { 2508 matched_addr = &(idlp->al_addrs[i]); 2509 break; 2510 } 2511 } 2512 if (insize == sizeof (struct in6_addr)) { 2513 if (bcmp(entry.e_u.u_in6.s6_addr, 2514 idlp->al_addrs[i].a_addr.i_addr.in6.s6_addr, 2515 insize) == 0) { 2516 matched_addr = &(idlp->al_addrs[i]); 2517 break; 2518 } 2519 } 2520 } 2521 2522 free(idlp); 2523 2524 if (matched_addr == NULL) { 2525 (void) close(fd); 2526 return (IMA_ERROR_OBJECT_NOT_FOUND); 2527 } 2528 2529 if (ioctl(fd, ISCSI_DISCOVERY_ADDR_CLEAR, &entry)) { 2530 status = errno; 2531 (void) close(fd); 2532 syslog(LOG_USER|LOG_DEBUG, 2533 "ISCSI_DISCOVERY_ADDR_CLEAR ioctl failed, errno: %d", 2534 errno); 2535 if (status == EBUSY) { 2536 return (IMA_ERROR_LU_IN_USE); 2537 } else { 2538 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2539 } 2540 } 2541 2542 (void) close(fd); 2543 return (IMA_STATUS_SUCCESS); 2544 } 2545 2546 IMA_STATUS SUN_IMA_SetTargetAuthMethods( 2547 IMA_OID targetOid, 2548 IMA_UINT *methodCount, 2549 const IMA_AUTHMETHOD *pMethodList 2550 ) 2551 { 2552 return (setAuthMethods(targetOid, methodCount, pMethodList)); 2553 } 2554 2555 IMA_STATUS getNegotiatedDigest( 2556 int digestType, 2557 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm, 2558 SUN_IMA_CONN_PROPERTIES *connProps) { 2559 2560 IMA_UINT digest; 2561 2562 if (connProps->valuesValid == IMA_TRUE) { 2563 algorithm->negotiatedValid = IMA_TRUE; 2564 2565 if (digestType == ISCSI_LOGIN_PARAM_HEADER_DIGEST) { 2566 digest = connProps->headerDigest; 2567 } else { 2568 digest = connProps->dataDigest; 2569 } 2570 2571 switch (digest) { 2572 case ISCSI_DIGEST_NONE: 2573 algorithm->negotiatedAlgorithms[0] = 2574 ISCSI_DIGEST_NONE; 2575 algorithm->negotiatedAlgorithmCount = 1; 2576 break; 2577 case ISCSI_DIGEST_CRC32C: 2578 algorithm->negotiatedAlgorithms[0] = 2579 ISCSI_DIGEST_CRC32C; 2580 algorithm->negotiatedAlgorithmCount = 1; 2581 break; 2582 2583 case ISCSI_DIGEST_CRC32C_NONE: 2584 algorithm->negotiatedAlgorithms[0] = 2585 ISCSI_DIGEST_CRC32C; 2586 algorithm->negotiatedAlgorithms[1] = 2587 ISCSI_DIGEST_NONE; 2588 algorithm->negotiatedAlgorithmCount = 2; 2589 break; 2590 case ISCSI_DIGEST_NONE_CRC32C: 2591 algorithm->negotiatedAlgorithms[0] = 2592 ISCSI_DIGEST_NONE; 2593 algorithm->negotiatedAlgorithms[1] = 2594 ISCSI_DIGEST_CRC32C; 2595 algorithm->negotiatedAlgorithmCount = 2; 2596 break; 2597 default: 2598 syslog(LOG_USER|LOG_DEBUG, 2599 "Invalid negotiated digest: %d", 2600 digest); 2601 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2602 } 2603 } else { 2604 algorithm->negotiatedValid = IMA_FALSE; 2605 } 2606 return (IMA_STATUS_SUCCESS); 2607 } 2608 2609 /* 2610 * Non-IMA defined function. 2611 */ 2612 IMA_API IMA_STATUS SUN_IMA_GetISNSServerAddressPropertiesList( 2613 SUN_IMA_DISC_ADDR_PROP_LIST **ppList 2614 ) 2615 { 2616 char isns_server_addr_str[256]; 2617 int fd; 2618 int i; 2619 int isns_server_addr_list_size; 2620 int status; 2621 int out_cnt; 2622 iscsi_addr_list_t *ialp; 2623 /* LINTED */ 2624 IMA_IP_ADDRESS *ipAddr; 2625 2626 if ((status = open_driver(&fd))) { 2627 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2628 } 2629 2630 ialp = (iscsi_addr_list_t *)calloc(1, sizeof (iscsi_addr_list_t)); 2631 if (ialp == NULL) { 2632 (void) close(fd); 2633 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2634 } 2635 ialp->al_vers = ISCSI_INTERFACE_VERSION; 2636 ialp->al_in_cnt = ialp->al_out_cnt = 1; 2637 2638 /* 2639 * Issue ioctl to retrieve the isns server addresses. Space has been 2640 * allocted for one entry. If more than one entry should be returned, 2641 * we will re-issue the entry with the right amount of space allocted 2642 */ 2643 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_LIST_GET, ialp) != 0) { 2644 (void) close(fd); 2645 syslog(LOG_USER|LOG_DEBUG, 2646 "ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl failed, errno: %d", 2647 errno); 2648 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2649 } 2650 2651 isns_server_addr_list_size = sizeof (iscsi_addr_list_t); 2652 if (ialp->al_out_cnt > 1) { 2653 out_cnt = ialp->al_out_cnt; 2654 free(ialp); 2655 2656 isns_server_addr_list_size += (sizeof (iscsi_addr_t) * 2657 out_cnt - 1); 2658 ialp = (iscsi_addr_list_t *)calloc(1, 2659 isns_server_addr_list_size); 2660 if (ialp == NULL) { 2661 (void) close(fd); 2662 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2663 } 2664 ialp->al_vers = ISCSI_INTERFACE_VERSION; 2665 ialp->al_in_cnt = out_cnt; 2666 2667 /* 2668 * Issue ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl again to obtain 2669 * the list of all the iSNS server addresses 2670 */ 2671 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_LIST_GET, ialp) != 0) { 2672 free(ialp); 2673 (void) close(fd); 2674 syslog(LOG_USER|LOG_DEBUG, 2675 "ISCSI_ISNS_SERVER_ADDR_LIST_GET ioctl failed, " 2676 "errno: %d", errno); 2677 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2678 2679 } 2680 } 2681 2682 *ppList = (SUN_IMA_DISC_ADDR_PROP_LIST *)calloc(1, 2683 sizeof (SUN_IMA_DISC_ADDR_PROP_LIST) + 2684 ialp->al_out_cnt * sizeof (IMA_DISCOVERY_ADDRESS_PROPERTIES)); 2685 if (*ppList == NULL) { 2686 free(ialp); 2687 (void) close(fd); 2688 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2689 } 2690 (*ppList)->discAddrCount = ialp->al_out_cnt; 2691 2692 for (i = 0; i < ialp->al_out_cnt; i++) { 2693 if (ialp->al_addrs[i].a_addr.i_insize == 2694 sizeof (struct in_addr)) { 2695 (*ppList)->props[i].discoveryAddress.hostnameIpAddress. 2696 id.ipAddress.ipv4Address = IMA_TRUE; 2697 } else if (ialp->al_addrs[i].a_addr.i_insize == 2698 sizeof (struct in6_addr)) { 2699 (*ppList)->props[i].discoveryAddress.hostnameIpAddress. 2700 id.ipAddress.ipv4Address = IMA_FALSE; 2701 } else { 2702 (void) strlcpy(isns_server_addr_str, "unknown", 2703 sizeof (isns_server_addr_str)); 2704 } 2705 2706 ipAddr = &(*ppList)->props[i].discoveryAddress. 2707 hostnameIpAddress.id.ipAddress; 2708 bcopy(&ialp->al_addrs[i].a_addr.i_addr, 2709 (*ppList)->props[i].discoveryAddress.hostnameIpAddress.id. 2710 ipAddress.ipAddress, 2711 sizeof (ipAddr->ipAddress)); 2712 (*ppList)->props[i].discoveryAddress.portNumber = 2713 ialp->al_addrs[i].a_port; 2714 } 2715 2716 free(ialp); 2717 (void) close(fd); 2718 return (IMA_STATUS_SUCCESS); 2719 } 2720 2721 /*ARGSUSED*/ 2722 /* 2723 * Remove iSNS Server Address 2724 */ 2725 IMA_API IMA_STATUS SUN_IMA_RemoveISNSServerAddress( 2726 SUN_IMA_TARGET_ADDRESS isnsServerAddress 2727 ) 2728 { 2729 entry_t entry; 2730 int fd, status; 2731 2732 if ((status = open_driver(&fd))) { 2733 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2734 } 2735 2736 if (prepare_discovery_entry(isnsServerAddress, &entry) != 2737 DISC_ADDR_OK) { 2738 (void) close(fd); 2739 return (IMA_ERROR_INVALID_PARAMETER); 2740 } 2741 2742 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_CLEAR, &entry)) { 2743 status = errno; 2744 (void) close(fd); 2745 syslog(LOG_USER|LOG_DEBUG, 2746 "ISCSI_ISNS_SERVER_ADDR_CLEAR ioctl failed, errno: %d", 2747 status); 2748 if (status == EBUSY) { 2749 return (IMA_ERROR_LU_IN_USE); 2750 } else { 2751 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2752 } 2753 } 2754 2755 (void) close(fd); 2756 return (IMA_STATUS_SUCCESS); 2757 } 2758 2759 /*ARGSUSED*/ 2760 IMA_API IMA_STATUS SUN_IMA_AddISNSServerAddress( 2761 const SUN_IMA_TARGET_ADDRESS isnsServerAddress 2762 ) 2763 { 2764 entry_t entry; 2765 int fd; 2766 int status; 2767 2768 if ((status = open_driver(&fd))) { 2769 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2770 } 2771 2772 if (prepare_discovery_entry(isnsServerAddress, &entry) != 2773 DISC_ADDR_OK) { 2774 (void) close(fd); 2775 return (IMA_ERROR_INVALID_PARAMETER); 2776 } 2777 2778 if (ioctl(fd, ISCSI_ISNS_SERVER_ADDR_SET, &entry)) { 2779 /* 2780 * Encountered problem setting the discovery address. 2781 */ 2782 (void) close(fd); 2783 syslog(LOG_USER|LOG_DEBUG, 2784 "ISCSI_ISNS_SERVER_ADDR_SET ioctl failed, errno: %d", 2785 errno); 2786 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2787 } 2788 2789 (void) close(fd); 2790 return (IMA_STATUS_SUCCESS); 2791 } 2792 2793 IMA_STATUS SUN_IMA_RetrieveISNSServerTargets( 2794 IMA_TARGET_ADDRESS serverAddress, 2795 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES **ppList 2796 ) 2797 { 2798 int fd; 2799 int ctr; 2800 int server_pg_list_sz; 2801 int status; 2802 isns_server_portal_group_list_t *server_pg_list = NULL; 2803 isns_portal_group_list_t *pg_list = NULL; 2804 IMA_BOOL retry = IMA_TRUE; 2805 entry_t entry; 2806 2807 #define ISNS_SERVER_DEFAULT_NUM_TARGETS 50 2808 2809 server_pg_list_sz = sizeof (*server_pg_list) + 2810 ((ISNS_SERVER_DEFAULT_NUM_TARGETS - 1) * 2811 sizeof (isns_portal_group_t)); 2812 2813 server_pg_list = (isns_server_portal_group_list_t *)calloc(1, 2814 server_pg_list_sz); 2815 if (server_pg_list == NULL) { 2816 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2817 } 2818 server_pg_list->addr_port_list.pg_in_cnt = 2819 ISNS_SERVER_DEFAULT_NUM_TARGETS; 2820 2821 if ((prepare_discovery_entry_IMA(serverAddress, &entry) 2822 != DISC_ADDR_OK)) { 2823 free(server_pg_list); 2824 return (IMA_ERROR_INVALID_PARAMETER); 2825 } 2826 server_pg_list->addr.a_port = entry.e_port; 2827 server_pg_list->addr.a_addr.i_insize = entry.e_insize; 2828 if (entry.e_insize == sizeof (struct in_addr)) { 2829 server_pg_list->addr.a_addr.i_addr.in4.s_addr = 2830 (entry.e_u.u_in4.s_addr); 2831 } else if (entry.e_insize == sizeof (struct in6_addr)) { 2832 bcopy(&entry.e_u.u_in6.s6_addr, 2833 server_pg_list->addr.a_addr.i_addr.in6.s6_addr, 16); 2834 } 2835 2836 if ((status = open_driver(&fd))) { 2837 free(server_pg_list); 2838 return (SUN_IMA_ERROR_SYSTEM_ERROR | status); 2839 } 2840 2841 retry_isns: 2842 /* 2843 * Issue ioctl to obtain the ISNS Portal Group List list 2844 */ 2845 if (ioctl(fd, ISCSI_ISNS_SERVER_GET, server_pg_list) != 0) { 2846 int tmp_errno = errno; 2847 IMA_STATUS return_status; 2848 2849 syslog(LOG_USER|LOG_DEBUG, 2850 "ISCSI_ISNS_SERVER_GET ioctl failed, errno: %d", tmp_errno); 2851 if (tmp_errno == EACCES) { 2852 return_status = IMA_ERROR_OBJECT_NOT_FOUND; 2853 } else { 2854 return_status = IMA_ERROR_UNEXPECTED_OS_ERROR; 2855 } 2856 (void) close(fd); 2857 free(server_pg_list); 2858 return (return_status); 2859 } 2860 pg_list = &server_pg_list->addr_port_list; 2861 2862 /* check if all targets received */ 2863 if (pg_list->pg_in_cnt < pg_list->pg_out_cnt) { 2864 if (retry == IMA_TRUE) { 2865 server_pg_list_sz = sizeof (*server_pg_list) + 2866 ((pg_list->pg_out_cnt - 1) * 2867 sizeof (isns_server_portal_group_list_t)); 2868 server_pg_list = (isns_server_portal_group_list_t *) 2869 realloc(server_pg_list, server_pg_list_sz); 2870 if (server_pg_list == NULL) { 2871 (void) close(fd); 2872 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2873 } 2874 pg_list = &server_pg_list->addr_port_list; 2875 pg_list->pg_in_cnt = pg_list->pg_out_cnt; 2876 retry = IMA_FALSE; 2877 goto retry_isns; 2878 } else { 2879 /* 2880 * don't retry after 2 attempts. The target list 2881 * shouldn't continue growing. Just continue 2882 * on and display what was found. 2883 */ 2884 syslog(LOG_USER|LOG_DEBUG, 2885 "ISCSI_SENDTGTS_GET overflow: " 2886 "failed to obtain all targets"); 2887 pg_list->pg_out_cnt = pg_list->pg_in_cnt; 2888 } 2889 } 2890 2891 (void) close(fd); 2892 2893 /* allocate for caller return buffer */ 2894 *ppList = (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *)calloc(1, 2895 sizeof (SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES) + 2896 pg_list->pg_out_cnt * sizeof (SUN_IMA_DISC_ADDRESS_KEY)); 2897 if (*ppList == NULL) { 2898 free(server_pg_list); 2899 return (IMA_ERROR_INSUFFICIENT_MEMORY); 2900 } 2901 2902 (*ppList)->keyCount = pg_list->pg_out_cnt; 2903 2904 for (ctr = 0; ctr < pg_list->pg_out_cnt; ctr++) { 2905 (void) mbstowcs((*ppList)->keys[ctr].name, 2906 (char *)pg_list->pg_list[ctr].pg_iscsi_name, 2907 IMA_NODE_NAME_LEN); 2908 2909 (*ppList)->keys[ctr].tpgt = pg_list->pg_list[ctr].pg_tag; 2910 2911 (*ppList)->keys[ctr].address.portNumber = 2912 pg_list->pg_list[ctr].pg_port; 2913 2914 if (pg_list->pg_list[ctr].insize == sizeof (struct in_addr)) { 2915 (*ppList)->keys[ctr].address.ipAddress.ipv4Address = 2916 IMA_TRUE; 2917 } else if (pg_list->pg_list[ctr].insize == 2918 sizeof (struct in6_addr)) { 2919 (*ppList)->keys[ctr].address.ipAddress.ipv4Address = 2920 IMA_FALSE; 2921 } else { 2922 free(pg_list); 2923 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2924 } 2925 2926 (void) memcpy(&(*ppList)->keys[ctr].address.ipAddress.ipAddress, 2927 &(pg_list->pg_list[ctr].pg_ip_addr), 2928 pg_list->pg_list[ctr].insize); 2929 } 2930 free(server_pg_list); 2931 2932 return (IMA_STATUS_SUCCESS); 2933 } 2934 2935 /* ARGSUSED */ 2936 IMA_STATUS SUN_IMA_GetSessionOidList( 2937 IMA_OID initiatorOid, 2938 IMA_OID_LIST **ppList 2939 ) 2940 { 2941 return (get_target_oid_list(ISCSI_TGT_OID_LIST, ppList)); 2942 } 2943 2944 /*ARGSUSED*/ 2945 IMA_API IMA_STATUS SUN_IMA_GetTargetAuthParms( 2946 IMA_OID oid, 2947 IMA_AUTHMETHOD method, 2948 IMA_INITIATOR_AUTHPARMS *pParms 2949 ) 2950 { 2951 int fd; 2952 iscsi_chap_props_t chap_p; 2953 2954 if (pParms == NULL) { 2955 return (IMA_ERROR_INVALID_PARAMETER); 2956 } 2957 2958 if (oid.objectType != IMA_OBJECT_TYPE_TARGET) { 2959 return (IMA_ERROR_INCORRECT_OBJECT_TYPE); 2960 } 2961 2962 if (method != IMA_AUTHMETHOD_CHAP) { 2963 return (IMA_ERROR_INVALID_PARAMETER); 2964 } 2965 2966 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 2967 syslog(LOG_USER|LOG_DEBUG, "Cannot open %s (%d)", 2968 ISCSI_DRIVER_DEVCTL, errno); 2969 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2970 } 2971 2972 (void) memset(&chap_p, 0, sizeof (iscsi_chap_props_t)); 2973 chap_p.c_vers = ISCSI_INTERFACE_VERSION; 2974 chap_p.c_oid = (uint32_t)oid.objectSequenceNumber; 2975 2976 if (ioctl(fd, ISCSI_CHAP_GET, &chap_p) != 0) { 2977 syslog(LOG_USER|LOG_DEBUG, 2978 2979 "ISCSI_CHAP_GET ioctl failed, errno: %d", 2980 errno); 2981 (void) close(fd); 2982 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 2983 } 2984 2985 (void) memcpy(pParms->chapParms.name, chap_p.c_user, 2986 chap_p.c_user_len); 2987 2988 pParms->chapParms.nameLength = chap_p.c_user_len; 2989 (void) memcpy(pParms->chapParms.challengeSecret, chap_p.c_secret, 2990 chap_p.c_secret_len); 2991 2992 pParms->chapParms.challengeSecretLength = chap_p.c_secret_len; 2993 2994 return (IMA_STATUS_SUCCESS); 2995 } 2996 2997 IMA_API IMA_STATUS SUN_IMA_GetBootTargetName( 2998 IMA_NODE_NAME tgtName 2999 ) 3000 { 3001 int fd; 3002 IMA_STATUS rtn; 3003 iscsi_boot_property_t bootProp; 3004 3005 bootProp.tgt_name.n_name[0] = '\0'; 3006 bootProp.tgt_chap.c_user[0] = '\0'; 3007 tgtName[0] = L'\0'; 3008 rtn = IMA_ERROR_UNEXPECTED_OS_ERROR; 3009 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3010 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3011 ISCSI_DRIVER_DEVCTL, errno); 3012 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3013 } 3014 3015 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3016 syslog(LOG_USER|LOG_DEBUG, 3017 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3018 errno); 3019 (void) close(fd); 3020 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3021 } 3022 3023 if ((bootProp.tgt_name.n_name[0] != '\0') && (tgtName != NULL)) { 3024 if (mbstowcs(tgtName, (const char *)bootProp.tgt_name.n_name, 3025 IMA_NODE_NAME_LEN) == (size_t)-1) { 3026 syslog(LOG_USER|LOG_DEBUG, 3027 "ISCSI Target name covert to WCHAR fail"); 3028 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3029 } else { 3030 rtn = IMA_STATUS_SUCCESS; 3031 } 3032 } 3033 3034 return (rtn); 3035 } 3036 3037 IMA_API IMA_STATUS SUN_IMA_GetBootTargetAuthParams( 3038 IMA_INITIATOR_AUTHPARMS *pTgtCHAP 3039 ) 3040 { 3041 int fd; 3042 IMA_STATUS rtn; 3043 iscsi_boot_property_t bootProp; 3044 3045 bootProp.tgt_name.n_name[0] = '\0'; 3046 bootProp.tgt_chap.c_user[0] = '\0'; 3047 bootProp.tgt_chap.c_secret[0] = '\0'; 3048 rtn = IMA_ERROR_UNEXPECTED_OS_ERROR; 3049 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3050 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3051 ISCSI_DRIVER_DEVCTL, errno); 3052 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3053 } 3054 3055 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3056 syslog(LOG_USER|LOG_DEBUG, 3057 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3058 errno); 3059 (void) close(fd); 3060 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3061 } 3062 3063 if (pTgtCHAP != NULL) { 3064 if (bootProp.tgt_chap.c_user[0] != '\0') { 3065 (void) memcpy(pTgtCHAP->chapParms.name, 3066 bootProp.tgt_chap.c_user, ISCSI_MAX_NAME_LEN); 3067 } else { 3068 pTgtCHAP->chapParms.name[0] = '\0'; 3069 } 3070 if (bootProp.tgt_chap.c_secret[0] != '\0') { 3071 (void) memcpy(pTgtCHAP->chapParms.challengeSecret, 3072 bootProp.tgt_chap.c_secret, MAX_CHAP_SECRET_LEN); 3073 } else { 3074 pTgtCHAP->chapParms.challengeSecret[0] = '\0'; 3075 } 3076 rtn = IMA_STATUS_SUCCESS; 3077 } 3078 return (rtn); 3079 } 3080 3081 IMA_STATUS SUN_IMA_GetBootMpxio( 3082 IMA_BOOL *pMpxioEnabled 3083 ) 3084 { 3085 int fd; 3086 iscsi_boot_property_t bootProp; 3087 3088 bootProp.hba_mpxio_enabled = B_FALSE; 3089 *pMpxioEnabled = IMA_UNKNOWN; 3090 3091 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3092 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3093 ISCSI_DRIVER_DEVCTL, errno); 3094 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3095 } 3096 3097 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3098 syslog(LOG_USER|LOG_DEBUG, 3099 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3100 errno); 3101 (void) close(fd); 3102 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3103 } 3104 3105 if (bootProp.hba_mpxio_enabled) { 3106 *pMpxioEnabled = IMA_TRUE; 3107 } else { 3108 *pMpxioEnabled = IMA_FALSE; 3109 } 3110 3111 (void) close(fd); 3112 return (IMA_STATUS_SUCCESS); 3113 } 3114 3115 IMA_STATUS SUN_IMA_GetBootIscsi( 3116 IMA_BOOL *pIscsiBoot 3117 ) 3118 { 3119 int fd; 3120 iscsi_boot_property_t bootProp; 3121 3122 bootProp.iscsiboot = 0; 3123 *pIscsiBoot = 0; 3124 3125 if ((fd = open(ISCSI_DRIVER_DEVCTL, O_RDONLY)) == -1) { 3126 syslog(LOG_USER|LOG_DEBUG, "Unable to open %s (%d)", 3127 ISCSI_DRIVER_DEVCTL, errno); 3128 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3129 } 3130 3131 if (ioctl(fd, ISCSI_BOOTPROP_GET, &bootProp) != 0) { 3132 syslog(LOG_USER|LOG_DEBUG, 3133 "ISCSI_BOOTPROP_GET ioctl failed, errno: %d", 3134 errno); 3135 (void) close(fd); 3136 return (IMA_ERROR_UNEXPECTED_OS_ERROR); 3137 } 3138 3139 *pIscsiBoot = bootProp.iscsiboot; 3140 3141 (void) close(fd); 3142 return (IMA_STATUS_SUCCESS); 3143 } 3144