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 <stdlib.h> 27 #include <stdio.h> 28 #include <wchar.h> 29 #include <widec.h> 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 #include <arpa/inet.h> 33 #include <netdb.h> 34 #include <unistd.h> 35 #include <libintl.h> 36 #include <limits.h> 37 #include <string.h> 38 #include <strings.h> 39 #include <syslog.h> 40 #include <errno.h> 41 #include <netinet/in.h> 42 #include <sys/socket.h> 43 #include <arpa/inet.h> 44 #include <wctype.h> 45 #include <assert.h> 46 47 #include <ima.h> 48 #include <libsun_ima.h> 49 #include <sys/iscsi_protocol.h> 50 #include <sys/scsi/adapters/iscsi_if.h> 51 52 #include "cmdparse.h" 53 #include "sun_ima.h" 54 #include "iscsiadm.h" 55 56 #define VERSION_STRING_MAX_LEN 10 57 #define MAX_LONG_CHAR_LEN 19 58 59 #define MAX_AUTH_METHODS 5 60 /* 61 * Version number: 62 * MAJOR - This should only change when there is an incompatible change made 63 * to the interfaces or the output. 64 * 65 * MINOR - This should change whenever there is a new command or new feature 66 * with no incompatible change. 67 */ 68 #define VERSION_STRING_MAJOR "1" 69 #define VERSION_STRING_MINOR "0" 70 71 #define OPTIONSTRING1 "yes|no" 72 #define OPTIONSTRING2 "initiator node name" 73 #define OPTIONSTRING3 "initiator node alias" 74 #define OPTIONSTRING4 "enable|disable" 75 #define OPTIONSTRING5 "key=value,..." 76 #define OPTIONSTRING6 "none|CRC32" 77 #define OPTIONSTRING7 "CHAP name" 78 #define OPTIONSTRING8 "<# sessions>|<IP Address>[,<IP Address>]*" 79 #define OPTIONSTRING9 "tunable-prop=value" 80 #define OPTIONVAL1 "0 to 3600" 81 #define OPTIONVAL2 "512 to 2**24 - 1" 82 #define OPTIONVAL3 "1 to 65535" 83 #define OPTIONVAL4 "<IP address>[:port]" 84 85 #define MAX_ISCSI_NAME_LEN 223 86 #define MAX_ADDRESS_LEN 255 87 #define MIN_CHAP_SECRET_LEN 12 88 #define MAX_CHAP_SECRET_LEN 16 89 #define DEFAULT_ISCSI_PORT 3260 90 #define ISNS_DEFAULT_SERVER_PORT 3205 91 #define DEFAULT_RADIUS_PORT 1812 92 #define MAX_CHAP_NAME_LEN 512 93 #define ISCSI_DEFAULT_RX_TIMEOUT_VALUE "60" 94 #define ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX "180" 95 #define ISCSI_DEFAULT_LOGIN_POLLING_DELAY "60" 96 97 /* For listNode */ 98 #define INF_ERROR 1 99 #define INVALID_NODE_NAME 2 100 101 #define IMABOOLPRINT(prop, option) \ 102 if ((option) == PRINT_CONFIGURED_PARAMS) { \ 103 (void) fprintf(stdout, "%s/%s\n", \ 104 (prop).defaultValue == IMA_TRUE ? gettext("yes") : \ 105 gettext("no"), \ 106 (prop).currentValueValid == IMA_TRUE ? \ 107 ((prop).currentValue == IMA_TRUE ? \ 108 gettext("yes"): gettext("no")) : "-"); \ 109 } else if ((option) == PRINT_NEGOTIATED_PARAMS) { \ 110 (void) fprintf(stdout, "%s\n", \ 111 (prop).currentValueValid == IMA_TRUE ? \ 112 (((prop).currentValue == IMA_TRUE) ? gettext("yes") : \ 113 gettext("no")) : "-"); \ 114 } 115 116 #define IMAMINMAXPRINT(prop, option) \ 117 if ((option) == PRINT_CONFIGURED_PARAMS) { \ 118 (void) fprintf(stdout, "%d/", (prop).defaultValue); \ 119 if ((prop).currentValueValid == IMA_TRUE) { \ 120 (void) fprintf(stdout, "%d\n", (prop).currentValue); \ 121 } else if ((prop).currentValueValid == IMA_FALSE) { \ 122 (void) fprintf(stdout, "%s\n", "-"); \ 123 } \ 124 } else if ((option) == PRINT_NEGOTIATED_PARAMS) { \ 125 if ((prop).currentValueValid == IMA_TRUE) { \ 126 (void) fprintf(stdout, "%d\n", (prop).currentValue); \ 127 } else if ((prop).currentValueValid == IMA_FALSE) { \ 128 (void) fprintf(stdout, "%s\n", "-"); \ 129 } \ 130 } 131 132 /* forward declarations */ 133 #define PARSE_ADDR_OK 0 134 #define PARSE_ADDR_MISSING_CLOSING_BRACKET 1 135 #define PARSE_ADDR_PORT_OUT_OF_RANGE 2 136 #define PARSE_TARGET_OK 0 137 #define PARSE_TARGET_INVALID_TPGT 1 138 #define PARSE_TARGET_INVALID_ADDR 2 139 140 #define PRINT_CONFIGURED_PARAMS 1 141 #define PRINT_NEGOTIATED_PARAMS 2 142 143 typedef enum iSCSINameCheckStatus { 144 iSCSINameCheckOK, 145 iSCSINameLenZero, 146 iSCSINameLenExceededMax, 147 iSCSINameUnknownType, 148 iSCSINameInvalidCharacter, 149 iSCSINameIqnFormatError, 150 iSCSINameEUIFormatError, 151 iSCSINameIqnDateFormatError, 152 iSCSINameIqnSubdomainFormatError, 153 iSCSINameIqnInvalidYearError, 154 iSCSINameIqnInvalidMonthError, 155 iSCSINameIqnFQDNError 156 } iSCSINameCheckStatusType; 157 158 /* Utility functions */ 159 iSCSINameCheckStatusType iSCSINameStringProfileCheck(wchar_t *name); 160 boolean_t isNaturalNumber(char *numberStr, uint32_t upperBound); 161 static int parseAddress(char *address_port_str, uint16_t defaultPort, 162 char *address_str, size_t address_str_len, 163 uint16_t *port, boolean_t *isIpv6); 164 int parseTarget(char *targetStr, 165 wchar_t *targetNameStr, 166 size_t targetNameStrLen, 167 boolean_t *targetAddressSpecified, 168 wchar_t *targetAddressStr, 169 size_t targetAddressStrLen, 170 uint16_t *port, 171 boolean_t *tpgtSpecified, 172 uint16_t *tpgt, 173 boolean_t *isIpv6); 174 static int chkConnLoginMaxPollingLoginDelay(IMA_OID oid, 175 int key, int uintValue); 176 177 /* subcommand functions */ 178 static int addFunc(int, char **, int, cmdOptions_t *, void *, int *); 179 static int listFunc(int, char **, int, cmdOptions_t *, void *, int *); 180 static int modifyFunc(int, char **, int, cmdOptions_t *, void *, int *); 181 static int removeFunc(int, char **, int, cmdOptions_t *, void *, int *); 182 183 /* helper functions */ 184 static char *getExecBasename(char *); 185 static int getNodeProps(IMA_NODE_PROPERTIES *); 186 static int getSecret(char *, int *, int, int); 187 static int getTargetAddress(int, char *, IMA_TARGET_ADDRESS *); 188 static int printLoginParameters(char *, IMA_OID, int); 189 static void printDiscoveryMethod(char *, IMA_UINT32); 190 static void printTargetLuns(IMA_OID_LIST *); 191 static void printSendTargets(SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *); 192 static void printDigestAlgorithm(SUN_IMA_DIGEST_ALGORITHM_VALUE *, int); 193 static int setLoginParameter(IMA_OID, int, char *); 194 static int setLoginParameters(IMA_OID, char *); 195 static int setTunableParameters(IMA_OID, char *); 196 static void printLibError(IMA_STATUS); 197 /* LINTED E_STATIC_UNUSED */ 198 static int sunPluginChk(IMA_OID, boolean_t *); 199 static int sunInitiatorFind(IMA_OID *); 200 static int getAuthMethodValue(char *, IMA_AUTHMETHOD *); 201 static int getLoginParam(char *); 202 static int getTunableParam(char *); 203 static void iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status); 204 static int modifyIndividualTargetParam(cmdOptions_t *optionList, 205 IMA_OID targetOid, int *); 206 static void listCHAPName(IMA_OID oid); 207 static int printConfiguredSessions(IMA_OID); 208 static int printTunableParameters(IMA_OID oid); 209 210 /* object functions per subcommand */ 211 static int addAddress(int, int, char *[], int *); 212 static int addStaticConfig(int, char *[], int *); 213 static int listDiscovery(int *); 214 static int listDiscoveryAddress(int, char *[], cmdOptions_t *, int *); 215 static int listISNSServerAddress(int, char *[], cmdOptions_t *, int *); 216 static int listNode(int *); 217 static int listStaticConfig(int, char *[], int *); 218 static int listTarget(int, char *[], cmdOptions_t *, int *); 219 static int listTargetParam(int, char *[], cmdOptions_t *, int *); 220 static int modifyDiscovery(cmdOptions_t *, int *); 221 static int modifyNodeAuthMethod(IMA_OID, char *, int *); 222 static int modifyNodeAuthParam(IMA_OID oid, int, char *, int *); 223 static int modifyNodeRadiusConfig(IMA_OID, char *, int *); 224 static int modifyNodeRadiusAccess(IMA_OID, char *, int *); 225 static int modifyNodeRadiusSharedSecret(IMA_OID, int *); 226 static int modifyNode(cmdOptions_t *, int *); 227 static int modifyTargetAuthMethod(IMA_OID, char *, int *); 228 static int modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *); 229 static int modifyTargetParam(cmdOptions_t *, char *, int *); 230 static int removeAddress(int, int, char *[], int *); 231 static int removeStaticConfig(int, char *[], int *); 232 static int removeTargetParam(int, char *[], int *); 233 static int modifyTargetBidirAuthFlag(IMA_OID, char *, int *); 234 static int modifyConfiguredSessions(IMA_OID targetOid, char *optarg); 235 236 /* LINTED E_STATIC_UNUSED */ 237 static IMA_STATUS getISCSINodeParameter(int paramType, 238 IMA_OID *oid, 239 void *pProps, 240 uint32_t paramIndex); 241 /* LINTED E_STATIC_UNUSED */ 242 static IMA_STATUS setISCSINodeParameter(int paramType, 243 IMA_OID *oid, 244 void *pProps, 245 uint32_t paramIndex); 246 /* LINTED E_STATIC_UNUSED */ 247 static IMA_STATUS getDigest(IMA_OID oid, int ioctlCmd, 248 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm); 249 250 IMA_STATUS getNegotiatedDigest(int digestType, 251 SUN_IMA_DIGEST_ALGORITHM_VALUE *algorithm, 252 SUN_IMA_CONN_PROPERTIES *connProps); 253 254 /* globals */ 255 static char *cmdName; 256 257 /* 258 * Available option letters: 259 * 260 * bcefgijklmnoquwxyz 261 * 262 * DEFGHIJKLMOQUVWXYZ 263 */ 264 265 /* 266 * Add new options here 267 */ 268 optionTbl_t longOptions[] = { 269 {"static", required_arg, 's', OPTIONSTRING4}, 270 {"sendtargets", required_arg, 't', OPTIONSTRING4}, 271 {"iSNS", required_arg, 'i', OPTIONSTRING4}, 272 {"headerdigest", required_arg, 'h', OPTIONSTRING6}, 273 {"datadigest", required_arg, 'd', OPTIONSTRING6}, 274 {"login-param", required_arg, 'p', OPTIONSTRING5}, 275 {"authentication", required_arg, 'a', "CHAP|none"}, 276 {"bi-directional-authentication", required_arg, 'B', OPTIONSTRING4}, 277 {"CHAP-secret", no_arg, 'C', NULL}, 278 {"CHAP-name", required_arg, 'H', OPTIONSTRING7}, 279 {"node-name", required_arg, 'N', OPTIONSTRING2}, 280 {"node-alias", required_arg, 'A', OPTIONSTRING3}, 281 {"radius-server", required_arg, 'r', OPTIONVAL4}, 282 {"radius-access", required_arg, 'R', OPTIONSTRING4}, 283 {"radius-shared-secret", no_arg, 'P', NULL}, 284 {"verbose", no_arg, 'v', NULL}, 285 {"scsi-target", no_arg, 'S', NULL}, 286 {"configured-sessions", required_arg, 'c', OPTIONSTRING8}, 287 {"tunable-param", required_arg, 'T', OPTIONSTRING9}, 288 {NULL, 0, 0, 0} 289 }; 290 291 parameterTbl_t loginParams[] = { 292 {"dataseqinorder", DATA_SEQ_IN_ORDER}, 293 {"defaulttime2retain", DEFAULT_TIME_2_RETAIN}, 294 {"defaulttime2wait", DEFAULT_TIME_2_WAIT}, 295 {"firstburstlength", FIRST_BURST_LENGTH}, 296 {"immediatedata", IMMEDIATE_DATA}, 297 {"initialr2t", INITIAL_R2T}, 298 {"maxburstlength", MAX_BURST_LENGTH}, 299 {"datapduinorder", DATA_PDU_IN_ORDER}, 300 {"maxoutstandingr2t", MAX_OUTSTANDING_R2T}, 301 {"maxrecvdataseglen", MAX_RECV_DATA_SEG_LEN}, 302 {"maxconnections", MAX_CONNECTIONS}, 303 {"errorrecoverylevel", ERROR_RECOVERY_LEVEL}, 304 {NULL, 0} 305 }; 306 307 parameterTbl_t tunableParams[] = { 308 {"recv-login-rsp-timeout", RECV_LOGIN_RSP_TIMEOUT}, 309 {"conn-login-max", CONN_LOGIN_MAX}, 310 {"polling-login-delay", POLLING_LOGIN_DELAY}, 311 {NULL, 0} 312 }; 313 314 /* 315 * Add new subcommands here 316 */ 317 subcommand_t subcommands[] = { 318 {"add", ADD, addFunc}, 319 {"list", LIST, listFunc}, 320 {"modify", MODIFY, modifyFunc}, 321 {"remove", REMOVE, removeFunc}, 322 {NULL, 0, NULL} 323 }; 324 325 /* 326 * Add objects here 327 */ 328 object_t objects[] = { 329 {"discovery", DISCOVERY}, 330 {"discovery-address", DISCOVERY_ADDRESS}, 331 {"isns-server", ISNS_SERVER_ADDRESS}, 332 {"initiator-node", NODE}, 333 {"static-config", STATIC_CONFIG}, 334 {"target", TARGET}, 335 {"target-param", TARGET_PARAM}, 336 {NULL, 0} 337 }; 338 339 /* 340 * Rules for subcommands and objects 341 */ 342 objectRules_t objectRules[] = { 343 {TARGET, 0, LIST, 0, ADD|REMOVE|MODIFY, LIST, 344 "target-name"}, 345 {TARGET_PARAM, MODIFY|REMOVE, LIST, 0, ADD, MODIFY, 346 "target-name"}, 347 {DISCOVERY, 0, 0, LIST|MODIFY, ADD|REMOVE, 0, NULL}, 348 {NODE, 0, 0, MODIFY|LIST, ADD|REMOVE, 0, NULL}, 349 {STATIC_CONFIG, ADD|REMOVE, LIST, 0, MODIFY, ADD|REMOVE|LIST, 350 "target-name,target-address[:port-number][,tpgt]"}, 351 {DISCOVERY_ADDRESS, ADD|REMOVE, LIST, 0, MODIFY, 352 ADD|REMOVE|LIST, "IP-address[:port-number]"}, 353 {ISNS_SERVER_ADDRESS, ADD|REMOVE, LIST, 0, MODIFY, 354 ADD|REMOVE|LIST, "IP-address[:port-number]"}, 355 {0, 0, 0, 0, 0, NULL} 356 }; 357 358 /* 359 * list of objects, subcommands, valid short options, required flag and 360 * exclusive option string 361 * 362 * If it's not here, there are no options for that object. 363 */ 364 optionRules_t optionRules[] = { 365 {DISCOVERY, MODIFY, "sti", B_TRUE, NULL}, 366 {DISCOVERY_ADDRESS, LIST, "v", B_FALSE, NULL}, 367 {ISNS_SERVER_ADDRESS, LIST, "v", B_FALSE, NULL}, 368 {TARGET, LIST, "vS", B_FALSE, NULL}, 369 {NODE, MODIFY, "NAhdCaRrPHcT", B_TRUE, "CP"}, 370 {TARGET_PARAM, MODIFY, "ahdBCpcHT", B_TRUE, "C"}, 371 {TARGET_PARAM, LIST, "v", B_FALSE, NULL}, 372 {0, 0, 0, 0, 0} 373 }; 374 375 376 static boolean_t 377 targetNamesEqual(wchar_t *name1, wchar_t *name2) 378 { 379 int i; 380 wchar_t wchar1, wchar2; 381 382 if (name1 == NULL || name2 == NULL) { 383 return (B_FALSE); 384 } 385 386 if (wcslen(name1) != wcslen(name2)) { 387 return (B_FALSE); 388 } 389 390 /* 391 * Convert names to lower case and compare 392 */ 393 for (i = 0; i < wcslen(name1); i++) { 394 wchar1 = towctrans((wint_t)name1[i], wctrans("tolower")); 395 wchar2 = towctrans((wint_t)name2[i], wctrans("tolower")); 396 397 if (wchar1 != wchar2) { 398 return (B_FALSE); 399 } 400 } 401 402 return (B_TRUE); 403 } 404 405 static boolean_t 406 ipAddressesEqual(IMA_TARGET_ADDRESS addr1, IMA_TARGET_ADDRESS addr2) 407 { 408 #define IPV4_ADDR_BYTES 4 409 #define IPV6_ADDR_BYTES 16 410 411 int compSize; 412 413 if (addr1.hostnameIpAddress.id.ipAddress.ipv4Address != 414 addr2.hostnameIpAddress.id.ipAddress.ipv4Address) { 415 return (B_FALSE); 416 } 417 418 compSize = IPV6_ADDR_BYTES; 419 if (addr1.hostnameIpAddress.id.ipAddress.ipv4Address) { 420 compSize = IPV4_ADDR_BYTES; 421 } 422 423 if (bcmp(addr1.hostnameIpAddress.id.ipAddress.ipAddress, 424 addr2.hostnameIpAddress.id.ipAddress.ipAddress, compSize) == 0) { 425 return (B_TRUE); 426 } 427 428 return (B_FALSE); 429 } 430 431 static int 432 getLoginParam(char *arg) 433 { 434 parameterTbl_t *paramp; 435 int len; 436 437 for (paramp = loginParams; paramp->name; paramp++) { 438 len = strlen(arg); 439 if (len == strlen(paramp->name) && 440 strncasecmp(arg, paramp->name, len) == 0) { 441 return (paramp->val); 442 } 443 } 444 return (-1); 445 } 446 447 static int 448 getTunableParam(char *arg) 449 { 450 parameterTbl_t *paramp; 451 int len; 452 453 for (paramp = tunableParams; paramp->name != NULL; paramp++) { 454 len = strlen(arg); 455 if (len == strlen(paramp->name) && 456 strncasecmp(arg, paramp->name, len) == 0) { 457 return (paramp->val); 458 } 459 } 460 return (-1); 461 } 462 463 static void 464 printLibError(IMA_STATUS status) 465 { 466 char *errorString; 467 switch (status) { 468 case IMA_ERROR_NOT_SUPPORTED: 469 errorString = 470 gettext("Operation currently not supported"); 471 break; 472 case IMA_ERROR_INSUFFICIENT_MEMORY: 473 errorString = gettext("Insufficient memory"); 474 break; 475 case IMA_ERROR_UNEXPECTED_OS_ERROR: 476 errorString = gettext("unexpected OS error"); 477 break; 478 case IMA_ERROR_UNKNOWN_ERROR: 479 errorString = gettext("Unknown error"); 480 break; 481 case IMA_ERROR_LU_IN_USE: 482 errorString = gettext("Logical unit in use"); 483 break; 484 case IMA_ERROR_INVALID_PARAMETER: 485 errorString = gettext("Invalid parameter specified"); 486 break; 487 case IMA_ERROR_INVALID_OBJECT_TYPE: 488 errorString = 489 gettext("Internal library error: Invalid oid type specified"); 490 break; 491 case IMA_ERROR_INCORRECT_OBJECT_TYPE: 492 errorString = 493 gettext("Internal library error: Incorrect oid type specified"); 494 break; 495 case IMA_ERROR_OBJECT_NOT_FOUND: 496 errorString = gettext("Internal library error: Oid not found"); 497 break; 498 case IMA_ERROR_NAME_TOO_LONG: 499 errorString = gettext("Name too long"); 500 break; 501 default: 502 errorString = gettext("Unknown error"); 503 } 504 (void) fprintf(stderr, "%s: %s\n", cmdName, errorString); 505 } 506 507 /* 508 * input: 509 * execFullName - exec name of program (argv[0]) 510 * 511 * Returns: 512 * command name portion of execFullName 513 */ 514 static char * 515 getExecBasename(char *execFullname) 516 { 517 char *lastSlash, *execBasename; 518 519 /* guard against '/' at end of command invocation */ 520 for (;;) { 521 lastSlash = strrchr(execFullname, '/'); 522 if (lastSlash == NULL) { 523 execBasename = execFullname; 524 break; 525 } else { 526 execBasename = lastSlash + 1; 527 if (*execBasename == '\0') { 528 *lastSlash = '\0'; 529 continue; 530 } 531 break; 532 } 533 } 534 return (execBasename); 535 } 536 537 538 /* 539 * input: 540 * nodeProps - pointer to caller allocated IMA_NODE_PROPERTIES 541 * 542 * returns: 543 * zero on success 544 * non-zero otherwise 545 */ 546 static int 547 getNodeProps(IMA_NODE_PROPERTIES *nodeProps) 548 { 549 IMA_OID sharedNodeOid; 550 551 IMA_STATUS status = IMA_GetSharedNodeOid(&sharedNodeOid); 552 if (!(IMA_SUCCESS(status))) { 553 printLibError(status); 554 return (INF_ERROR); 555 } 556 557 status = IMA_GetNodeProperties(sharedNodeOid, nodeProps); 558 if (!IMA_SUCCESS(status)) { 559 printLibError(status); 560 return (INF_ERROR); 561 } 562 563 return (0); 564 } 565 566 /* 567 * sunInitiatorFind 568 * Purpose: 569 * Finds the Sun iSCSI initiator (LHBA). This CLI currently supports only 570 * one initiator. 571 * 572 * output: 573 * oid of initiator 574 * 575 * Returns: 576 * zero on success with initiator found 577 * > 0 on success with no initiator found 578 * < 0 on failure 579 */ 580 static int 581 sunInitiatorFind(IMA_OID *oid) 582 { 583 IMA_OID_LIST *lhbaList = NULL; 584 585 IMA_STATUS status = IMA_GetLhbaOidList(&lhbaList); 586 if (!IMA_SUCCESS(status)) { 587 printLibError(status); 588 return (-1); 589 } 590 591 if ((lhbaList == NULL) || (lhbaList->oidCount == 0)) { 592 printLibError(IMA_ERROR_OBJECT_NOT_FOUND); 593 if (lhbaList != NULL) 594 (void) IMA_FreeMemory(lhbaList); 595 return (-1); 596 } 597 598 *oid = lhbaList->oids[0]; 599 (void) IMA_FreeMemory(lhbaList); 600 601 return (0); 602 } 603 604 /* 605 * input: 606 * wcInput - wide character string containing discovery address 607 * output: 608 * address - IMA_TARGET_ADDRESS structure containing valid 609 * discovery address 610 * returns: 611 * zero on success 612 * non-zero on failure 613 */ 614 615 static int 616 getTargetAddress(int addrType, char *ipStr, IMA_TARGET_ADDRESS *address) 617 { 618 char cCol = ':'; 619 char cBracketL = '['; /* Open Bracket '[' */ 620 char cBracketR = ']'; /* Close Bracket ']' */ 621 char *colPos; 622 char *startPos; 623 unsigned long inputPort; 624 int addressType = AF_INET; 625 char *tmpStrPtr, tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 626 int rval; 627 628 /* Check if this is a ipv6 address */ 629 if (ipStr[0] == cBracketL) { 630 addressType = AF_INET6; 631 startPos = strchr(ipStr, cBracketR); 632 if (!startPos) { 633 (void) fprintf(stderr, "%s: %s: ']' %s\n", 634 cmdName, ipStr, gettext("missing")); 635 return (1); 636 } 637 (void) strlcpy(tmpStr, ipStr+1, startPos-ipStr); 638 address->hostnameIpAddress.id.ipAddress.ipv4Address = IMA_FALSE; 639 tmpStrPtr = tmpStr; 640 } else { 641 /* set start position to beginning of input object */ 642 addressType = AF_INET; 643 startPos = ipStr; 644 address->hostnameIpAddress.id.ipAddress.ipv4Address = IMA_TRUE; 645 tmpStrPtr = ipStr; 646 } 647 /* wcschr for ':'. If not there, use default port */ 648 colPos = strchr(startPos, cCol); 649 650 if (!colPos) { 651 if (addrType == DISCOVERY_ADDRESS) { 652 inputPort = DEFAULT_ISCSI_PORT; 653 } else if (addrType == ISNS_SERVER_ADDRESS) { 654 inputPort = ISNS_DEFAULT_SERVER_PORT; 655 } else { 656 *colPos = NULL; 657 } 658 } else { 659 *colPos = NULL; 660 } 661 662 rval = inet_pton(addressType, tmpStrPtr, 663 address->hostnameIpAddress.id.ipAddress.ipAddress); 664 /* inet_pton returns 1 on success */ 665 if (rval != 1) { 666 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, ipStr, 667 gettext("invalid IP address")); 668 return (1); 669 } 670 671 672 if (colPos) { 673 char *errchr; 674 675 colPos++; 676 if (*colPos == NULL) { 677 (void) fprintf(stderr, "%s: %s: %s\n", 678 cmdName, ipStr, 679 gettext("port number missing")); 680 return (1); 681 } 682 683 /* 684 * convert port string to unsigned value 685 * Note: Don't remove errno = 0 as you may get false failures. 686 */ 687 errno = 0; 688 inputPort = strtol(colPos, &errchr, 10); 689 if (errno != 0 || inputPort == 0 && errchr != NULL) { 690 (void) fprintf(stderr, "%s: %s:%s %s\n", 691 cmdName, ipStr, colPos, 692 gettext("port number invalid")); 693 return (1); 694 } 695 /* make sure it's in the range */ 696 if (inputPort > USHRT_MAX) { 697 (void) fprintf(stderr, "%s: %s: %s\n", 698 cmdName, ipStr, 699 gettext("port number out of range")); 700 return (1); 701 } 702 } 703 address->portNumber = inputPort; 704 705 return (0); 706 } 707 708 /* 709 * Print results of send targets command 710 */ 711 static void 712 printSendTargets(SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList) 713 { 714 char outBuf[INET6_ADDRSTRLEN]; 715 int inetSize; 716 int af; 717 int i; 718 719 for (i = 0; i < pList->keyCount; i++) { 720 if (pList->keys[i].address.ipAddress.ipv4Address == IMA_TRUE) { 721 af = AF_INET; 722 inetSize = INET_ADDRSTRLEN; 723 } else { 724 af = AF_INET6; 725 inetSize = INET6_ADDRSTRLEN; 726 } 727 (void) fprintf(stdout, gettext("\tTarget name: %ws\n"), 728 pList->keys[i].name); 729 (void) fprintf(stdout, "\t\t%s: %15s:%d", "Target address", 730 inet_ntop(af, &(pList->keys[i].address.ipAddress.ipAddress), 731 outBuf, inetSize), pList->keys[i].address.portNumber); 732 (void) fprintf(stdout, ", %d", pList->keys[i].tpgt); 733 (void) fprintf(stdout, "\n"); 734 } 735 } 736 737 738 /* 739 * Print all login parameters 740 */ 741 static int 742 printLoginParameters(char *prefix, IMA_OID oid, int printOption) 743 { 744 IMA_STATUS status; 745 IMA_BOOL_VALUE propBool; 746 IMA_MIN_MAX_VALUE propMinMax; 747 char longString[MAX_LONG_CHAR_LEN + 1]; 748 SUN_IMA_CONN_PROPERTIES *connProps = NULL; 749 IMA_OID_LIST *pConnList; 750 751 (void) memset(longString, 0, sizeof (longString)); 752 753 switch (printOption) { 754 case PRINT_CONFIGURED_PARAMS: 755 (void) fprintf(stdout, "%s%s:\n", 756 prefix, 757 gettext("Login Parameters (Default/Configured)")); 758 break; 759 case PRINT_NEGOTIATED_PARAMS: 760 (void) fprintf(stdout, "%s%s:\n", 761 prefix, 762 gettext("Login Parameters (Negotiated)")); 763 status = SUN_IMA_GetConnOidList( 764 &oid, 765 &pConnList); 766 767 if (!IMA_SUCCESS(status)) { 768 printLibError(status); 769 return (1); 770 } 771 772 status = SUN_IMA_GetConnProperties(&pConnList->oids[0], 773 &connProps); 774 propBool.currentValueValid = connProps->valuesValid; 775 propMinMax.currentValueValid = connProps->valuesValid; 776 break; 777 default: 778 return (1); 779 } 780 781 if (printOption == PRINT_NEGOTIATED_PARAMS) { 782 propBool.currentValue = connProps->dataSequenceInOrder; 783 } else { 784 status = IMA_GetDataSequenceInOrderProperties(oid, &propBool); 785 } 786 if (!IMA_SUCCESS(status)) { 787 printLibError(status); 788 (void) IMA_FreeMemory(connProps); 789 return (1); 790 } 791 (void) fprintf(stdout, "%s\t%s: ", prefix, 792 gettext("Data Sequence In Order")); 793 IMABOOLPRINT(propBool, printOption); 794 795 796 if (printOption == PRINT_NEGOTIATED_PARAMS) { 797 propBool.currentValue = connProps->dataPduInOrder; 798 } else { 799 status = IMA_GetDataPduInOrderProperties(oid, &propBool); 800 } 801 if (!IMA_SUCCESS(status)) { 802 printLibError(status); 803 (void) IMA_FreeMemory(connProps); 804 return (1); 805 } 806 (void) fprintf(stdout, "%s\t%s: ", prefix, 807 gettext("Data PDU In Order")); 808 IMABOOLPRINT(propBool, printOption); 809 810 811 if (printOption == PRINT_NEGOTIATED_PARAMS) { 812 propMinMax.currentValue = connProps->defaultTime2Retain; 813 } else { 814 status = IMA_GetDefaultTime2RetainProperties(oid, &propMinMax); 815 } 816 if (!IMA_SUCCESS(status)) { 817 printLibError(status); 818 (void) IMA_FreeMemory(connProps); 819 return (1); 820 } 821 (void) fprintf(stdout, "%s\t%s: ", prefix, 822 gettext("Default Time To Retain")); 823 IMAMINMAXPRINT(propMinMax, printOption); 824 825 826 if (printOption == PRINT_NEGOTIATED_PARAMS) { 827 propMinMax.currentValue = connProps->defaultTime2Wait; 828 } else { 829 status = IMA_GetDefaultTime2WaitProperties(oid, &propMinMax); 830 } 831 if (!IMA_SUCCESS(status)) { 832 printLibError(status); 833 (void) IMA_FreeMemory(connProps); 834 return (1); 835 } 836 (void) fprintf(stdout, "%s\t%s: ", prefix, 837 gettext("Default Time To Wait")); 838 IMAMINMAXPRINT(propMinMax, printOption); 839 840 841 if (printOption == PRINT_NEGOTIATED_PARAMS) { 842 propMinMax.currentValue = connProps->errorRecoveryLevel; 843 } else { 844 status = IMA_GetErrorRecoveryLevelProperties(oid, &propMinMax); 845 } 846 if (!IMA_SUCCESS(status)) { 847 printLibError(status); 848 (void) IMA_FreeMemory(connProps); 849 return (1); 850 } 851 (void) fprintf(stdout, "%s\t%s: ", prefix, 852 gettext("Error Recovery Level")); 853 IMAMINMAXPRINT(propMinMax, printOption); 854 855 856 if (printOption == PRINT_NEGOTIATED_PARAMS) { 857 propMinMax.currentValue = connProps->firstBurstLength; 858 } else { 859 status = IMA_GetFirstBurstLengthProperties(oid, 860 &propMinMax); 861 } 862 if (!IMA_SUCCESS(status)) { 863 printLibError(status); 864 (void) IMA_FreeMemory(connProps); 865 return (1); 866 } 867 (void) fprintf(stdout, "%s\t%s: ", 868 prefix, gettext("First Burst Length")); 869 IMAMINMAXPRINT(propMinMax, printOption); 870 871 872 if (printOption == PRINT_NEGOTIATED_PARAMS) { 873 propBool.currentValue = connProps->immediateData; 874 } else { 875 status = IMA_GetImmediateDataProperties(oid, &propBool); 876 } 877 if (!IMA_SUCCESS(status)) { 878 printLibError(status); 879 (void) IMA_FreeMemory(connProps); 880 return (1); 881 } 882 (void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Immediate Data")); 883 IMABOOLPRINT(propBool, printOption); 884 885 886 if (printOption == PRINT_NEGOTIATED_PARAMS) { 887 propBool.currentValue = connProps->initialR2T; 888 } else { 889 status = IMA_GetInitialR2TProperties(oid, &propBool); 890 } 891 if (!IMA_SUCCESS(status)) { 892 printLibError(status); 893 (void) IMA_FreeMemory(connProps); 894 return (1); 895 } 896 (void) fprintf(stdout, "%s\t%s: ", prefix, 897 gettext("Initial Ready To Transfer (R2T)")); 898 IMABOOLPRINT(propBool, printOption); 899 900 901 if (printOption == PRINT_NEGOTIATED_PARAMS) { 902 propMinMax.currentValue = connProps->maxBurstLength; 903 } else { 904 status = IMA_GetMaxBurstLengthProperties(oid, &propMinMax); 905 } 906 if (!IMA_SUCCESS(status)) { 907 printLibError(status); 908 (void) IMA_FreeMemory(connProps); 909 return (1); 910 } 911 (void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Max Burst Length")); 912 IMAMINMAXPRINT(propMinMax, printOption); 913 914 915 if (printOption == PRINT_NEGOTIATED_PARAMS) { 916 propMinMax.currentValue = connProps->maxOutstandingR2T; 917 } else { 918 status = IMA_GetMaxOutstandingR2TProperties(oid, &propMinMax); 919 } 920 if (!IMA_SUCCESS(status)) { 921 printLibError(status); 922 (void) IMA_FreeMemory(connProps); 923 return (1); 924 } 925 (void) fprintf(stdout, "%s\t%s: ", prefix, 926 gettext("Max Outstanding R2T")); 927 IMAMINMAXPRINT(propMinMax, printOption); 928 929 930 if (printOption == PRINT_NEGOTIATED_PARAMS) { 931 propMinMax.currentValue = connProps->maxRecvDataSegmentLength; 932 } else { 933 status = IMA_GetMaxRecvDataSegmentLengthProperties(oid, 934 &propMinMax); 935 } 936 if (!IMA_SUCCESS(status)) { 937 printLibError(status); 938 (void) IMA_FreeMemory(connProps); 939 return (1); 940 } 941 (void) fprintf(stdout, "%s\t%s: ", prefix, 942 gettext("Max Receive Data Segment Length")); 943 IMAMINMAXPRINT(propMinMax, printOption); 944 945 946 if (printOption == PRINT_NEGOTIATED_PARAMS) { 947 propMinMax.currentValue = connProps->maxConnections; 948 } else { 949 status = IMA_GetMaxConnectionsProperties(oid, &propMinMax); 950 } 951 if (!IMA_SUCCESS(status)) { 952 printLibError(status); 953 (void) IMA_FreeMemory(connProps); 954 return (1); 955 } 956 (void) fprintf(stdout, "%s\t%s: ", prefix, gettext("Max Connections")); 957 IMAMINMAXPRINT(propMinMax, printOption); 958 959 (void) IMA_FreeMemory(connProps); 960 return (0); 961 } 962 963 /* 964 * Print discovery information. 965 */ 966 static void 967 printDiscoveryMethod(char *prefix, IMA_UINT32 discoveryMethodFlags) 968 { 969 (void) fprintf(stdout, "%s%s: ", prefix, gettext("Discovery Method")); 970 if (discoveryMethodFlags == IMA_TARGET_DISCOVERY_METHOD_UNKNOWN) { 971 (void) fprintf(stdout, "%s\n", gettext("NA")); 972 } else { 973 if (!((discoveryMethodFlags & 974 IMA_TARGET_DISCOVERY_METHOD_STATIC) ^ 975 IMA_TARGET_DISCOVERY_METHOD_STATIC)) { 976 (void) fprintf(stdout, "%s ", gettext("Static")); 977 } 978 if (!((discoveryMethodFlags & 979 IMA_TARGET_DISCOVERY_METHOD_SENDTARGETS) ^ 980 IMA_TARGET_DISCOVERY_METHOD_SENDTARGETS)) { 981 (void) fprintf(stdout, "%s ", gettext("SendTargets")); 982 } 983 if (!((discoveryMethodFlags & 984 IMA_TARGET_DISCOVERY_METHOD_ISNS) ^ 985 IMA_TARGET_DISCOVERY_METHOD_ISNS)) { 986 (void) fprintf(stdout, "%s ", gettext("iSNS")); 987 } 988 (void) fprintf(stdout, "\n"); 989 } 990 } 991 992 /* 993 * printConnectionList - Prints the conection list provided 994 */ 995 static void 996 printConnectionList(char *prefix, IMA_OID_LIST *pConnList) 997 { 998 IMA_STATUS imaStatus; 999 int i; 1000 SUN_IMA_CONN_PROPERTIES *connProps; 1001 union { 1002 char ipv4[INET_ADDRSTRLEN+1]; 1003 char ipv6[INET6_ADDRSTRLEN+1]; 1004 } tmp; 1005 1006 for (i = 0; i < pConnList->oidCount; i++) { 1007 imaStatus = SUN_IMA_GetConnProperties(&pConnList->oids[i], 1008 &connProps); 1009 1010 if (imaStatus != IMA_STATUS_SUCCESS) { 1011 continue; 1012 } 1013 1014 (void) fprintf(stdout, "%sCID: %d\n", prefix, 1015 connProps->connectionID); 1016 1017 (void) memset(&tmp, 0, sizeof (tmp)); 1018 if (connProps->local.ipAddress.ipv4Address == IMA_TRUE) { 1019 if (inet_ntop(AF_INET, 1020 &connProps->local.ipAddress.ipAddress[0], 1021 &tmp.ipv4[0], 1022 INET_ADDRSTRLEN)) { 1023 (void) fprintf(stdout, 1024 "%s %s: %s:%u\n", 1025 prefix, 1026 gettext("IP address (Local)"), 1027 &tmp.ipv4[0], 1028 ntohs(connProps->local.portNumber)); 1029 } 1030 } else { 1031 if (inet_ntop(AF_INET6, 1032 &connProps->local.ipAddress.ipAddress[0], 1033 &tmp.ipv6[0], 1034 INET6_ADDRSTRLEN)) { 1035 (void) fprintf(stdout, 1036 "%s %s: [%s]:%u\n", 1037 prefix, 1038 gettext("IP address (Local)"), 1039 &tmp.ipv6[0], 1040 ntohs(connProps->local.portNumber)); 1041 } 1042 } 1043 if (connProps->peer.ipAddress.ipv4Address == IMA_TRUE) { 1044 if (inet_ntop(AF_INET, 1045 &connProps->peer.ipAddress.ipAddress[0], 1046 &tmp.ipv4[0], 1047 INET_ADDRSTRLEN)) { 1048 (void) fprintf(stdout, 1049 "%s %s: %s:%u\n", 1050 prefix, 1051 gettext("IP address (Peer)"), 1052 &tmp.ipv4[0], 1053 ntohs(connProps->peer.portNumber)); 1054 } 1055 } else { 1056 if (inet_ntop(AF_INET6, 1057 &connProps->peer.ipAddress.ipAddress[0], 1058 &tmp.ipv6[0], 1059 INET6_ADDRSTRLEN)) { 1060 (void) fprintf(stdout, 1061 "%s %s: [%s]:%u\n", 1062 prefix, 1063 gettext("IP address (Peer)"), 1064 &tmp.ipv6[0], 1065 ntohs(connProps->peer.portNumber)); 1066 } 1067 } 1068 1069 (void) IMA_FreeMemory(connProps); 1070 } 1071 } 1072 1073 /* 1074 * Set login parameters on a target or initiator 1075 */ 1076 static int 1077 setLoginParameter(IMA_OID oid, int optval, char *optarg) 1078 { 1079 IMA_STATUS status = IMA_STATUS_SUCCESS; 1080 IMA_UINT uintValue; 1081 IMA_BOOL boolValue; 1082 SUN_IMA_DIGEST_ALGORITHM digestAlgList[1]; 1083 IMA_MIN_MAX_VALUE propMinMax; 1084 char *endptr; 1085 1086 /* 1087 * for clarity, there are two switch statements 1088 * The first loads the variable and the second 1089 * calls the appropriate API 1090 */ 1091 switch (optval) { 1092 case DATA_SEQ_IN_ORDER: 1093 case IMMEDIATE_DATA: 1094 case INITIAL_R2T: 1095 case DATA_PDU_IN_ORDER: 1096 /* implement 'default'? */ 1097 if (strcasecmp(optarg, "yes") == 0) { 1098 boolValue = IMA_TRUE; 1099 } else if (strcasecmp(optarg, "no") == 0) { 1100 boolValue = IMA_FALSE; 1101 } else { 1102 (void) fprintf(stderr, "%s: %s - %s\n", 1103 cmdName, 1104 gettext("invalid option argument"), 1105 optarg); 1106 return (1); 1107 } 1108 break; 1109 case DEFAULT_TIME_2_RETAIN: 1110 case DEFAULT_TIME_2_WAIT: 1111 errno = 0; 1112 uintValue = strtoul(optarg, &endptr, 0); 1113 if (*endptr != '\0' || errno != 0) { 1114 (void) fprintf(stderr, "%s: %s - %s\n", 1115 cmdName, 1116 gettext("invalid option argument"), 1117 optarg); 1118 return (1); 1119 } 1120 if (uintValue > 3600) { 1121 (void) fprintf(stderr, "%s: %s\n", 1122 cmdName, 1123 gettext("value must be between 0 and 3600")); 1124 return (1); 1125 } 1126 break; 1127 case FIRST_BURST_LENGTH: 1128 case MAX_BURST_LENGTH: 1129 case MAX_RECV_DATA_SEG_LEN: 1130 errno = 0; 1131 /* implement 'default'? */ 1132 uintValue = strtoul(optarg, &endptr, 0); 1133 if (*endptr != '\0' || errno != 0) { 1134 (void) fprintf(stderr, "%s: %s - %s\n", 1135 cmdName, 1136 gettext("invalid option argument"), 1137 optarg); 1138 return (1); 1139 } 1140 if (uintValue < 512 || uintValue > 16777215) { 1141 (void) fprintf(stderr, "%s: %s\n", 1142 cmdName, 1143 gettext("value must be between 512 and 16777215")); 1144 return (1); 1145 } 1146 break; 1147 case MAX_OUTSTANDING_R2T: 1148 errno = 0; 1149 uintValue = strtoul(optarg, &endptr, 0); 1150 if (*endptr != '\0' || errno != 0) { 1151 (void) fprintf(stderr, "%s: %s - %s\n", 1152 cmdName, 1153 gettext("invalid option argument"), 1154 optarg); 1155 return (1); 1156 } 1157 if (uintValue < 1 || uintValue > 65535) { 1158 (void) fprintf(stderr, "%s: %s\n", 1159 cmdName, 1160 gettext("value must be between 1 and 65535")); 1161 return (1); 1162 } 1163 break; 1164 case HEADER_DIGEST: 1165 case DATA_DIGEST: 1166 if (strcasecmp(optarg, "none") == 0) { 1167 digestAlgList[0] = SUN_IMA_DIGEST_NONE; 1168 } else if (strcasecmp(optarg, "CRC32") == 0) { 1169 digestAlgList[0] = SUN_IMA_DIGEST_CRC32; 1170 } else { 1171 (void) fprintf(stderr, "%s: %s - %s\n", 1172 cmdName, 1173 gettext("invalid option argument"), 1174 optarg); 1175 return (1); 1176 } 1177 break; 1178 case MAX_CONNECTIONS: 1179 errno = 0; 1180 uintValue = strtoul(optarg, &endptr, 0); 1181 if (*endptr != '\0' || errno != 0) { 1182 (void) fprintf(stderr, "%s: %s - %s\n", 1183 cmdName, 1184 gettext("invalid option argument"), 1185 optarg); 1186 return (1); 1187 } 1188 if (uintValue < 1 || uintValue > 256) { 1189 (void) fprintf(stderr, "%s: %s\n", 1190 cmdName, 1191 gettext("value must be between 1 and 256")); 1192 return (1); 1193 } 1194 break; 1195 case ERROR_RECOVERY_LEVEL: 1196 errno = 0; 1197 uintValue = strtoul(optarg, &endptr, 0); 1198 if (*endptr != '\0' || errno != 0) { 1199 (void) fprintf(stderr, "%s: %s - %s\n", 1200 cmdName, 1201 gettext("invalid option argument"), 1202 optarg); 1203 return (1); 1204 } 1205 if (uintValue > 2) { 1206 (void) fprintf(stderr, "%s: %s\n", 1207 cmdName, 1208 gettext("value must be between 0 and 2")); 1209 return (1); 1210 } 1211 break; 1212 default: 1213 (void) fprintf(stderr, "%s: %c: %s\n", 1214 cmdName, optval, gettext("unknown option")); 1215 return (1); 1216 } 1217 1218 switch (optval) { 1219 case DATA_PDU_IN_ORDER: 1220 status = IMA_SetDataPduInOrder(oid, boolValue); 1221 break; 1222 case DATA_SEQ_IN_ORDER: 1223 status = IMA_SetDataSequenceInOrder(oid, boolValue); 1224 break; 1225 case DEFAULT_TIME_2_RETAIN: 1226 status = IMA_SetDefaultTime2Retain(oid, uintValue); 1227 break; 1228 case DEFAULT_TIME_2_WAIT: 1229 status = IMA_SetDefaultTime2Wait(oid, uintValue); 1230 break; 1231 case FIRST_BURST_LENGTH: 1232 status = IMA_SetFirstBurstLength(oid, uintValue); 1233 1234 /* 1235 * If this call fails check to see if it's because 1236 * the requested value is > than maxBurstLength 1237 */ 1238 if (!IMA_SUCCESS(status)) { 1239 status = IMA_GetMaxBurstLengthProperties(oid, 1240 &propMinMax); 1241 if (!IMA_SUCCESS(status)) { 1242 printLibError(status); 1243 return (1); 1244 } 1245 if (uintValue > propMinMax.currentValue) { 1246 (void) fprintf(stderr, 1247 "%s: %s\n", cmdName, 1248 gettext("firstBurstLength must " \ 1249 "be less than or equal to than " \ 1250 "maxBurstLength")); 1251 } 1252 return (1); 1253 } 1254 1255 break; 1256 case IMMEDIATE_DATA: 1257 status = IMA_SetImmediateData(oid, boolValue); 1258 break; 1259 case INITIAL_R2T: 1260 status = IMA_SetInitialR2T(oid, boolValue); 1261 break; 1262 case MAX_BURST_LENGTH: 1263 status = IMA_SetMaxBurstLength(oid, uintValue); 1264 /* 1265 * If this call fails check to see if it's because 1266 * the requested value is < than firstBurstLength 1267 */ 1268 if (!IMA_SUCCESS(status)) { 1269 status = IMA_GetFirstBurstLengthProperties(oid, 1270 &propMinMax); 1271 if (!IMA_SUCCESS(status)) { 1272 printLibError(status); 1273 return (1); 1274 } 1275 if (uintValue < propMinMax.currentValue) { 1276 (void) fprintf(stderr, "%s: %s\n", 1277 cmdName, 1278 gettext("maxBurstLength must be " \ 1279 "greater than or equal to " \ 1280 "firstBurstLength")); 1281 } 1282 return (1); 1283 } 1284 break; 1285 1286 case MAX_OUTSTANDING_R2T: 1287 status = IMA_SetMaxOutstandingR2T(oid, uintValue); 1288 break; 1289 case MAX_RECV_DATA_SEG_LEN: 1290 status = IMA_SetMaxRecvDataSegmentLength(oid, 1291 uintValue); 1292 break; 1293 case HEADER_DIGEST: 1294 status = SUN_IMA_SetHeaderDigest(oid, 1, 1295 &digestAlgList[0]); 1296 break; 1297 case DATA_DIGEST: 1298 status = SUN_IMA_SetDataDigest(oid, 1, 1299 &digestAlgList[0]); 1300 break; 1301 case MAX_CONNECTIONS: 1302 status = IMA_SetMaxConnections(oid, uintValue); 1303 break; 1304 case ERROR_RECOVERY_LEVEL: 1305 status = IMA_SetErrorRecoveryLevel(oid, uintValue); 1306 break; 1307 } 1308 if (!IMA_SUCCESS(status)) { 1309 printLibError(status); 1310 return (1); 1311 } 1312 return (0); 1313 } 1314 1315 static void 1316 printDigestAlgorithm(SUN_IMA_DIGEST_ALGORITHM_VALUE *digestAlgorithms, 1317 int printOption) 1318 { 1319 int i; 1320 1321 if (printOption == PRINT_CONFIGURED_PARAMS) { 1322 for (i = 0; i < digestAlgorithms->defaultAlgorithmCount; i++) { 1323 if (i > 0) { 1324 (void) fprintf(stdout, "|"); 1325 } 1326 switch (digestAlgorithms->defaultAlgorithms[i]) { 1327 case SUN_IMA_DIGEST_NONE: 1328 (void) fprintf(stdout, 1329 gettext("NONE")); 1330 break; 1331 case SUN_IMA_DIGEST_CRC32: 1332 (void) fprintf(stdout, 1333 gettext("CRC32")); 1334 break; 1335 default: 1336 (void) fprintf(stdout, 1337 gettext("Unknown")); 1338 break; 1339 } 1340 } 1341 (void) fprintf(stdout, "/"); 1342 if (digestAlgorithms->currentValid == IMA_TRUE) { 1343 for (i = 0; 1344 i < digestAlgorithms->currentAlgorithmCount; i++) { 1345 if (i > 0) { 1346 (void) fprintf(stdout, "|"); 1347 } 1348 switch (digestAlgorithms-> 1349 currentAlgorithms[i]) { 1350 case SUN_IMA_DIGEST_NONE: 1351 (void) fprintf(stdout, 1352 gettext("NONE")); 1353 break; 1354 case SUN_IMA_DIGEST_CRC32: 1355 (void) fprintf(stdout, 1356 gettext("CRC32")); 1357 break; 1358 default: 1359 (void) fprintf(stdout, 1360 gettext("Unknown")); 1361 break; 1362 } 1363 } 1364 } else { 1365 (void) fprintf(stdout, "-"); 1366 } 1367 (void) fprintf(stdout, "\n"); 1368 } else if (printOption == PRINT_NEGOTIATED_PARAMS) { 1369 1370 if (digestAlgorithms->negotiatedValid == IMA_TRUE) { 1371 for (i = 0; 1372 i < digestAlgorithms->negotiatedAlgorithmCount; 1373 i++) { 1374 if (i > 0) { 1375 (void) fprintf(stdout, "|"); 1376 } 1377 switch (digestAlgorithms-> 1378 negotiatedAlgorithms[i]) { 1379 case SUN_IMA_DIGEST_NONE: 1380 (void) fprintf(stdout, 1381 gettext("NONE")); 1382 break; 1383 case SUN_IMA_DIGEST_CRC32: 1384 (void) fprintf(stdout, 1385 gettext("CRC32")); 1386 break; 1387 default: 1388 (void) fprintf(stdout, 1389 gettext("Unknown")); 1390 break; 1391 } 1392 } 1393 } else { 1394 (void) fprintf(stdout, "-"); 1395 } 1396 (void) fprintf(stdout, "\n"); 1397 } 1398 } 1399 1400 static int 1401 setLoginParameters(IMA_OID oid, char *optarg) 1402 { 1403 char keyp[MAXOPTARGLEN]; 1404 char valp[MAXOPTARGLEN]; 1405 int key; 1406 char *nameValueString, *indexp, *delim = NULL; 1407 1408 if ((nameValueString = strdup(optarg)) == NULL) { 1409 if (errno == ENOMEM) { 1410 (void) fprintf(stderr, "%s: %s\n", 1411 cmdName, strerror(errno)); 1412 } else { 1413 (void) fprintf(stderr, "%s: %s\n", cmdName, 1414 gettext("unknown error")); 1415 } 1416 return (1); 1417 } 1418 1419 indexp = nameValueString; 1420 1421 /* 1422 * Retrieve all login params from option argument 1423 * Syntax <key=value,...> 1424 */ 1425 while (indexp) { 1426 if (delim = strchr(indexp, ',')) { 1427 delim[0] = '\0'; 1428 } 1429 (void) memset(keyp, 0, sizeof (keyp)); 1430 (void) memset(valp, 0, sizeof (valp)); 1431 if (sscanf(indexp, gettext("%[^=]=%s"), keyp, valp) != 2) { 1432 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 1433 gettext("Unknown param"), indexp); 1434 if (nameValueString) { 1435 free(nameValueString); 1436 nameValueString = NULL; 1437 } 1438 return (1); 1439 } 1440 if ((key = getLoginParam(keyp)) == -1) { 1441 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 1442 gettext("Unknown key"), keyp); 1443 if (nameValueString) { 1444 free(nameValueString); 1445 nameValueString = NULL; 1446 } 1447 return (1); 1448 } 1449 if (setLoginParameter(oid, key, valp) != 0) { 1450 if (nameValueString) { 1451 free(nameValueString); 1452 nameValueString = NULL; 1453 } 1454 return (1); 1455 } 1456 if (delim) { 1457 indexp = delim + 1; 1458 } else { 1459 indexp = NULL; 1460 } 1461 } 1462 1463 if (nameValueString) { 1464 free(nameValueString); 1465 nameValueString = NULL; 1466 } 1467 return (0); 1468 } 1469 1470 /* 1471 * Print logical unit information for a specific target 1472 */ 1473 static void 1474 printTargetLuns(IMA_OID_LIST * lunList) 1475 { 1476 int j; 1477 IMA_STATUS status; 1478 SUN_IMA_LU_PROPERTIES lunProps; 1479 1480 for (j = 0; j < lunList->oidCount; j++) { 1481 status = SUN_IMA_GetLuProperties(lunList->oids[j], 1482 &lunProps); 1483 if (!IMA_SUCCESS(status)) { 1484 printLibError(status); 1485 return; 1486 } 1487 1488 if (lunProps.imaProps.osDeviceNameValid == IMA_TRUE) { 1489 (void) fprintf(stdout, "\tLUN: %lld\n", 1490 lunProps.imaProps.targetLun); 1491 (void) fprintf(stdout, "\t Vendor: %s\n", 1492 lunProps.vendorId); 1493 (void) fprintf(stdout, "\t Product: %s\n", 1494 lunProps.productId); 1495 (void) fprintf(stdout, 1496 gettext("\t OS Device Name: %ws\n"), 1497 lunProps.imaProps.osDeviceName); 1498 } 1499 } 1500 } 1501 1502 /* 1503 * Retrieve CHAP secret from input 1504 */ 1505 static int 1506 getSecret(char *secret, int *secretLen, int minSecretLen, int maxSecretLen) 1507 { 1508 char *chapSecret; 1509 1510 /* get password */ 1511 chapSecret = getpassphrase(gettext("Enter secret:")); 1512 1513 if (chapSecret == NULL) { 1514 (void) fprintf(stderr, "%s: %s\n", cmdName, 1515 gettext("Unable to get secret")); 1516 *secret = NULL; 1517 return (1); 1518 } 1519 1520 if (strlen(chapSecret) > maxSecretLen) { 1521 (void) fprintf(stderr, "%s: %s %d\n", cmdName, 1522 gettext("secret too long, maximum length is"), 1523 maxSecretLen); 1524 *secret = NULL; 1525 return (1); 1526 } 1527 1528 if (strlen(chapSecret) < minSecretLen) { 1529 (void) fprintf(stderr, "%s: %s %d\n", cmdName, 1530 gettext("secret too short, minimum length is"), 1531 minSecretLen); 1532 *secret = NULL; 1533 return (1); 1534 } 1535 1536 (void) strcpy(secret, chapSecret); 1537 1538 chapSecret = getpassphrase(gettext("Re-enter secret:")); 1539 1540 if (chapSecret == NULL) { 1541 (void) fprintf(stderr, "%s: %s\n", cmdName, 1542 gettext("Unable to get secret")); 1543 *secret = NULL; 1544 return (1); 1545 } 1546 1547 if (strcmp(secret, chapSecret) != 0) { 1548 (void) fprintf(stderr, "%s: %s\n", cmdName, 1549 gettext("secrets do not match, secret not changed")); 1550 *secret = NULL; 1551 return (1); 1552 } 1553 *secretLen = strlen(chapSecret); 1554 return (0); 1555 } 1556 1557 /* 1558 * Lists the discovery attributes 1559 */ 1560 static int 1561 listDiscovery(int *funcRet) 1562 { 1563 IMA_OID initiatorOid; 1564 IMA_DISCOVERY_PROPERTIES discProps; 1565 int ret; 1566 IMA_STATUS status; 1567 1568 assert(funcRet != NULL); 1569 1570 1571 /* Find Sun initiator */ 1572 ret = sunInitiatorFind(&initiatorOid); 1573 if (ret > 0) { 1574 (void) fprintf(stderr, "%s: %s\n", 1575 cmdName, gettext("no initiator found")); 1576 } 1577 1578 if (ret != 0) { 1579 return (ret); 1580 } 1581 1582 /* Get discovery attributes from IMA */ 1583 status = IMA_GetDiscoveryProperties(initiatorOid, &discProps); 1584 if (!IMA_SUCCESS(status)) { 1585 printLibError(status); 1586 *funcRet = 1; 1587 return (ret); 1588 } 1589 1590 1591 (void) fprintf(stdout, "%s:\n", "Discovery"); 1592 (void) fprintf(stdout, "\tStatic: %s\n", 1593 discProps.staticDiscoveryEnabled == IMA_TRUE ? \ 1594 gettext("enabled") : gettext("disabled")); 1595 (void) fprintf(stdout, "\tSend Targets: %s\n", 1596 discProps.sendTargetsDiscoveryEnabled == IMA_TRUE ? \ 1597 gettext("enabled") : gettext("disabled")); 1598 (void) fprintf(stdout, "\tiSNS: %s\n", 1599 discProps.iSnsDiscoveryEnabled == IMA_TRUE ? \ 1600 gettext("enabled") : gettext("disabled")); 1601 1602 return (0); 1603 } 1604 1605 /* 1606 * Print all initiator node attributes 1607 */ 1608 static int 1609 listNode(int *funcRet) 1610 { 1611 IMA_OID initiatorOid; 1612 IMA_NODE_PROPERTIES nodeProps; 1613 IMA_STATUS status; 1614 int ret; 1615 IMA_UINT maxEntries = MAX_AUTH_METHODS; 1616 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 1617 SUN_IMA_RADIUS_CONFIG radiusConfig; 1618 SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms; 1619 IMA_BOOL radiusAccess; 1620 1621 int i; 1622 1623 assert(funcRet != NULL); 1624 1625 ret = getNodeProps(&nodeProps); 1626 if (ret != 0) { 1627 return (ret); 1628 } 1629 1630 if (nodeProps.nameValid == IMA_FALSE) { 1631 return (INVALID_NODE_NAME); 1632 } 1633 1634 /* Find Sun initiator */ 1635 ret = sunInitiatorFind(&initiatorOid); 1636 if (ret > 0) { 1637 (void) fprintf(stderr, "%s: %s\n", 1638 cmdName, gettext("no initiator found")); 1639 } 1640 1641 if (ret != 0) { 1642 return (ret); 1643 } 1644 /* Begin output */ 1645 (void) fprintf(stdout, gettext("%s: %ws\n"), 1646 gettext("Initiator node name"), 1647 nodeProps.name); 1648 (void) fprintf(stdout, gettext("Initiator node alias: ")); 1649 if (nodeProps.aliasValid == IMA_TRUE) { 1650 (void) fprintf(stdout, gettext("%ws\n"), nodeProps.alias); 1651 } else { 1652 (void) fprintf(stdout, "%s\n", "-"); 1653 } 1654 (void) fprintf(stdout, "\t%s:\n", 1655 gettext("Login Parameters (Default/Configured)")); 1656 1657 /* Get Digest configuration */ 1658 status = SUN_IMA_GetHeaderDigest(initiatorOid, &digestAlgorithms); 1659 if (IMA_SUCCESS(status)) { 1660 (void) fprintf(stdout, "\t\t%s: ", gettext("Header Digest")); 1661 printDigestAlgorithm(&digestAlgorithms, 1662 PRINT_CONFIGURED_PARAMS); 1663 } else { 1664 printLibError(status); 1665 *funcRet = 1; 1666 return (ret); 1667 } 1668 1669 status = SUN_IMA_GetDataDigest(initiatorOid, &digestAlgorithms); 1670 if (IMA_SUCCESS(status)) { 1671 (void) fprintf(stdout, "\t\t%s: ", gettext("Data Digest")); 1672 printDigestAlgorithm(&digestAlgorithms, 1673 PRINT_CONFIGURED_PARAMS); 1674 } else { 1675 printLibError(status); 1676 *funcRet = 1; 1677 return (ret); 1678 } 1679 1680 /* Get authentication type for this lhba */ 1681 status = IMA_GetInUseInitiatorAuthMethods(initiatorOid, &maxEntries, 1682 &methodList[0]); 1683 (void) fprintf(stdout, "\t%s: ", gettext("Authentication Type")); 1684 if (!IMA_SUCCESS(status)) { 1685 /* No authentication method set - default is NONE */ 1686 (void) fprintf(stdout, gettext("NONE")); 1687 } else { 1688 for (i = 0; i < maxEntries; i++) { 1689 if (i > 0) { 1690 (void) fprintf(stdout, "|"); 1691 } 1692 switch (methodList[i]) { 1693 case IMA_AUTHMETHOD_NONE: 1694 (void) fprintf(stdout, gettext("NONE")); 1695 break; 1696 case IMA_AUTHMETHOD_CHAP: 1697 (void) fprintf(stdout, gettext("CHAP")); 1698 listCHAPName(initiatorOid); 1699 break; 1700 default: 1701 (void) fprintf(stdout, 1702 gettext("unknown type")); 1703 break; 1704 } 1705 } 1706 } 1707 (void) fprintf(stdout, "\n"); 1708 1709 1710 /* Get RADIUS configuration */ 1711 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 1712 (void) fprintf(stdout, "\t%s: ", gettext("RADIUS Server")); 1713 if (IMA_SUCCESS(status)) { 1714 if (strlen(radiusConfig.hostnameIpAddress) > 0) { 1715 (void) fprintf(stdout, "%s:%d", 1716 radiusConfig.hostnameIpAddress, 1717 radiusConfig.port); 1718 } else { 1719 (void) fprintf(stdout, "%s", gettext("NONE")); 1720 } 1721 } else { 1722 (void) fprintf(stdout, "%s", gettext("NONE")); 1723 } 1724 (void) fprintf(stdout, "\n"); 1725 1726 status = SUN_IMA_GetInitiatorRadiusAccess(initiatorOid, 1727 &radiusAccess); 1728 (void) fprintf(stdout, "\t%s: ", gettext("RADIUS Access")); 1729 if (IMA_SUCCESS(status)) { 1730 if (radiusAccess == IMA_TRUE) { 1731 (void) fprintf(stdout, "%s", gettext("enabled")); 1732 } else { 1733 (void) fprintf(stdout, "%s", gettext("disabled")); 1734 } 1735 } else if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 1736 (void) fprintf(stdout, "%s", gettext("disabled")); 1737 } else { 1738 (void) fprintf(stdout, "%s", gettext("unknown")); 1739 } 1740 (void) fprintf(stdout, "\n"); 1741 1742 /* print tunable parameters information. */ 1743 ret = printTunableParameters(initiatorOid); 1744 1745 /* print configured session information. */ 1746 ret = printConfiguredSessions(initiatorOid); 1747 1748 return (ret); 1749 } 1750 1751 /* 1752 * Print discovery addresses 1753 */ 1754 static int 1755 listDiscoveryAddress(int objectLen, char *objects[], cmdOptions_t *options, 1756 int *funcRet) 1757 { 1758 IMA_OID initiatorOid; 1759 SUN_IMA_DISC_ADDR_PROP_LIST *discoveryAddressPropertiesList; 1760 IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps; 1761 IMA_TARGET_ADDRESS address; 1762 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList; 1763 IMA_STATUS status; 1764 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 1765 int ret; 1766 boolean_t object = B_FALSE; 1767 int outerLoop; 1768 boolean_t found; 1769 boolean_t verbose = B_FALSE; 1770 int i, j; 1771 cmdOptions_t *optionList = options; 1772 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 1773 1774 assert(funcRet != NULL); 1775 1776 /* Find Sun initiator */ 1777 ret = sunInitiatorFind(&initiatorOid); 1778 if (ret > 0) { 1779 (void) fprintf(stderr, "%s: %s\n", 1780 cmdName, gettext("no initiator found")); 1781 } 1782 1783 if (ret != 0) { 1784 return (ret); 1785 } 1786 1787 for (; optionList->optval; optionList++) { 1788 switch (optionList->optval) { 1789 case 'v': 1790 verbose = B_TRUE; 1791 break; 1792 default: 1793 (void) fprintf(stderr, "%s: %c: %s\n", 1794 cmdName, optionList->optval, 1795 gettext("unknown option")); 1796 return (1); 1797 } 1798 } 1799 1800 /* 1801 * If there are multiple objects, execute outer 'for' loop that 1802 * many times for each target detail, otherwise, execute it only 1803 * once with summaries only 1804 */ 1805 if (objectLen > 0) { 1806 object = B_TRUE; 1807 outerLoop = objectLen; 1808 } else { 1809 object = B_FALSE; 1810 outerLoop = 1; 1811 } 1812 1813 status = SUN_IMA_GetDiscoveryAddressPropertiesList( 1814 &discoveryAddressPropertiesList); 1815 if (!IMA_SUCCESS(status)) { 1816 printLibError(status); 1817 *funcRet = 1; 1818 return (ret); 1819 } 1820 1821 for (i = 0; i < outerLoop; i++) { 1822 if (object) { 1823 /* initialize */ 1824 (void) memset(&wcInputObject[0], 0, 1825 sizeof (wcInputObject)); 1826 (void) memset(&address, 0, sizeof (address)); 1827 if (mbstowcs(wcInputObject, objects[i], 1828 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 1829 (void) fprintf(stderr, "%s: %s\n", 1830 cmdName, 1831 gettext("conversion error")); 1832 ret = 1; 1833 continue; 1834 } 1835 1836 /* 1837 * if one or more objects were input, 1838 * get the values 1839 */ 1840 if (getTargetAddress(DISCOVERY_ADDRESS, 1841 objects[i], &address) != 0) { 1842 ret = 1; 1843 continue; 1844 } 1845 } 1846 for (found = B_FALSE, j = 0; 1847 j < discoveryAddressPropertiesList->discAddrCount; 1848 j++) { 1849 discAddrProps = 1850 discoveryAddressPropertiesList->props[j]; 1851 1852 /* 1853 * Compare the discovery address with the input if 1854 * one was input 1855 */ 1856 if (object && 1857 ipAddressesEqual(discAddrProps.discoveryAddress, 1858 address) && (discAddrProps.discoveryAddress. 1859 portNumber == address.portNumber)) { 1860 found = B_TRUE; 1861 } 1862 1863 if (!object || found) { 1864 /* Print summary - always */ 1865 if (discAddrProps.discoveryAddress. 1866 hostnameIpAddress.id.ipAddress. 1867 ipv4Address) { 1868 (void) inet_ntop(AF_INET, discAddrProps. 1869 discoveryAddress.hostnameIpAddress. 1870 id.ipAddress.ipAddress, sAddr, 1871 sizeof (sAddr)); 1872 (void) fprintf(stdout, 1873 "Discovery Address: %s:%u\n", 1874 sAddr, discAddrProps. 1875 discoveryAddress.portNumber); 1876 } else { 1877 (void) inet_ntop(AF_INET6, 1878 discAddrProps. 1879 discoveryAddress.hostnameIpAddress. 1880 id.ipAddress.ipAddress, sAddr, 1881 sizeof (sAddr)); 1882 (void) fprintf(stdout, 1883 "DiscoveryAddress: [%s]:%u\n", 1884 sAddr, discAddrProps. 1885 discoveryAddress.portNumber); 1886 } 1887 } 1888 1889 if ((!object || found) && verbose) { 1890 IMA_NODE_PROPERTIES nodeProps; 1891 1892 if (getNodeProps(&nodeProps) != 0) { 1893 break; 1894 } 1895 1896 /* 1897 * Issue sendTargets only when an addr is 1898 * specified. 1899 */ 1900 status = SUN_IMA_SendTargets(nodeProps.name, 1901 discAddrProps.discoveryAddress, &pList); 1902 if (!IMA_SUCCESS(status)) { 1903 (void) fprintf(stderr, "%s\n", 1904 gettext("\tUnable to get "\ 1905 "targets.")); 1906 *funcRet = 1; 1907 continue; 1908 } 1909 printSendTargets(pList); 1910 } 1911 1912 if (found) { 1913 /* we found the discovery address - break */ 1914 break; 1915 } 1916 } 1917 /* 1918 * There was an object entered but we didn't 1919 * find it. 1920 */ 1921 if (object && !found) { 1922 (void) fprintf(stdout, "%s: %s\n", 1923 objects[i], gettext("not found")); 1924 } 1925 } 1926 return (ret); 1927 } 1928 1929 /* 1930 * Print ISNS Server addresses 1931 */ 1932 static int 1933 listISNSServerAddress(int objectLen, char *objects[], cmdOptions_t *options, 1934 int *funcRet) 1935 { 1936 IMA_OID initiatorOid; 1937 SUN_IMA_DISC_ADDR_PROP_LIST *discoveryAddressPropertiesList; 1938 IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps; 1939 IMA_TARGET_ADDRESS address; 1940 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList; 1941 IMA_STATUS status; 1942 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 1943 int ret; 1944 boolean_t object = B_FALSE; 1945 int outerLoop; 1946 boolean_t found; 1947 boolean_t showTarget = B_FALSE; 1948 int i, j; 1949 cmdOptions_t *optionList = options; 1950 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 1951 1952 assert(funcRet != NULL); 1953 1954 /* Find Sun initiator */ 1955 ret = sunInitiatorFind(&initiatorOid); 1956 if (ret > 0) { 1957 (void) fprintf(stderr, "%s: %s\n", 1958 cmdName, gettext("no initiator found")); 1959 } 1960 1961 if (ret != 0) { 1962 return (ret); 1963 } 1964 1965 for (; optionList->optval; optionList++) { 1966 switch (optionList->optval) { 1967 case 'v': 1968 showTarget = B_TRUE; 1969 break; 1970 default: 1971 (void) fprintf(stderr, "%s: %c: %s\n", 1972 cmdName, optionList->optval, 1973 gettext("unknown option")); 1974 return (1); 1975 } 1976 } 1977 1978 /* 1979 * If there are multiple objects, execute outer 'for' loop that 1980 * many times for each target detail, otherwise, execute it only 1981 * once with summaries only 1982 */ 1983 if (objectLen > 0) { 1984 object = B_TRUE; 1985 outerLoop = objectLen; 1986 } else { 1987 object = B_FALSE; 1988 outerLoop = 1; 1989 } 1990 1991 status = SUN_IMA_GetISNSServerAddressPropertiesList( 1992 &discoveryAddressPropertiesList); 1993 if (!IMA_SUCCESS(status)) { 1994 printLibError(status); 1995 *funcRet = 1; 1996 return (ret); 1997 } 1998 1999 for (i = 0; i < outerLoop; i++) { 2000 if (object) { 2001 /* initialize */ 2002 (void) memset(&wcInputObject[0], 0, 2003 sizeof (wcInputObject)); 2004 (void) memset(&address, 0, sizeof (address)); 2005 if (mbstowcs(wcInputObject, objects[i], 2006 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 2007 (void) fprintf(stderr, "%s: %s\n", 2008 cmdName, 2009 gettext("conversion error")); 2010 ret = 1; 2011 continue; 2012 } 2013 2014 /* 2015 * if one or more objects were input, 2016 * get the values 2017 */ 2018 if (getTargetAddress(ISNS_SERVER_ADDRESS, 2019 objects[i], &address) != 0) { 2020 ret = 1; 2021 continue; 2022 } 2023 } 2024 for (found = B_FALSE, j = 0; 2025 j < discoveryAddressPropertiesList->discAddrCount; 2026 j++) { 2027 discAddrProps = 2028 discoveryAddressPropertiesList->props[j]; 2029 2030 /* 2031 * Compare the discovery address with the input if 2032 * one was input 2033 */ 2034 if (object && 2035 ipAddressesEqual(discAddrProps.discoveryAddress, 2036 address) && 2037 (discAddrProps.discoveryAddress.portNumber == 2038 address.portNumber)) { 2039 found = B_TRUE; 2040 } 2041 2042 if (!object || found) { 2043 /* Print summary - always */ 2044 if (discAddrProps.discoveryAddress. 2045 hostnameIpAddress.id.ipAddress. 2046 ipv4Address) { 2047 (void) inet_ntop(AF_INET, discAddrProps. 2048 discoveryAddress.hostnameIpAddress. 2049 id.ipAddress.ipAddress, sAddr, 2050 sizeof (sAddr)); 2051 } else { 2052 (void) inet_ntop(AF_INET6, 2053 discAddrProps. 2054 discoveryAddress.hostnameIpAddress. 2055 id.ipAddress.ipAddress, sAddr, 2056 sizeof (sAddr)); 2057 } 2058 (void) fprintf(stdout, 2059 "iSNS Server IP Address: %s:%u\n", 2060 sAddr, 2061 discAddrProps.discoveryAddress.portNumber); 2062 } 2063 2064 if ((!object || found) && showTarget) { 2065 IMA_NODE_PROPERTIES nodeProps; 2066 2067 if (getNodeProps(&nodeProps) != 0) { 2068 break; 2069 } 2070 2071 /* 2072 * Issue sendTargets only when an addr is 2073 * specified. 2074 */ 2075 status = SUN_IMA_RetrieveISNSServerTargets( 2076 discAddrProps.discoveryAddress, 2077 &pList); 2078 if (!IMA_SUCCESS(status)) { 2079 /* 2080 * Check if the discovery mode is 2081 * disabled. 2082 */ 2083 if (status == 2084 IMA_ERROR_OBJECT_NOT_FOUND) { 2085 (void) fprintf(stderr, "%s\n", 2086 gettext("\tiSNS "\ 2087 "discovery "\ 2088 "mode "\ 2089 "disabled. "\ 2090 "No targets "\ 2091 "to report.")); 2092 2093 } else { 2094 (void) fprintf(stderr, "%s\n", 2095 gettext("\tUnable "\ 2096 "to get "\ 2097 "targets.")); 2098 } 2099 continue; 2100 } 2101 printSendTargets(pList); 2102 } 2103 2104 if (found) { 2105 /* we found the discovery address - break */ 2106 break; 2107 } 2108 } 2109 /* 2110 * There was an object entered but we didn't 2111 * find it. 2112 */ 2113 if (object && !found) { 2114 (void) fprintf(stdout, "%s: %s\n", 2115 objects[i], gettext("not found")); 2116 } 2117 } 2118 return (ret); 2119 } 2120 2121 /* 2122 * Print static configuration targets 2123 */ 2124 static int 2125 listStaticConfig(int operandLen, char *operand[], int *funcRet) 2126 { 2127 IMA_STATUS status; 2128 IMA_OID initiatorOid; 2129 IMA_OID_LIST *staticTargetList; 2130 SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps; 2131 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 2132 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2133 wchar_t wcCol; 2134 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2135 int ret; 2136 boolean_t object = B_FALSE; 2137 int outerLoop; 2138 boolean_t found; /* B_TRUE if a target name is found */ 2139 boolean_t matched; /* B_TRUE if a specific target is found */ 2140 boolean_t targetAddressSpecified = B_FALSE; 2141 boolean_t tpgtSpecified = B_FALSE; 2142 boolean_t isIpv6; 2143 int i, j; 2144 IMA_UINT16 port = 0; 2145 IMA_UINT16 tpgt = 0; 2146 char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2147 wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2148 2149 assert(funcRet != NULL); 2150 2151 /* Find Sun initiator */ 2152 ret = sunInitiatorFind(&initiatorOid); 2153 if (ret > 0) { 2154 (void) fprintf(stderr, "%s: %s\n", 2155 cmdName, gettext("no initiator found")); 2156 } 2157 2158 if (ret != 0) { 2159 return (ret); 2160 } 2161 2162 /* 2163 * If there are multiple objects, execute outer 'for' loop that 2164 * many times for each static config detail, otherwise, execute it only 2165 * once with summaries only 2166 */ 2167 if (operandLen > 0) { 2168 object = B_TRUE; 2169 outerLoop = operandLen; 2170 } else { 2171 object = B_FALSE; 2172 outerLoop = 1; 2173 } 2174 2175 /* convert ':' to wide char for wchar string search */ 2176 if (mbtowc(&wcCol, ":", sizeof (wcCol)) == -1) { 2177 (void) fprintf(stderr, "%s: %s\n", 2178 cmdName, gettext("conversion error")); 2179 return (1); 2180 } 2181 2182 status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid, 2183 &staticTargetList); 2184 if (!IMA_SUCCESS(status)) { 2185 printLibError(status); 2186 *funcRet = 1; 2187 return (ret); 2188 } 2189 2190 for (i = 0; i < outerLoop; i++) { 2191 if (object) { 2192 if (parseTarget(operand[i], 2193 &staticTargetName[0], 2194 MAX_ISCSI_NAME_LEN + 1, 2195 &targetAddressSpecified, 2196 &staticTargetAddress[0], 2197 SUN_IMA_IP_ADDRESS_PORT_LEN, 2198 &port, 2199 &tpgtSpecified, 2200 &tpgt, 2201 &isIpv6) != PARSE_TARGET_OK) { 2202 ret = 1; 2203 continue; 2204 } 2205 } 2206 2207 for (found = B_FALSE, j = 0; j < staticTargetList->oidCount; 2208 j++) { 2209 boolean_t isIpv6 = B_FALSE; 2210 IMA_UINT16 stpgt; 2211 IMA_BOOL defaultTpgt; 2212 2213 matched = B_FALSE; 2214 (void) memset(&staticTargetProps, 0, 2215 sizeof (staticTargetProps)); 2216 2217 status = SUN_IMA_GetStaticTargetProperties( 2218 staticTargetList->oids[j], &staticTargetProps); 2219 if (!IMA_SUCCESS(status)) { 2220 printLibError(status); 2221 (void) IMA_FreeMemory(staticTargetList); 2222 *funcRet = 1; 2223 return (ret); 2224 } 2225 2226 stpgt = staticTargetProps.staticTarget.targetAddress. 2227 tpgt; 2228 2229 defaultTpgt = staticTargetProps.staticTarget. 2230 targetAddress.defaultTpgt; 2231 2232 isIpv6 = !staticTargetProps.staticTarget.targetAddress. 2233 imaStruct.hostnameIpAddress.id.ipAddress. 2234 ipv4Address; 2235 2236 /* 2237 * Compare the static target name with the input if 2238 * one was input 2239 */ 2240 2241 if (object && 2242 (targetNamesEqual( 2243 staticTargetProps.staticTarget.targetName, 2244 staticTargetName) == B_TRUE)) { 2245 /* targetName found - found = B_TRUE */ 2246 found = B_TRUE; 2247 if (targetAddressSpecified == B_FALSE) { 2248 matched = B_TRUE; 2249 } else { 2250 2251 if (staticTargetProps.staticTarget. 2252 targetAddress.imaStruct. 2253 hostnameIpAddress.id.ipAddress. 2254 ipv4Address == IMA_TRUE) { 2255 (void) inet_ntop(AF_INET, 2256 staticTargetProps. 2257 staticTarget.targetAddress. 2258 imaStruct.hostnameIpAddress.id. 2259 ipAddress.ipAddress, tmpStr, 2260 sizeof (tmpStr)); 2261 } else { 2262 (void) inet_ntop(AF_INET6, 2263 staticTargetProps. 2264 staticTarget.targetAddress. 2265 imaStruct.hostnameIpAddress.id. 2266 ipAddress.ipAddress, tmpStr, 2267 sizeof (tmpStr)); 2268 } 2269 2270 if (mbstowcs(tmpTargetAddress, tmpStr, 2271 SUN_IMA_IP_ADDRESS_PORT_LEN) == 2272 (size_t)-1) { 2273 (void) fprintf(stderr, "%s: %s\n", 2274 cmdName, 2275 gettext("conversion error")); 2276 ret = 1; 2277 continue; 2278 } 2279 2280 if (wcsncmp(tmpTargetAddress, 2281 staticTargetAddress, 2282 SUN_IMA_IP_ADDRESS_PORT_LEN) 2283 == 0 && 2284 staticTargetProps. 2285 staticTarget.targetAddress. 2286 imaStruct.portNumber == port) { 2287 /* 2288 * Since an object is 2289 * specified, it should also 2290 * have a tpgt specified. If 2291 * not, that means the object 2292 * specified is associated with 2293 * the default tpgt. In 2294 * either case, a tpgt 2295 * comparison should be done 2296 * before claiming that a 2297 * match is found. 2298 */ 2299 if ((tpgt == stpgt && 2300 tpgtSpecified == B_TRUE && 2301 defaultTpgt == IMA_FALSE) || 2302 (tpgt == stpgt && 2303 tpgtSpecified == B_FALSE && 2304 defaultTpgt == IMA_TRUE)) { 2305 matched = B_TRUE; 2306 } 2307 } 2308 2309 } 2310 } 2311 2312 if (!object || matched) { 2313 /* print summary - always */ 2314 (void) fprintf(stdout, gettext("%s: %ws,"), 2315 "Static Configuration Target", 2316 staticTargetProps.staticTarget.targetName); 2317 2318 if (isIpv6 == B_FALSE) { 2319 (void) inet_ntop(AF_INET, 2320 staticTargetProps. 2321 staticTarget.targetAddress. 2322 imaStruct.hostnameIpAddress.id. 2323 ipAddress.ipAddress, sAddr, 2324 sizeof (sAddr)); 2325 (void) fprintf(stdout, "%s:%d", 2326 sAddr, 2327 staticTargetProps.staticTarget. 2328 targetAddress.imaStruct.portNumber); 2329 } else { 2330 (void) inet_ntop(AF_INET6, 2331 staticTargetProps. 2332 staticTarget.targetAddress. 2333 imaStruct.hostnameIpAddress.id. 2334 ipAddress.ipAddress, sAddr, 2335 sizeof (sAddr)); 2336 (void) fprintf(stdout, "[%s]:%d", 2337 sAddr, 2338 staticTargetProps.staticTarget. 2339 targetAddress.imaStruct.portNumber); 2340 } 2341 2342 if (staticTargetProps.staticTarget. 2343 targetAddress. 2344 defaultTpgt == IMA_FALSE) { 2345 (void) fprintf(stdout, ",%d\n", 2346 staticTargetProps. 2347 staticTarget.targetAddress.tpgt); 2348 } else { 2349 (void) fprintf(stdout, "\n"); 2350 } 2351 } 2352 2353 } 2354 /* 2355 * No details to display, but if there were: 2356 * if (object && found)... 2357 * 2358 */ 2359 2360 /* 2361 * There was an object entered but we didn't 2362 * find it. 2363 */ 2364 if (object && !found) { 2365 (void) fprintf(stdout, "%s: %s\n", 2366 operand[i], gettext("not found")); 2367 ret = 1; /* DIY test fix */ 2368 } 2369 } 2370 return (ret); 2371 } 2372 2373 /* 2374 * Print targets 2375 */ 2376 /*ARGSUSED*/ 2377 static int 2378 listTarget(int objectLen, char *objects[], cmdOptions_t *options, int *funcRet) 2379 { 2380 IMA_OID initiatorOid; 2381 IMA_OID_LIST *targetList; 2382 IMA_OID_LIST *lunList; 2383 SUN_IMA_TARGET_PROPERTIES targetProps; 2384 IMA_STATUS status; 2385 IMA_OID_LIST *pConnList; 2386 SUN_IMA_CONN_PROPERTIES *connProps; 2387 2388 int ret; 2389 wchar_t targetName[MAX_ISCSI_NAME_LEN + 1]; 2390 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2391 int outerLoop; 2392 boolean_t found; 2393 boolean_t operandEntered = B_FALSE; 2394 boolean_t verbose = B_FALSE; 2395 boolean_t scsi_target = B_FALSE; 2396 boolean_t targetAddressSpecified = B_FALSE; 2397 boolean_t isIpv6 = B_FALSE; 2398 int i, j; 2399 cmdOptions_t *optionList = options; 2400 boolean_t tpgtSpecified = B_FALSE; 2401 IMA_UINT16 port = 0; 2402 uint16_t tpgt; 2403 2404 assert(funcRet != NULL); 2405 2406 /* Find Sun initiator */ 2407 ret = sunInitiatorFind(&initiatorOid); 2408 if (ret > 0) { 2409 (void) fprintf(stderr, "%s: %s\n", 2410 cmdName, gettext("no initiator found")); 2411 } 2412 2413 if (ret != 0) { 2414 return (ret); 2415 } 2416 2417 for (; optionList->optval; optionList++) { 2418 switch (optionList->optval) { 2419 case 'S': 2420 scsi_target = B_TRUE; 2421 break; 2422 case 'v': 2423 verbose = B_TRUE; 2424 break; 2425 default: 2426 (void) fprintf(stderr, "%s: %c: %s\n", 2427 cmdName, optionList->optval, 2428 gettext("unknown option")); 2429 return (1); 2430 } 2431 } 2432 2433 /* 2434 * If there are multiple objects, execute outer 'for' loop that 2435 * many times for each target detail, otherwise, execute it only 2436 * once with summaries only 2437 */ 2438 if (objectLen > 0) { 2439 operandEntered = B_TRUE; 2440 outerLoop = objectLen; 2441 } else { 2442 operandEntered = B_FALSE; 2443 outerLoop = 1; 2444 } 2445 2446 status = SUN_IMA_GetSessionOidList(initiatorOid, &targetList); 2447 if (!IMA_SUCCESS(status)) { 2448 printLibError(status); 2449 *funcRet = 1; 2450 return (ret); 2451 } 2452 2453 for (i = 0; i < outerLoop; i++) { 2454 2455 tpgtSpecified = B_FALSE; 2456 if (operandEntered) { 2457 if (parseTarget(objects[i], 2458 &targetName[0], 2459 MAX_ISCSI_NAME_LEN + 1, 2460 &targetAddressSpecified, 2461 &targetAddress[0], 2462 SUN_IMA_IP_ADDRESS_PORT_LEN, 2463 &port, 2464 &tpgtSpecified, 2465 &tpgt, 2466 &isIpv6) != PARSE_TARGET_OK) { 2467 ret = 1; 2468 continue; 2469 } 2470 } 2471 for (found = B_FALSE, j = 0; j < targetList->oidCount; j++) { 2472 status = SUN_IMA_GetTargetProperties( 2473 targetList->oids[j], 2474 &targetProps); 2475 if (!IMA_SUCCESS(status)) { 2476 printLibError(status); 2477 (void) IMA_FreeMemory(targetList); 2478 *funcRet = 1; 2479 return (ret); 2480 } 2481 2482 /* 2483 * Compare the target name with the input if 2484 * one was input, if they match, print the target's info 2485 * 2486 * if no target name was input, continue printing this 2487 * target 2488 */ 2489 if (operandEntered) { 2490 if (targetNamesEqual(targetProps.imaProps.name, 2491 targetName) == B_TRUE) { 2492 if (tpgtSpecified == B_TRUE) { 2493 if (targetProps. 2494 defaultTpgtConf == 2495 IMA_FALSE && 2496 targetProps. 2497 tpgtConf == tpgt) { 2498 found = B_TRUE; 2499 } else { 2500 /* 2501 * tpgt does not match, 2502 * move on to next 2503 * target 2504 */ 2505 continue; 2506 } 2507 } else { 2508 found = B_TRUE; 2509 } 2510 } else { 2511 /* 2512 * target name does not match, move on 2513 * to next target 2514 */ 2515 continue; 2516 } 2517 } 2518 2519 /* print summary - always */ 2520 (void) fprintf(stdout, gettext("%s: %ws\n"), 2521 gettext("Target"), targetProps.imaProps.name); 2522 2523 /* Alias */ 2524 (void) fprintf(stdout, "\t%s: ", gettext("Alias")); 2525 if (wslen(targetProps.imaProps.alias) > (size_t)0) { 2526 (void) fprintf(stdout, gettext("%ws\n"), 2527 targetProps.imaProps.alias); 2528 } else { 2529 (void) fprintf(stdout, "%s\n", "-"); 2530 } 2531 2532 if (targetProps.defaultTpgtNego != IMA_TRUE) { 2533 (void) fprintf(stdout, "%s%s: %d\n", 2534 "\t", gettext("TPGT"), 2535 targetProps.tpgtNego); 2536 } else if (targetProps.defaultTpgtConf != IMA_TRUE) { 2537 (void) fprintf(stdout, "%s%s: %d\n", 2538 "\t", gettext("TPGT"), 2539 targetProps.tpgtConf); 2540 } 2541 2542 (void) fprintf(stdout, 2543 "%s%s: %02x%02x%02x%02x%02x%02x\n", 2544 "\t", gettext("ISID"), 2545 targetProps.isid[0], targetProps.isid[1], 2546 targetProps.isid[2], targetProps.isid[3], 2547 targetProps.isid[4], targetProps.isid[5]); 2548 2549 pConnList = NULL; 2550 status = SUN_IMA_GetConnOidList( 2551 &targetList->oids[j], 2552 &pConnList); 2553 2554 if (!IMA_SUCCESS(status)) { 2555 printLibError(status); 2556 (void) IMA_FreeMemory(targetList); 2557 *funcRet = 1; 2558 return (ret); 2559 } 2560 2561 (void) fprintf(stdout, "%s%s: %lu\n", 2562 "\t", 2563 gettext("Connections"), 2564 pConnList->oidCount); 2565 2566 if (verbose) { 2567 SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms; 2568 2569 printConnectionList("\t\t", pConnList); 2570 printDiscoveryMethod( 2571 "\t\t ", 2572 targetProps.imaProps.discoveryMethodFlags); 2573 (void) printLoginParameters( 2574 "\t\t ", 2575 targetList->oids[j], 2576 PRINT_NEGOTIATED_PARAMS); 2577 2578 /* Get Digest configuration */ 2579 status = SUN_IMA_GetConnProperties( 2580 &pConnList->oids[0], &connProps); 2581 2582 (void) getNegotiatedDigest( 2583 ISCSI_LOGIN_PARAM_HEADER_DIGEST, 2584 &digestAlgorithms, connProps); 2585 2586 if (IMA_SUCCESS(status)) { 2587 (void) fprintf(stdout, "\t\t \t%s: ", 2588 gettext("Header Digest")); 2589 printDigestAlgorithm( 2590 &digestAlgorithms, 2591 PRINT_NEGOTIATED_PARAMS); 2592 } else { 2593 (void) IMA_FreeMemory(pConnList); 2594 (void) IMA_FreeMemory(targetList); 2595 printLibError(status); 2596 *funcRet = 1; 2597 return (ret); 2598 } 2599 2600 (void) getNegotiatedDigest( 2601 ISCSI_LOGIN_PARAM_DATA_DIGEST, 2602 &digestAlgorithms, connProps); 2603 2604 if (IMA_SUCCESS(status)) { 2605 (void) fprintf(stdout, "\t\t \t%s: ", 2606 gettext("Data Digest")); 2607 printDigestAlgorithm( 2608 &digestAlgorithms, 2609 PRINT_NEGOTIATED_PARAMS); 2610 } else { 2611 (void) IMA_FreeMemory(pConnList); 2612 (void) IMA_FreeMemory(targetList); 2613 printLibError(status); 2614 *funcRet = 1; 2615 return (ret); 2616 } 2617 2618 (void) fprintf(stdout, "\n"); 2619 } 2620 2621 if (scsi_target) { 2622 status = IMA_GetLuOidList( 2623 targetList->oids[j], 2624 &lunList); 2625 if (!IMA_SUCCESS(status)) { 2626 printLibError(status); 2627 (void) IMA_FreeMemory(targetList); 2628 *funcRet = 1; 2629 return (ret); 2630 } 2631 if (lunList->oidCount != 0) { 2632 printTargetLuns(lunList); 2633 } 2634 (void) fprintf(stdout, "\n"); 2635 (void) IMA_FreeMemory(lunList); 2636 } 2637 } 2638 /* 2639 * did we find the object 2640 */ 2641 2642 if (operandEntered && !found) { 2643 (void) fprintf(stdout, "%s: %s\n", 2644 objects[i], gettext("not found")); 2645 } 2646 } 2647 2648 (void) IMA_FreeMemory(targetList); 2649 return (ret); 2650 } 2651 2652 2653 /* 2654 * Print configured session information 2655 */ 2656 static int 2657 printConfiguredSessions(IMA_OID oid) 2658 { 2659 IMA_STATUS status; 2660 const char *rtn; 2661 SUN_IMA_CONFIG_SESSIONS *pConfigSessions; 2662 char address[MAX_ADDRESS_LEN]; 2663 int out; 2664 2665 /* Get configured session information */ 2666 status = SUN_IMA_GetConfigSessions(oid, &pConfigSessions); 2667 2668 if (IMA_SUCCESS(status)) { 2669 (void) fprintf(stdout, "\t%s: ", 2670 gettext("Configured Sessions")); 2671 if (pConfigSessions->bound == IMA_FALSE) { 2672 /* default binding */ 2673 (void) fprintf(stdout, "%lu\n", pConfigSessions->out); 2674 } else { 2675 /* hardcoded binding */ 2676 for (out = 0; 2677 out < pConfigSessions->out; out++) { 2678 if (pConfigSessions->bindings[out]. 2679 ipAddress.ipv4Address == IMA_TRUE) { 2680 rtn = inet_ntop(AF_INET, 2681 pConfigSessions->bindings[out]. 2682 ipAddress.ipAddress, address, 2683 MAX_ADDRESS_LEN); 2684 } else { 2685 rtn = inet_ntop(AF_INET6, 2686 pConfigSessions->bindings[out]. 2687 ipAddress.ipAddress, address, 2688 MAX_ADDRESS_LEN); 2689 } 2690 if (rtn != NULL) { 2691 (void) printf("%s ", address); 2692 } 2693 } 2694 (void) fprintf(stdout, "\n"); 2695 } 2696 } else { 2697 free(pConfigSessions); 2698 printLibError(status); 2699 return (1); 2700 } 2701 2702 free(pConfigSessions); 2703 return (0); 2704 } 2705 2706 /* 2707 * Print target parameters 2708 */ 2709 static int 2710 listTargetParam(int operandLen, char *operand[], cmdOptions_t *options, 2711 int *funcRet) 2712 { 2713 IMA_STATUS status; 2714 IMA_OID initiatorOid; 2715 IMA_OID_LIST *targetList; 2716 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 2717 SUN_IMA_TARGET_PROPERTIES targetProps; 2718 IMA_UINT maxEntries = MAX_AUTH_METHODS; 2719 IMA_BOOL bidirAuth; 2720 int ret; 2721 wchar_t targetName[MAX_ISCSI_NAME_LEN + 1]; 2722 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2723 boolean_t operandEntered = B_FALSE; 2724 boolean_t targetAddressSpecified = B_FALSE; 2725 boolean_t printObject = B_FALSE; 2726 boolean_t tpgtSpecified = B_FALSE; 2727 boolean_t isIpv6 = B_FALSE; 2728 int outerLoop; 2729 boolean_t found; 2730 int i, j; 2731 SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms; 2732 boolean_t verbose = B_FALSE; 2733 cmdOptions_t *optionList = options; 2734 IMA_UINT16 port = 0; 2735 IMA_UINT16 tpgt = 0; 2736 2737 assert(funcRet != NULL); 2738 2739 /* Find Sun initiator */ 2740 ret = sunInitiatorFind(&initiatorOid); 2741 if (ret > 0) { 2742 (void) fprintf(stderr, "%s: %s\n", 2743 cmdName, gettext("no initiator found")); 2744 } 2745 2746 if (ret != 0) { 2747 return (ret); 2748 } 2749 2750 for (; optionList->optval; optionList++) { 2751 switch (optionList->optval) { 2752 case 'v': 2753 verbose = B_TRUE; 2754 break; 2755 default: 2756 (void) fprintf(stderr, "%s: %c: %s\n", 2757 cmdName, optionList->optval, 2758 gettext("unknown option")); 2759 return (1); 2760 } 2761 } 2762 2763 /* 2764 * If there are multiple operands, execute outer 'for' loop that 2765 * many times to find each target parameter operand entered, otherwise, 2766 * execute it only once for all target parameters returned. 2767 */ 2768 if (operandLen > 0) { 2769 operandEntered = B_TRUE; 2770 outerLoop = operandLen; 2771 } else { 2772 operandEntered = B_FALSE; 2773 outerLoop = 1; 2774 } 2775 2776 /* 2777 * Ideally there should be an interface available for obtaining 2778 * the list of target-param objects. Since the driver currently 2779 * creates a target OID and the associated session structure when 2780 * a target-param object is created, we can leverage the target 2781 * OID list and use it to manage the target-param objects. When 2782 * we stop creating a session for target-param object in the 2783 * driver, we will switch to using a different interface to 2784 * obtain target-param objects. 2785 */ 2786 status = IMA_GetTargetOidList(initiatorOid, &targetList); 2787 if (!IMA_SUCCESS(status)) { 2788 printLibError(status); 2789 *funcRet = 1; 2790 return (ret); 2791 } 2792 2793 for (i = 0; i < outerLoop; i++) { 2794 if (operandEntered) { 2795 if (parseTarget(operand[i], 2796 &targetName[0], 2797 MAX_ISCSI_NAME_LEN + 1, 2798 &targetAddressSpecified, 2799 &targetAddress[0], 2800 SUN_IMA_IP_ADDRESS_PORT_LEN, 2801 &port, 2802 &tpgtSpecified, 2803 &tpgt, 2804 &isIpv6) != PARSE_TARGET_OK) { 2805 ret = 1; 2806 continue; 2807 } 2808 } 2809 for (j = 0; j < targetList->oidCount; j++) { 2810 found = B_FALSE; 2811 printObject = B_FALSE; 2812 status = SUN_IMA_GetTargetProperties( 2813 targetList->oids[j], 2814 &targetProps); 2815 if (!IMA_SUCCESS(status)) { 2816 printLibError(status); 2817 (void) IMA_FreeMemory(targetList); 2818 *funcRet = 1; 2819 return (ret); 2820 } 2821 2822 /* 2823 * Compare the target name with the input if 2824 * one was input 2825 */ 2826 if (operandEntered && 2827 (targetNamesEqual(targetProps.imaProps.name, 2828 targetName) == B_TRUE)) { 2829 /* 2830 * For now, regardless of whether a target 2831 * address is specified, we return B_TRUE 2832 * because IMA_TARGET_PROPERTIES does not 2833 * have a field for specifying address. 2834 */ 2835 found = B_TRUE; 2836 } 2837 2838 /* 2839 * if no operand was entered OR 2840 * an operand was entered and it was 2841 * found, we want to print 2842 */ 2843 if (!operandEntered || found) { 2844 printObject = B_TRUE; 2845 } 2846 2847 if (printObject) { 2848 (void) fprintf(stdout, gettext("%s: %ws\n"), 2849 gettext("Target"), 2850 targetProps.imaProps.name); 2851 2852 (void) fprintf(stdout, 2853 "\t%s: ", gettext("Alias")); 2854 if (wslen(targetProps.imaProps.alias) > 2855 (size_t)0) { 2856 (void) fprintf(stdout, 2857 gettext("%ws\n"), 2858 targetProps.imaProps.alias); 2859 } else { 2860 (void) fprintf(stdout, "%s\n", "-"); 2861 } 2862 } 2863 2864 if (printObject && verbose) { 2865 /* Get bidirectional authentication flag */ 2866 (void) fprintf(stdout, "\t%s: ", 2867 gettext("Bi-directional Authentication")); 2868 status = SUN_IMA_GetTargetBidirAuthFlag( 2869 targetList->oids[j], 2870 &bidirAuth); 2871 if (IMA_SUCCESS(status)) { 2872 if (bidirAuth == IMA_TRUE) { 2873 (void) fprintf(stdout, 2874 gettext("enabled")); 2875 } else { 2876 (void) fprintf(stdout, 2877 gettext("disabled")); 2878 } 2879 } else { 2880 (void) fprintf(stdout, 2881 gettext("disabled")); 2882 } 2883 (void) fprintf(stdout, "\n"); 2884 2885 /* Get authentication type for this target */ 2886 status = SUN_IMA_GetTargetAuthMethods( 2887 initiatorOid, 2888 targetList->oids[j], 2889 &maxEntries, 2890 &methodList[0]); 2891 (void) fprintf(stdout, "\t%s: ", 2892 gettext("Authentication Type")); 2893 if (!IMA_SUCCESS(status)) { 2894 /* 2895 * No authentication method define 2896 * NONE by default. 2897 */ 2898 (void) fprintf(stdout, gettext("NONE")); 2899 } else { 2900 for (i = 0; i < maxEntries; i++) { 2901 if (i > 0) { 2902 (void) fprintf(stdout, 2903 "|"); 2904 } 2905 switch (methodList[i]) { 2906 case IMA_AUTHMETHOD_NONE: 2907 (void) fprintf(stdout, 2908 gettext("NONE")); 2909 break; 2910 2911 case IMA_AUTHMETHOD_CHAP: 2912 (void) fprintf(stdout, 2913 gettext("CHAP")); 2914 listCHAPName( 2915 targetList-> 2916 oids[j]); 2917 break; 2918 2919 default: 2920 (void) fprintf(stdout, 2921 gettext( 2922 "unknown " 2923 "type")); 2924 break; 2925 } 2926 } 2927 } 2928 (void) fprintf(stdout, "\n"); 2929 if (printLoginParameters("\t", 2930 targetList->oids[j], 2931 PRINT_CONFIGURED_PARAMS) 2932 != 0) { 2933 (void) IMA_FreeMemory(targetList); 2934 *funcRet = 1; 2935 return (ret); 2936 } 2937 2938 /* Get Digest configuration */ 2939 status = SUN_IMA_GetHeaderDigest( 2940 targetList->oids[j], 2941 &digestAlgorithms); 2942 if (IMA_SUCCESS(status)) { 2943 (void) fprintf(stdout, "\t\t%s: ", 2944 gettext("Header Digest")); 2945 printDigestAlgorithm(&digestAlgorithms, 2946 PRINT_CONFIGURED_PARAMS); 2947 } else { 2948 printLibError(status); 2949 *funcRet = 1; 2950 return (ret); 2951 } 2952 2953 status = SUN_IMA_GetDataDigest( 2954 targetList->oids[j], 2955 &digestAlgorithms); 2956 if (IMA_SUCCESS(status)) { 2957 (void) fprintf(stdout, "\t\t%s: ", 2958 gettext("Data Digest")); 2959 printDigestAlgorithm(&digestAlgorithms, 2960 PRINT_CONFIGURED_PARAMS); 2961 } else { 2962 printLibError(status); 2963 *funcRet = 1; 2964 return (ret); 2965 } 2966 2967 /* print tunable parameters infomation */ 2968 if (printTunableParameters( 2969 targetList->oids[j]) != 0) { 2970 *funcRet = 1; 2971 return (ret); 2972 } 2973 2974 /* print configured session information */ 2975 if (printConfiguredSessions( 2976 targetList->oids[j]) != 0) { 2977 *funcRet = 1; 2978 return (ret); 2979 } 2980 2981 (void) fprintf(stdout, "\n"); 2982 } 2983 2984 if (found) { 2985 break; 2986 } 2987 } 2988 if (operandEntered && !found) { 2989 *funcRet = 1; /* DIY message fix */ 2990 (void) fprintf(stdout, "%s: %s\n", 2991 operand[i], gettext("not found")); 2992 } 2993 } 2994 2995 (void) IMA_FreeMemory(targetList); 2996 return (ret); 2997 } 2998 2999 /* 3000 * Modify discovery attributes 3001 */ 3002 static int 3003 modifyDiscovery(cmdOptions_t *options, int *funcRet) 3004 { 3005 IMA_OID oid; 3006 IMA_STATUS status; 3007 IMA_BOOL setDiscovery; 3008 IMA_HOST_ID hostId; 3009 3010 int ret; 3011 cmdOptions_t *optionList = options; 3012 3013 assert(funcRet != NULL); 3014 3015 /* Find Sun initiator */ 3016 ret = sunInitiatorFind(&oid); 3017 if (ret > 0) { 3018 (void) fprintf(stderr, "%s: %s\n", 3019 cmdName, gettext("no initiator found")); 3020 } 3021 3022 if (ret != 0) { 3023 return (ret); 3024 } 3025 3026 for (; optionList->optval; optionList++) { 3027 /* check optarg and set bool accordingly */ 3028 if (strcasecmp(optionList->optarg, ISCSIADM_ARG_ENABLE) == 0) { 3029 setDiscovery = IMA_TRUE; 3030 } else if (strcasecmp(optionList->optarg, ISCSIADM_ARG_DISABLE) 3031 == 0) { 3032 setDiscovery = IMA_FALSE; 3033 } else { 3034 (void) fprintf(stderr, "%s: %s\n", 3035 cmdName, gettext("invalid option argument")); 3036 return (1); 3037 } 3038 3039 switch (optionList->optval) { 3040 case 's': 3041 /* Set static discovery */ 3042 status = IMA_SetStaticDiscovery(oid, 3043 setDiscovery); 3044 if (!IMA_SUCCESS(status)) { 3045 printLibError(status); 3046 *funcRet = 1; 3047 return (ret); 3048 } 3049 break; 3050 case 't': 3051 /* Set send targets discovery */ 3052 status = IMA_SetSendTargetsDiscovery(oid, 3053 setDiscovery); 3054 if (!IMA_SUCCESS(status)) { 3055 printLibError(status); 3056 *funcRet = 1; 3057 return (ret); 3058 } 3059 break; 3060 case 'i': 3061 /* Set iSNS discovery */ 3062 (void) memset(&hostId, 0, sizeof (hostId)); 3063 status = IMA_SetIsnsDiscovery(oid, setDiscovery, 3064 IMA_ISNS_DISCOVERY_METHOD_STATIC, &hostId); 3065 if (!IMA_SUCCESS(status)) { 3066 printLibError(status); 3067 *funcRet = 1; 3068 return (ret); 3069 } 3070 break; 3071 default: 3072 (void) fprintf(stderr, "%s: %c: %s\n", 3073 cmdName, optionList->optval, 3074 gettext("unknown option")); 3075 return (1); 3076 } 3077 } 3078 3079 return (ret); 3080 } 3081 3082 /* 3083 * Set the initiator node's authentication method 3084 */ 3085 static int 3086 modifyNodeAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet) 3087 { 3088 IMA_INITIATOR_AUTHPARMS authParams; 3089 IMA_STATUS status; 3090 int ret; 3091 int secretLen = MAX_CHAP_SECRET_LEN; 3092 3093 IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1]; 3094 3095 assert(funcRet != NULL); 3096 3097 /* 3098 * Start with existing parameters and modify with the desired change 3099 * before passing along. We ignore any failures as they probably 3100 * are caused by non-existence of auth params for the given node. 3101 */ 3102 status = IMA_GetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3103 &authParams); 3104 3105 switch (param) { 3106 case AUTH_NAME: 3107 if (chapName == NULL) { 3108 (void) fprintf(stderr, "CHAP name cannot be NULL.\n"); 3109 return (1); 3110 } 3111 if (strlen(chapName) == 0) { 3112 (void) fprintf(stderr, "CHAP name cannot be empty.\n"); 3113 return (1); 3114 } 3115 (void) memset(&authParams.chapParms.name, 0, 3116 sizeof (authParams.chapParms.name)); 3117 (void) memcpy(&authParams.chapParms.name, 3118 &chapName[0], strlen(chapName)); 3119 authParams.chapParms.nameLength = strlen(chapName); 3120 break; 3121 3122 case AUTH_PASSWORD : 3123 ret = getSecret((char *)&chapSecret[0], &secretLen, 3124 MIN_CHAP_SECRET_LEN, MAX_CHAP_SECRET_LEN); 3125 3126 if (ret != 0) { 3127 return (ret); 3128 } 3129 3130 (void) memset(&authParams.chapParms.challengeSecret, 0, 3131 sizeof (authParams.chapParms.challengeSecret)); 3132 (void) memcpy(&authParams.chapParms.challengeSecret, 3133 &chapSecret[0], secretLen); 3134 authParams.chapParms.challengeSecretLength = secretLen; 3135 break; 3136 3137 default: 3138 (void) fprintf(stderr, "Invalid auth parameter %d\n", param); 3139 return (1); 3140 } 3141 3142 status = IMA_SetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3143 &authParams); 3144 if (!IMA_SUCCESS(status)) { 3145 printLibError(status); 3146 *funcRet = 1; 3147 } 3148 return (ret); 3149 } 3150 3151 /* 3152 * Set the target's authentication method 3153 */ 3154 static int 3155 modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet) 3156 { 3157 IMA_INITIATOR_AUTHPARMS authParams; 3158 IMA_STATUS status; 3159 int ret; 3160 int secretLen = MAX_CHAP_SECRET_LEN; 3161 3162 IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1]; 3163 3164 assert(funcRet != NULL); 3165 3166 /* 3167 * Start with existing parameters and modify with the desired change 3168 * before passing along. We ignore any get failures as they probably 3169 * are caused by non-existence of auth params for the given target. 3170 */ 3171 status = SUN_IMA_GetTargetAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3172 &authParams); 3173 3174 switch (param) { 3175 case AUTH_NAME: 3176 if (chapName == NULL) { 3177 (void) fprintf(stderr, "CHAP name cannot be NULL.\n"); 3178 return (1); 3179 } 3180 if (strlen(chapName) == 0) { 3181 (void) fprintf(stderr, "CHAP name cannot be empty.\n"); 3182 return (1); 3183 } 3184 (void) memset(&authParams.chapParms.name, 0, 3185 sizeof (authParams.chapParms.name)); 3186 (void) memcpy(&authParams.chapParms.name, 3187 &chapName[0], strlen(chapName)); 3188 authParams.chapParms.nameLength = strlen(chapName); 3189 break; 3190 3191 case AUTH_PASSWORD : 3192 ret = getSecret((char *)&chapSecret[0], &secretLen, 3193 1, MAX_CHAP_SECRET_LEN); 3194 3195 if (ret != 0) { 3196 return (ret); 3197 } 3198 3199 (void) memset(&authParams.chapParms.challengeSecret, 0, 3200 sizeof (authParams.chapParms.challengeSecret)); 3201 (void) memcpy(&authParams.chapParms.challengeSecret, 3202 &chapSecret[0], secretLen); 3203 authParams.chapParms.challengeSecretLength = secretLen; 3204 break; 3205 3206 default: 3207 (void) fprintf(stderr, "Invalid auth parameter %d\n", param); 3208 return (1); 3209 } 3210 3211 status = SUN_IMA_SetTargetAuthParams(oid, IMA_AUTHMETHOD_CHAP, 3212 &authParams); 3213 if (!IMA_SUCCESS(status)) { 3214 printLibError(status); 3215 *funcRet = 1; 3216 } 3217 return (0); 3218 } 3219 3220 static int 3221 modifyTargetBidirAuthFlag(IMA_OID targetOid, char *optarg, int *funcRet) 3222 { 3223 IMA_BOOL boolValue; 3224 IMA_STATUS status; 3225 3226 assert(funcRet != NULL); 3227 3228 if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) { 3229 boolValue = IMA_TRUE; 3230 } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) { 3231 boolValue = IMA_FALSE; 3232 } else { 3233 (void) fprintf(stderr, "%s: %s %s\n", 3234 cmdName, gettext("invalid option argument"), optarg); 3235 return (1); 3236 } 3237 3238 status = SUN_IMA_SetTargetBidirAuthFlag(targetOid, &boolValue); 3239 if (!IMA_SUCCESS(status)) { 3240 printLibError(status); 3241 *funcRet = 1; 3242 } 3243 return (0); 3244 } 3245 3246 static int 3247 modifyConfiguredSessions(IMA_OID targetOid, char *optarg) 3248 { 3249 SUN_IMA_CONFIG_SESSIONS *pConfigSessions; 3250 IMA_STATUS status; 3251 int sessions; 3252 int size; 3253 char tmp[1024]; 3254 boolean_t isIpv6 = B_FALSE; 3255 uint16_t port; 3256 char address[MAX_ADDRESS_LEN]; 3257 char *commaPos; 3258 char *addressPos; 3259 int rtn; 3260 3261 /* 3262 * Strip the first int value from the string. If we sprintf 3263 * this back to a string and it matches the original string 3264 * then this command is using default binding. If not a 3265 * match we have hard coded binding or a usage error. 3266 */ 3267 sessions = atoi(optarg); 3268 (void) sprintf(tmp, "%d", sessions); 3269 if (strcmp(optarg, tmp) == 0) { 3270 /* default binding */ 3271 3272 /* allocate the required pConfigSessions */ 3273 size = sizeof (SUN_IMA_CONFIG_SESSIONS); 3274 pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 3275 if (pConfigSessions == NULL) { 3276 return (1); 3277 } 3278 3279 /* setup pConfigSessions */ 3280 pConfigSessions->bound = IMA_FALSE; 3281 pConfigSessions->in = sessions; 3282 pConfigSessions->out = 0; 3283 } else { 3284 /* hardcoded binding */ 3285 3286 /* 3287 * First we need to determine how many bindings 3288 * are available. This can be done by scanning 3289 * for the number of ',' + 1. 3290 */ 3291 sessions = 1; 3292 commaPos = strchr(optarg, ','); 3293 while (commaPos != NULL) { 3294 sessions++; 3295 commaPos = strchr(++commaPos, ','); 3296 } 3297 3298 /* allocate the required pConfigSessions */ 3299 size = sizeof (SUN_IMA_CONFIG_SESSIONS) + ((sessions - 1) * 3300 sizeof (IMA_ADDRESS_KEY)); 3301 pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 3302 if (pConfigSessions == NULL) { 3303 return (1); 3304 } 3305 3306 /* setup pConfigSessions */ 3307 pConfigSessions->bound = IMA_TRUE; 3308 pConfigSessions->in = sessions; 3309 pConfigSessions->out = 0; 3310 3311 /* Now fill in the binding information. */ 3312 sessions = 0; 3313 addressPos = optarg; 3314 /* 3315 * Walk thru possible address strings 3316 * stop once all strings are processed. 3317 */ 3318 while (addressPos != NULL) { 3319 /* 3320 * Check if there is another address after this 3321 * one. If so terminate the current address and 3322 * keep a pointer to the next one. 3323 */ 3324 commaPos = strchr(addressPos, ','); 3325 if (commaPos != NULL) { 3326 *commaPos++ = 0x00; 3327 } 3328 3329 /* 3330 * Parse current address. If invalid abort 3331 * processing of addresses and free memory. 3332 */ 3333 if (parseAddress(addressPos, 0, address, 3334 MAX_ADDRESS_LEN, &port, &isIpv6) != PARSE_ADDR_OK) { 3335 free(pConfigSessions); 3336 printLibError(IMA_ERROR_INVALID_PARAMETER); 3337 return (1); 3338 } 3339 3340 /* Convert address into binary form */ 3341 if (isIpv6 == B_FALSE) { 3342 pConfigSessions->bindings[sessions]. 3343 ipAddress.ipv4Address = IMA_TRUE; 3344 rtn = inet_pton(AF_INET, address, 3345 pConfigSessions->bindings[sessions]. 3346 ipAddress.ipAddress); 3347 } else { 3348 pConfigSessions->bindings[sessions].ipAddress. 3349 ipv4Address = 3350 IMA_FALSE; 3351 rtn = inet_pton(AF_INET6, address, 3352 pConfigSessions->bindings[sessions]. 3353 ipAddress.ipAddress); 3354 } 3355 if (rtn == 0) { 3356 /* inet_pton found address invalid */ 3357 free(pConfigSessions); 3358 printLibError(IMA_ERROR_INVALID_PARAMETER); 3359 return (1); 3360 } 3361 3362 /* update addressPos to next address */ 3363 sessions++; 3364 addressPos = commaPos; 3365 } 3366 } 3367 3368 /* issue SUN_IMA request */ 3369 status = SUN_IMA_SetConfigSessions(targetOid, 3370 pConfigSessions); 3371 if (!IMA_SUCCESS(status)) { 3372 printLibError(status); 3373 free(pConfigSessions); 3374 return (1); 3375 } 3376 3377 free(pConfigSessions); 3378 return (0); 3379 } 3380 3381 static int 3382 getAuthMethodValue(char *method, IMA_AUTHMETHOD *value) 3383 { 3384 if (strcasecmp(method, "chap") == 0) { 3385 *value = IMA_AUTHMETHOD_CHAP; 3386 return (0); 3387 } 3388 3389 if (strcasecmp(method, "none") == 0) { 3390 *value = IMA_AUTHMETHOD_NONE; 3391 return (0); 3392 } 3393 3394 return (1); 3395 } 3396 3397 3398 /* 3399 * Set the authentication method 3400 * Currently only supports CHAP and NONE 3401 */ 3402 static int 3403 modifyNodeAuthMethod(IMA_OID oid, char *optarg, int *funcRet) 3404 { 3405 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 3406 IMA_UINT methodCount = 0; 3407 IMA_STATUS status; 3408 IMA_AUTHMETHOD value; 3409 char *method; 3410 char *commaPos; 3411 3412 assert(funcRet != NULL); 3413 3414 /* 3415 * optarg will be a , delimited set of auth methods, in order 3416 * of preference 3417 * if any values here are incorrect, return without setting 3418 * anything. 3419 */ 3420 method = optarg; 3421 3422 commaPos = strchr(optarg, ','); 3423 3424 while (commaPos && methodCount < MAX_AUTH_METHODS) { 3425 *commaPos = NULL; 3426 if (getAuthMethodValue(method, &value) != 0) { 3427 (void) fprintf(stderr, "%s: a: %s\n", 3428 cmdName, gettext("invalid option argument")); 3429 return (1); 3430 } 3431 methodList[methodCount++] = value; 3432 commaPos++; 3433 method = commaPos; 3434 commaPos = strchr(method, ','); 3435 } 3436 /* Should not find more method specified - if found, error */ 3437 if (commaPos) { 3438 (void) fprintf(stderr, "%s: -a: %s\n", 3439 cmdName, gettext("invalid option argument")); 3440 return (1); 3441 } 3442 if (getAuthMethodValue(method, &value) != 0) { 3443 (void) fprintf(stderr, "%s: -a: %s\n", 3444 cmdName, gettext("invalid option argument")); 3445 return (1); 3446 } 3447 methodList[methodCount++] = value; 3448 3449 status = IMA_SetInitiatorAuthMethods(oid, methodCount, &methodList[0]); 3450 if (!IMA_SUCCESS(status)) { 3451 printLibError(status); 3452 *funcRet = 1; 3453 } 3454 return (0); 3455 } 3456 3457 static int 3458 modifyTargetAuthMethod(IMA_OID oid, char *optarg, int *funcRet) 3459 { 3460 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 3461 IMA_UINT methodCount = 0; 3462 IMA_STATUS status; 3463 IMA_AUTHMETHOD value; 3464 char *method; 3465 char *commaPos; 3466 3467 assert(funcRet != NULL); 3468 3469 /* 3470 * optarg will be a , delimited set of auth methods, in order 3471 * of preference 3472 * if any values here are incorrect, return without setting 3473 * anything. 3474 */ 3475 method = optarg; 3476 3477 commaPos = strchr(optarg, ','); 3478 3479 while (commaPos && methodCount < MAX_AUTH_METHODS) { 3480 *commaPos = NULL; 3481 if (getAuthMethodValue(method, &value) != 0) { 3482 (void) fprintf(stderr, "%s: a: %s\n", 3483 cmdName, gettext("invalid option argument")); 3484 return (1); 3485 } 3486 methodList[methodCount++] = value; 3487 commaPos++; 3488 method = commaPos; 3489 commaPos = strchr(method, ','); 3490 } 3491 /* Should not find more method specified - if found, error */ 3492 if (commaPos) { 3493 (void) fprintf(stderr, "%s: -a: %s\n", 3494 cmdName, gettext("invalid option argument")); 3495 return (1); 3496 } 3497 if (getAuthMethodValue(method, &value) != 0) { 3498 (void) fprintf(stderr, "%s: -a: %s\n", 3499 cmdName, gettext("invalid option argument")); 3500 return (1); 3501 } 3502 methodList[methodCount++] = value; 3503 3504 status = SUN_IMA_SetTargetAuthMethods(oid, &methodCount, 3505 &methodList[0]); 3506 if (!IMA_SUCCESS(status)) { 3507 printLibError(status); 3508 *funcRet = 1; 3509 } 3510 return (0); 3511 } 3512 3513 /* 3514 * Modify the RADIUS configuration of the initiator node. 3515 * 3516 * Return 0 on success. 3517 */ 3518 static int 3519 modifyNodeRadiusConfig(IMA_OID oid, char *optarg, int *funcRet) 3520 { 3521 SUN_IMA_RADIUS_CONFIG config; 3522 IMA_STATUS status; 3523 boolean_t isIpv6 = B_FALSE; 3524 uint16_t port; 3525 3526 assert(funcRet != NULL); 3527 3528 (void) memset(&config, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3529 if (parseAddress(optarg, DEFAULT_RADIUS_PORT, 3530 &config.hostnameIpAddress[0], SUN_IMA_IP_ADDRESS_PORT_LEN, 3531 &port, &isIpv6) != 3532 PARSE_ADDR_OK) { 3533 return (1); 3534 } 3535 config.port = (IMA_UINT16)port; 3536 config.isIpv6 = (isIpv6 == B_TRUE) ? IMA_TRUE : IMA_FALSE; 3537 /* Not setting shared secret here. */ 3538 config.sharedSecretValid = IMA_FALSE; 3539 3540 status = SUN_IMA_SetInitiatorRadiusConfig(oid, &config); 3541 if (!IMA_SUCCESS(status)) { 3542 printLibError(status); 3543 *funcRet = 1; 3544 } 3545 3546 return (0); 3547 } 3548 3549 /* 3550 * Modify the RADIUS access flag of the initiator node. 3551 * 3552 * Return 0 on success. 3553 */ 3554 static int 3555 modifyNodeRadiusAccess(IMA_OID oid, char *optarg, int *funcRet) 3556 { 3557 IMA_BOOL radiusAccess; 3558 IMA_OID initiatorOid; 3559 IMA_STATUS status; 3560 SUN_IMA_RADIUS_CONFIG radiusConfig; 3561 int ret; 3562 3563 assert(funcRet != NULL); 3564 3565 /* Check if Radius Config is there */ 3566 ret = sunInitiatorFind(&initiatorOid); 3567 if (ret != 0) { 3568 (void) fprintf(stderr, "%s: %s\n", 3569 cmdName, gettext("no initiator found")); 3570 return (1); 3571 } 3572 (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3573 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 3574 if (!IMA_SUCCESS(status)) { 3575 (void) fprintf(stderr, "%s: %s\n", 3576 cmdName, gettext("RADIUS server not configured yet")); 3577 *funcRet = 1; 3578 return (ret); 3579 } 3580 3581 /* Check if Radius Shared is set */ 3582 if (radiusConfig.sharedSecretValid == IMA_FALSE) { 3583 (void) fprintf(stderr, "%s: %s\n", cmdName, 3584 gettext("RADIUS server secret not configured yet")); 3585 return (1); 3586 } 3587 3588 if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) { 3589 radiusAccess = IMA_TRUE; 3590 } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) { 3591 radiusAccess = IMA_FALSE; 3592 } else { 3593 (void) fprintf(stderr, "%s: %s %s\n", 3594 cmdName, 3595 gettext("invalid option argument"), 3596 optarg); 3597 return (1); 3598 } 3599 status = SUN_IMA_SetInitiatorRadiusAccess(oid, radiusAccess); 3600 if (!IMA_SUCCESS(status)) { 3601 printLibError(status); 3602 *funcRet = 1; 3603 } 3604 3605 return (ret); 3606 } 3607 3608 /* 3609 * Modify the RADIUS shared secret. 3610 * 3611 * Returns: 3612 * zero on success. 3613 * > 0 on failure. 3614 */ 3615 static int 3616 modifyNodeRadiusSharedSecret(IMA_OID oid, int *funcRet) 3617 { 3618 IMA_BYTE radiusSharedSecret[SUN_IMA_MAX_RADIUS_SECRET_LEN + 1]; 3619 IMA_OID initiatorOid; 3620 IMA_STATUS status; 3621 SUN_IMA_RADIUS_CONFIG radiusConfig; 3622 int ret; 3623 int secretLen = SUN_IMA_MAX_RADIUS_SECRET_LEN; 3624 3625 assert(funcRet != NULL); 3626 3627 ret = getSecret((char *)&radiusSharedSecret[0], &secretLen, 3628 0, SUN_IMA_MAX_RADIUS_SECRET_LEN); 3629 if (ret != 0) { 3630 return (1); 3631 } 3632 3633 ret = sunInitiatorFind(&initiatorOid); 3634 if (ret > 0) { 3635 (void) fprintf(stderr, "%s: %s\n", 3636 cmdName, gettext("no initiator found")); 3637 } 3638 if (ret != 0) { 3639 return (1); 3640 } 3641 /* First obtain existing RADIUS configuration (if any) */ 3642 (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3643 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 3644 if (!IMA_SUCCESS(status)) { 3645 (void) fprintf(stderr, "%s: %s\n", 3646 cmdName, gettext("RADIUS server not configured yet")); 3647 return (1); 3648 } 3649 3650 /* Modify the shared secret only */ 3651 radiusConfig.sharedSecretLength = secretLen; 3652 (void) memcpy(&radiusConfig.sharedSecret, 3653 &radiusSharedSecret[0], secretLen); 3654 radiusConfig.sharedSecretValid = IMA_TRUE; 3655 status = SUN_IMA_SetInitiatorRadiusConfig(oid, &radiusConfig); 3656 if (!IMA_SUCCESS(status)) { 3657 printLibError(status); 3658 *funcRet = 1; 3659 } 3660 3661 return (0); 3662 } 3663 3664 /* 3665 * Set initiator node attributes. 3666 */ 3667 static int 3668 modifyNode(cmdOptions_t *options, int *funcRet) 3669 { 3670 IMA_NODE_NAME nodeName; 3671 IMA_NODE_ALIAS nodeAlias; 3672 IMA_OID oid; 3673 IMA_STATUS status; 3674 cmdOptions_t *optionList = options; 3675 int ret; 3676 iSCSINameCheckStatusType nameCheckStatus; 3677 IMA_OID sharedNodeOid; 3678 int i; 3679 int lowerCase; 3680 IMA_BOOL iscsiBoot = IMA_FALSE; 3681 IMA_BOOL mpxioEnabled = IMA_FALSE; 3682 char *mb_name = NULL; 3683 int prefixlen = 0; 3684 3685 assert(funcRet != NULL); 3686 3687 /* Get boot session's info */ 3688 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 3689 if (iscsiBoot == IMA_TRUE) { 3690 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 3691 if (!IMA_SUCCESS(status)) { 3692 (void) fprintf(stderr, "%s: %s\n", 3693 cmdName, gettext("unable to get MPxIO info" 3694 " of root disk")); 3695 *funcRet = 1; 3696 return (1); 3697 } 3698 } 3699 3700 /* Find Sun initiator */ 3701 ret = sunInitiatorFind(&oid); 3702 if (ret != 0) { 3703 (void) fprintf(stderr, "%s: %s\n", 3704 cmdName, gettext("no initiator found")); 3705 return (ret); 3706 } 3707 3708 for (; optionList->optval; optionList++) { 3709 switch (optionList->optval) { 3710 case 'N': 3711 if (strlen(optionList->optarg) >= 3712 MAX_ISCSI_NAME_LEN) { 3713 (void) fprintf(stderr, "%s: %s %d\n", 3714 cmdName, 3715 gettext("name too long, \ 3716 maximum length is:"), 3717 MAX_ISCSI_NAME_LEN); 3718 } 3719 3720 /* Take the first operand as node name. */ 3721 (void) memset(&nodeName, 0, 3722 sizeof (IMA_NODE_NAME)); 3723 if (mbstowcs(nodeName, optionList->optarg, 3724 IMA_NODE_NAME_LEN) == (size_t)-1) { 3725 (void) fprintf(stderr, "%s: %s\n", 3726 cmdName, 3727 gettext("conversion error")); 3728 return (1); 3729 } 3730 3731 prefixlen = strlen(ISCSI_IQN_NAME_PREFIX); 3732 mb_name = (char *)calloc(1, prefixlen + 1); 3733 if (mb_name == NULL) { 3734 return (1); 3735 } 3736 3737 if (wcstombs(mb_name, nodeName, 3738 prefixlen) == (size_t)-1) { 3739 (void) fprintf(stderr, "%s: %s\n", 3740 cmdName, 3741 gettext("conversion error")); 3742 (void) IMA_FreeMemory(mb_name); 3743 return (1); 3744 } 3745 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 3746 prefixlen) == 0) { 3747 /* 3748 * For iqn format, we should map 3749 * the upper-case characters to 3750 * their lower-case equivalents. 3751 */ 3752 for (i = 0; nodeName[i] != 0; i++) { 3753 lowerCase = 3754 tolower(nodeName[i]); 3755 nodeName[i] = lowerCase; 3756 } 3757 } 3758 (void) IMA_FreeMemory(mb_name); 3759 3760 /* Perform string profile checks */ 3761 nameCheckStatus = 3762 iSCSINameStringProfileCheck(nodeName); 3763 iSCSINameCheckStatusDisplay(nameCheckStatus); 3764 if (nameCheckStatus != iSCSINameCheckOK) { 3765 *funcRet = 1; /* DIY message fix */ 3766 return (1); 3767 } 3768 3769 /* 3770 * IMA_GetSharedNodeOid(&sharedNodeOid); 3771 * if (!IMA_SUCCESS(status)) { 3772 * printLibError(status); 3773 * return (INF_ERROR); 3774 * } 3775 */ 3776 if (iscsiBoot == IMA_TRUE) { 3777 (void) fprintf(stderr, "%s: %s\n", 3778 cmdName, gettext("iscsi boot, not" 3779 " allowed to change" 3780 " initiator's name")); 3781 return (1); 3782 } 3783 oid.objectType = IMA_OBJECT_TYPE_NODE; 3784 status = IMA_SetNodeName(oid, nodeName); 3785 if (!IMA_SUCCESS(status)) { 3786 printLibError(status); 3787 *funcRet = 1; 3788 return (ret); 3789 } 3790 break; 3791 3792 case 'A': 3793 if (iscsiBoot == IMA_TRUE) { 3794 (void) fprintf(stderr, "%s: %s\n", 3795 cmdName, gettext("iscsi boot, not" 3796 " allowed to change" 3797 " initiator's alias")); 3798 return (1); 3799 } 3800 /* Take the first operand as node alias. */ 3801 if (strlen(optionList->optarg) >= 3802 MAX_ISCSI_NAME_LEN) { 3803 (void) fprintf(stderr, "%s: %s %d\n", 3804 cmdName, 3805 gettext("alias too long, maximum \ 3806 length is:"), 3807 MAX_ISCSI_NAME_LEN); 3808 } 3809 3810 (void) memset(&nodeAlias, 0, 3811 sizeof (IMA_NODE_ALIAS)); 3812 if (mbstowcs(nodeAlias, optionList->optarg, 3813 IMA_NODE_ALIAS_LEN) == (size_t)-1) { 3814 (void) fprintf(stderr, "%s: %s\n", 3815 cmdName, 3816 gettext("conversion error")); 3817 return (1); 3818 } 3819 3820 status = IMA_GetSharedNodeOid(&sharedNodeOid); 3821 if (!IMA_SUCCESS(status)) { 3822 printLibError(status); 3823 *funcRet = 1; 3824 return (ret); 3825 } 3826 3827 status = IMA_SetNodeAlias(sharedNodeOid, 3828 nodeAlias); 3829 if (!IMA_SUCCESS(status)) { 3830 printLibError(status); 3831 *funcRet = 1; 3832 return (ret); 3833 } 3834 break; 3835 3836 case 'a': 3837 if (iscsiBoot == IMA_TRUE) { 3838 (void) fprintf(stderr, "%s: %s\n", 3839 cmdName, gettext("iscsi boot, not" 3840 " allowed to change authentication" 3841 " method")); 3842 return (1); 3843 } 3844 if (modifyNodeAuthMethod(oid, options->optarg, 3845 funcRet) != 0) { 3846 return (1); 3847 } 3848 break; 3849 3850 case 'R': 3851 if (modifyNodeRadiusAccess(oid, options->optarg, 3852 funcRet) != 0) { 3853 return (1); 3854 } 3855 break; 3856 3857 case 'r': 3858 if (modifyNodeRadiusConfig(oid, options->optarg, 3859 funcRet) != 0) { 3860 return (1); 3861 } 3862 break; 3863 3864 case 'P': 3865 if (modifyNodeRadiusSharedSecret(oid, funcRet) 3866 != 0) { 3867 return (1); 3868 } 3869 break; 3870 3871 case 'C': 3872 if (iscsiBoot == IMA_TRUE) { 3873 (void) fprintf(stderr, "%s: %s\n", 3874 cmdName, gettext("iscsi boot, not" 3875 " allowed to change CHAP secret")); 3876 return (1); 3877 } 3878 if (modifyNodeAuthParam(oid, AUTH_PASSWORD, 3879 NULL, funcRet) != 0) { 3880 return (1); 3881 } 3882 break; 3883 3884 case 'c': 3885 if (iscsiBoot == IMA_TRUE) { 3886 if (mpxioEnabled == IMA_FALSE) { 3887 (void) fprintf(stderr, 3888 "%s: %s\n", cmdName, 3889 gettext("iscsi" 3890 " boot and MPxIO" 3891 " is disabled, not allowed" 3892 " to change number of" 3893 " sessions to be" 3894 " configured")); 3895 return (1); 3896 } 3897 } 3898 if (modifyConfiguredSessions(oid, 3899 optionList->optarg) != 0) { 3900 if (iscsiBoot == IMA_TRUE) { 3901 (void) fprintf(stderr, 3902 "%s: %s\n", cmdName, 3903 gettext("iscsi boot," 3904 " fail to set configured" 3905 " session")); 3906 } 3907 return (1); 3908 } 3909 break; 3910 3911 3912 case 'H': 3913 if (iscsiBoot == IMA_TRUE) { 3914 (void) fprintf(stderr, "%s: %s\n", 3915 cmdName, gettext("iscsi boot, not" 3916 " allowed to change CHAP name")); 3917 return (1); 3918 } 3919 if (modifyNodeAuthParam(oid, AUTH_NAME, 3920 optionList->optarg, funcRet) != 0) { 3921 return (1); 3922 } 3923 break; 3924 3925 3926 case 'd': 3927 if (iscsiBoot == IMA_TRUE) { 3928 if (mpxioEnabled == IMA_FALSE) { 3929 (void) fprintf(stderr, 3930 "%s: %s\n", cmdName, 3931 gettext("iscsi" 3932 " boot and MPxIO" 3933 " is disabled, not" 3934 " allowed to" 3935 " change initiator's" 3936 " login params")); 3937 return (1); 3938 } 3939 } 3940 if (setLoginParameter(oid, DATA_DIGEST, 3941 optionList->optarg) != 0) { 3942 return (1); 3943 } 3944 break; 3945 3946 case 'h': 3947 if (iscsiBoot == IMA_TRUE) { 3948 if (mpxioEnabled == IMA_FALSE) { 3949 (void) fprintf(stderr, 3950 "%s: %s\n", cmdName, 3951 gettext("iscsi" 3952 " boot and MPxIO" 3953 " is disabled, not" 3954 " allowed to" 3955 " change initiator's" 3956 " login params")); 3957 return (1); 3958 } 3959 } 3960 if (setLoginParameter(oid, HEADER_DIGEST, 3961 optionList->optarg) != 0) { 3962 return (1); 3963 } 3964 break; 3965 3966 case 'T': 3967 if (setTunableParameters(oid, 3968 optionList->optarg) != 0) { 3969 return (1); 3970 } 3971 break; 3972 default: 3973 (void) fprintf(stderr, "%s: %c: %s\n", 3974 cmdName, optionList->optval, 3975 gettext("unknown option")); 3976 break; 3977 } 3978 } 3979 3980 return (ret); 3981 } 3982 3983 /* 3984 * Modify target parameters 3985 */ 3986 static int 3987 modifyTargetParam(cmdOptions_t *options, char *targetName, int *funcRet) 3988 { 3989 IMA_OID oid; 3990 IMA_OID targetOid; 3991 IMA_STATUS status; 3992 IMA_OID_LIST *targetList; 3993 SUN_IMA_TARGET_PROPERTIES targetProps; 3994 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 3995 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 3996 int ret; 3997 boolean_t found; 3998 boolean_t targetAddressSpecified = B_TRUE; 3999 boolean_t tpgtSpecified = B_FALSE; 4000 boolean_t isIpv6 = B_FALSE; 4001 int i; 4002 iSCSINameCheckStatusType nameCheckStatus; 4003 IMA_UINT16 port = 0; 4004 IMA_UINT16 tpgt = 0; 4005 4006 IMA_NODE_NAME bootTargetName; 4007 IMA_INITIATOR_AUTHPARMS bootTargetCHAP; 4008 IMA_BOOL iscsiBoot; 4009 IMA_BOOL mpxioEnabled; 4010 4011 cmdOptions_t *optionList = options; 4012 4013 assert(funcRet != NULL); 4014 4015 /* Find Sun initiator */ 4016 ret = sunInitiatorFind(&oid); 4017 if (ret > 0) { 4018 (void) fprintf(stderr, "%s: %s\n", 4019 cmdName, gettext("no initiator found")); 4020 } 4021 4022 if (ret != 0) { 4023 return (ret); 4024 } 4025 4026 if (parseTarget(targetName, 4027 &wcInputObject[0], 4028 MAX_ISCSI_NAME_LEN + 1, 4029 &targetAddressSpecified, 4030 &targetAddress[0], 4031 SUN_IMA_IP_ADDRESS_PORT_LEN, 4032 &port, 4033 &tpgtSpecified, 4034 &tpgt, 4035 &isIpv6) != PARSE_TARGET_OK) { 4036 return (1); 4037 } 4038 4039 /* Perform string profile checks */ 4040 nameCheckStatus = iSCSINameStringProfileCheck(wcInputObject); 4041 iSCSINameCheckStatusDisplay(nameCheckStatus); 4042 if (nameCheckStatus != iSCSINameCheckOK) { 4043 return (1); 4044 } 4045 4046 status = IMA_GetTargetOidList(oid, &targetList); 4047 if (!IMA_SUCCESS(status)) { 4048 printLibError(status); 4049 *funcRet = 1; 4050 return (0); 4051 } 4052 4053 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 4054 if (iscsiBoot == IMA_TRUE) { 4055 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 4056 if (!IMA_SUCCESS(status)) { 4057 (void) fprintf(stderr, "%s: %s\n", 4058 cmdName, gettext("unable to get MPxIO info" 4059 " of root disk")); 4060 *funcRet = 1; 4061 return (ret); 4062 } 4063 status = SUN_IMA_GetBootTargetName(bootTargetName); 4064 if (!IMA_SUCCESS(status)) { 4065 (void) fprintf(stderr, "%s: %s\n", 4066 cmdName, gettext("unable to get boot target's" 4067 " name")); 4068 *funcRet = 1; 4069 return (ret); 4070 } 4071 status = SUN_IMA_GetBootTargetAuthParams(&bootTargetCHAP); 4072 if (!IMA_SUCCESS(status)) { 4073 (void) fprintf(stderr, "%s: %s\n", 4074 cmdName, gettext("unable to get boot target's" 4075 " auth param")); 4076 *funcRet = 1; 4077 return (ret); 4078 } 4079 } 4080 4081 /* find target oid */ 4082 for (found = B_FALSE, i = 0; i < targetList->oidCount; i++) { 4083 status = SUN_IMA_GetTargetProperties(targetList->oids[i], 4084 &targetProps); 4085 if (!IMA_SUCCESS(status)) { 4086 printLibError(status); 4087 (void) IMA_FreeMemory(targetList); 4088 *funcRet = 1; 4089 return (ret); 4090 } 4091 4092 /* 4093 * Compare the target name with the input name 4094 */ 4095 if ((targetNamesEqual(wcInputObject, targetProps.imaProps.name) 4096 == B_TRUE)) { 4097 /* 4098 * For now, regardless of whether a target address 4099 * is specified, we return B_TRUE because 4100 * IMA_TARGET_PROPERTIES does not have a field for 4101 * specifying address. 4102 */ 4103 found = B_TRUE; 4104 targetOid = targetList->oids[i]; 4105 4106 if ((targetNamesEqual(bootTargetName, wcInputObject) 4107 == B_TRUE) && (iscsiBoot == IMA_TRUE)) { 4108 /* 4109 * iscsi booting, need changed target param is 4110 * booting target, for auth param, not allow 4111 * to change, for others dependent on mpxio 4112 */ 4113 4114 if ((optionList->optval == 'C') || 4115 (optionList->optval == 'H') || 4116 (optionList->optval == 'B') || 4117 (optionList->optval == 'a')) { 4118 /* 4119 * -C CHAP secret set 4120 * -H CHAP name set 4121 * -a authentication 4122 * -B bi-directional-authentication 4123 */ 4124 (void) fprintf(stderr, "%s: %s\n", 4125 cmdName, gettext("iscsi boot," 4126 " not allowed to modify" 4127 " authentication parameters" 4128 " of boot target")); 4129 return (1); 4130 } 4131 if (mpxioEnabled == IMA_FALSE) { 4132 (void) fprintf(stderr, "%s: %s\n", 4133 cmdName, gettext("iscsi boot and" 4134 " MPxIO is disabled, not allowed" 4135 " to modify boot target's" 4136 " parameters")); 4137 return (1); 4138 } 4139 4140 } 4141 4142 if (modifyIndividualTargetParam(optionList, targetOid, 4143 funcRet) != 0) { 4144 return (ret); 4145 } 4146 4147 /* 4148 * Even after finding a matched target, keep going 4149 * since there could be multiple target objects 4150 * associated with one target name in the system 4151 * because of different TPGTs. 4152 */ 4153 } 4154 } 4155 4156 /* If the target OID cannot be found create one */ 4157 if (!found) { 4158 status = SUN_IMA_CreateTargetOid(wcInputObject, &targetOid); 4159 if (!IMA_SUCCESS(status)) { 4160 printLibError(status); 4161 (void) IMA_FreeMemory(targetList); 4162 *funcRet = 1; 4163 return (ret); 4164 } 4165 if (modifyIndividualTargetParam(optionList, targetOid, 4166 funcRet) != 0) { 4167 return (ret); 4168 } 4169 } 4170 4171 (void) IMA_FreeMemory(targetList); 4172 return (ret); 4173 } 4174 4175 /* 4176 * Add one or more addresses 4177 */ 4178 static int 4179 addAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4180 { 4181 IMA_STATUS status; 4182 IMA_OID oid, addressOid; 4183 SUN_IMA_TARGET_ADDRESS address; 4184 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4185 int ret; 4186 int i; 4187 4188 assert(funcRet != NULL); 4189 4190 /* Find Sun initiator */ 4191 ret = sunInitiatorFind(&oid); 4192 if (ret > 0) { 4193 (void) fprintf(stderr, "%s: %s\n", 4194 cmdName, gettext("no initiator found")); 4195 } 4196 4197 if (ret != 0) { 4198 return (ret); 4199 } 4200 4201 /* 4202 * Format of discovery address operand: 4203 * 4204 * <IP address|hostname>:<port> 4205 */ 4206 for (i = 0; i < operandLen; i++) { 4207 /* initialize */ 4208 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4209 (void) memset(&address, 0, sizeof (address)); 4210 4211 if (mbstowcs(wcInputObject, operand[i], 4212 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 4213 (void) fprintf(stderr, "%s: %s\n", 4214 cmdName, gettext("conversion error")); 4215 ret = 1; 4216 continue; 4217 } 4218 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4219 != 0) { 4220 ret = 1; 4221 continue; 4222 } 4223 if (addrType == DISCOVERY_ADDRESS) { 4224 status = IMA_AddDiscoveryAddress(oid, 4225 address.imaStruct, &addressOid); 4226 if (!IMA_SUCCESS(status)) { 4227 printLibError(status); 4228 *funcRet = 1; 4229 return (ret); 4230 } 4231 } else if (addrType == ISNS_SERVER_ADDRESS) { 4232 status = SUN_IMA_AddISNSServerAddress(address); 4233 if (!IMA_SUCCESS(status)) { 4234 printLibError(status); 4235 *funcRet = 1; 4236 return (ret); 4237 } 4238 } 4239 } 4240 return (ret); 4241 } 4242 4243 /* 4244 * Add one or more static configuration targets 4245 */ 4246 static int 4247 addStaticConfig(int operandLen, char *operand[], int *funcRet) 4248 { 4249 int i; 4250 boolean_t targetAddressSpecified = B_FALSE; 4251 boolean_t tpgtSpecified = B_FALSE; 4252 boolean_t isIpv6 = B_FALSE; 4253 int ret; 4254 int addrType; 4255 IMA_STATUS status; 4256 IMA_OID oid; 4257 SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig; 4258 IMA_UINT16 port = 0; 4259 IMA_UINT16 tpgt = 0; 4260 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4261 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4262 iSCSINameCheckStatusType nameCheckStatus; 4263 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4264 4265 assert(funcRet != NULL); 4266 4267 /* Find Sun initiator */ 4268 ret = sunInitiatorFind(&oid); 4269 if (ret > 0) { 4270 (void) fprintf(stderr, "%s: %s\n", 4271 cmdName, gettext("no initiator found")); 4272 } 4273 4274 if (ret != 0) { 4275 return (ret); 4276 } 4277 4278 /* 4279 * Format of static config operand: 4280 * <target-name>,<IP address|hostname>[:port][,tpgt] 4281 */ 4282 for (i = 0; i < operandLen; i++) { 4283 if (parseTarget(operand[i], 4284 &staticTargetName[0], 4285 MAX_ISCSI_NAME_LEN + 1, 4286 &targetAddressSpecified, 4287 &staticTargetAddress[0], 4288 SUN_IMA_IP_ADDRESS_PORT_LEN, 4289 &port, 4290 &tpgtSpecified, 4291 &tpgt, 4292 &isIpv6) != PARSE_TARGET_OK) { 4293 ret = 1; 4294 continue; 4295 } 4296 4297 if (targetAddressSpecified != B_TRUE) { 4298 (void) fprintf(stderr, "%s: %s\n", 4299 cmdName, gettext("missing target address")); 4300 *funcRet = 1; /* DIY message fix */ 4301 return (1); 4302 } 4303 /* Perform string profile checks */ 4304 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4305 iSCSINameCheckStatusDisplay(nameCheckStatus); 4306 if (nameCheckStatus != iSCSINameCheckOK) { 4307 *funcRet = 1; /* DIY message fix */ 4308 return (1); 4309 } 4310 (void) wcsncpy(staticConfig.targetName, staticTargetName, 4311 MAX_ISCSI_NAME_LEN + 1); 4312 4313 (void) wcstombs(sAddr, staticTargetAddress, sizeof (sAddr)); 4314 4315 if (isIpv6 == B_TRUE) { 4316 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4317 id.ipAddress.ipv4Address = B_FALSE; 4318 addrType = AF_INET6; 4319 } else { 4320 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4321 id.ipAddress.ipv4Address = B_TRUE; 4322 addrType = AF_INET; 4323 } 4324 4325 if (inet_pton(addrType, sAddr, staticConfig.targetAddress. 4326 imaStruct.hostnameIpAddress.id.ipAddress.ipAddress) != 1) { 4327 (void) fprintf(stderr, "%s: %s\n", 4328 cmdName, gettext("static config conversion error")); 4329 ret = 1; 4330 continue; 4331 } 4332 4333 staticConfig.targetAddress.imaStruct.portNumber = port; 4334 if (tpgtSpecified == B_TRUE) { 4335 staticConfig.targetAddress.defaultTpgt = B_FALSE; 4336 staticConfig.targetAddress.tpgt = tpgt; 4337 } else { 4338 staticConfig.targetAddress.defaultTpgt = B_TRUE; 4339 staticConfig.targetAddress.tpgt = 0; 4340 } 4341 4342 status = SUN_IMA_AddStaticTarget(oid, staticConfig, &oid); 4343 if (!IMA_SUCCESS(status)) { 4344 printLibError(status); 4345 *funcRet = 1; 4346 return (1); 4347 } 4348 } 4349 4350 if (ret != 0) { 4351 *funcRet = 1; 4352 } 4353 4354 return (ret); 4355 } 4356 4357 /* 4358 * Remove one or more addresses 4359 */ 4360 static int 4361 removeAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4362 { 4363 IMA_STATUS status; 4364 IMA_OID initiatorOid; 4365 SUN_IMA_TARGET_ADDRESS address; 4366 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4367 int ret; 4368 int i; 4369 4370 assert(funcRet != NULL); 4371 4372 /* Find Sun initiator */ 4373 ret = sunInitiatorFind(&initiatorOid); 4374 if (ret > 0) { 4375 (void) fprintf(stderr, "%s: %s\n", 4376 cmdName, gettext("no initiator found")); 4377 } 4378 4379 if (ret != 0) { 4380 return (ret); 4381 } 4382 4383 for (i = 0; i < operandLen; i++) { 4384 /* initialize */ 4385 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4386 (void) memset(&address, 0, sizeof (address)); 4387 4388 if (mbstowcs(wcInputObject, operand[i], 4389 MAX_ADDRESS_LEN + 1) == (size_t)-1) { 4390 (void) fprintf(stderr, "%s: %s\n", 4391 cmdName, gettext("conversion error")); 4392 ret = 1; 4393 continue; 4394 } 4395 4396 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4397 != 0) { 4398 ret = 1; 4399 continue; 4400 } 4401 4402 if (addrType == DISCOVERY_ADDRESS) { 4403 status = SUN_IMA_RemoveDiscoveryAddress(address); 4404 if (!IMA_SUCCESS(status)) { 4405 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4406 (void) fprintf(stderr, "%s: %s\n", 4407 operand[i], gettext("not found")); 4408 } else { 4409 printLibError(status); 4410 } 4411 *funcRet = 1; 4412 } 4413 } else { 4414 status = SUN_IMA_RemoveISNSServerAddress(address); 4415 if (!IMA_SUCCESS(status)) { 4416 printLibError(status); 4417 *funcRet = 1; 4418 } 4419 } 4420 } 4421 return (ret); 4422 } 4423 4424 /* 4425 * Remove one or more static configuration targets 4426 */ 4427 static int 4428 removeStaticConfig(int operandLen, char *operand[], int *funcRet) 4429 { 4430 IMA_STATUS status; 4431 IMA_OID initiatorOid; 4432 IMA_OID_LIST *staticTargetList; 4433 SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps; 4434 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4435 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4436 int ret; 4437 boolean_t atLeastFoundOne; 4438 boolean_t matched; 4439 boolean_t targetAddressSpecified = B_TRUE; 4440 boolean_t tpgtSpecified = B_FALSE; 4441 boolean_t isIpv6 = B_FALSE; 4442 int i, j; 4443 IMA_UINT16 port = 0; 4444 IMA_UINT16 tpgt = 0; 4445 iSCSINameCheckStatusType nameCheckStatus; 4446 char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4447 wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4448 4449 assert(funcRet != NULL); 4450 4451 /* Find Sun initiator */ 4452 ret = sunInitiatorFind(&initiatorOid); 4453 if (ret > 0) { 4454 (void) fprintf(stderr, "%s: %s\n", 4455 cmdName, gettext("no initiator found")); 4456 } 4457 4458 if (ret != 0) { 4459 return (ret); 4460 } 4461 4462 status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid, 4463 &staticTargetList); 4464 if (!IMA_SUCCESS(status)) { 4465 printLibError(status); 4466 *funcRet = 1; 4467 return (ret); 4468 } 4469 4470 for (i = 0; i < operandLen; i++) { 4471 if (parseTarget(operand[i], 4472 &staticTargetName[0], 4473 MAX_ISCSI_NAME_LEN + 1, 4474 &targetAddressSpecified, 4475 &staticTargetAddress[0], 4476 SUN_IMA_IP_ADDRESS_PORT_LEN, 4477 &port, 4478 &tpgtSpecified, 4479 &tpgt, 4480 &isIpv6) != PARSE_TARGET_OK) { 4481 ret = 1; 4482 continue; 4483 } 4484 4485 /* Perform string profile checks */ 4486 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4487 iSCSINameCheckStatusDisplay(nameCheckStatus); 4488 if (nameCheckStatus != iSCSINameCheckOK) { 4489 return (1); 4490 } 4491 4492 for (atLeastFoundOne = B_FALSE, j = 0; 4493 j < staticTargetList->oidCount; 4494 j++) { 4495 IMA_UINT16 stpgt; 4496 4497 matched = B_FALSE; 4498 status = SUN_IMA_GetStaticTargetProperties( 4499 staticTargetList->oids[j], &staticTargetProps); 4500 if (!IMA_SUCCESS(status)) { 4501 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4502 /* 4503 * When removing multiple static-config 4504 * entries we need to expect get 4505 * failures. These failures occur when 4506 * we are trying to get entry 4507 * information we have just removed. 4508 * Ignore the failure and continue. 4509 */ 4510 ret = 1; 4511 continue; 4512 } else { 4513 printLibError(status); 4514 (void) IMA_FreeMemory(staticTargetList); 4515 *funcRet = 1; 4516 return (ret); 4517 } 4518 } 4519 4520 stpgt = 4521 staticTargetProps.staticTarget.targetAddress.tpgt; 4522 4523 /* 4524 * Compare the static target name with the input if 4525 * one was input 4526 */ 4527 if ((targetNamesEqual( 4528 staticTargetProps.staticTarget.targetName, 4529 staticTargetName) == B_TRUE)) { 4530 if (targetAddressSpecified == B_FALSE) { 4531 matched = B_TRUE; 4532 } else { 4533 4534 if (staticTargetProps.staticTarget. 4535 targetAddress.imaStruct. 4536 hostnameIpAddress. 4537 id.ipAddress.ipv4Address == 4538 IMA_TRUE) { 4539 (void) inet_ntop(AF_INET, 4540 staticTargetProps. 4541 staticTarget.targetAddress. 4542 imaStruct.hostnameIpAddress. 4543 id.ipAddress.ipAddress, 4544 tmpStr, 4545 sizeof (tmpStr)); 4546 } else { 4547 (void) inet_ntop(AF_INET6, 4548 staticTargetProps. 4549 staticTarget.targetAddress. 4550 imaStruct.hostnameIpAddress. 4551 id.ipAddress.ipAddress, 4552 tmpStr, 4553 sizeof (tmpStr)); 4554 } 4555 4556 if (mbstowcs(tmpTargetAddress, tmpStr, 4557 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4558 (size_t)-1) { 4559 (void) fprintf(stderr, 4560 "%s: %s\n", 4561 cmdName, gettext( 4562 "conversion error")); 4563 ret = 1; 4564 continue; 4565 } 4566 4567 if ((wcsncmp(tmpTargetAddress, 4568 staticTargetAddress, 4569 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4570 0) && (staticTargetProps. 4571 staticTarget.targetAddress. 4572 imaStruct.portNumber == port)) { 4573 if (tpgtSpecified == B_FALSE) { 4574 matched = B_TRUE; 4575 } else { 4576 if (tpgt == stpgt) { 4577 matched = 4578 B_TRUE; 4579 } 4580 } 4581 } 4582 } 4583 4584 if (matched) { 4585 status = 4586 IMA_RemoveStaticDiscoveryTarget( 4587 staticTargetList->oids[j]); 4588 if (!IMA_SUCCESS(status)) { 4589 printLibError(status); 4590 *funcRet = 1; 4591 return (ret); 4592 } 4593 atLeastFoundOne = B_TRUE; 4594 } 4595 } 4596 } 4597 if (!atLeastFoundOne) { 4598 (void) fprintf(stderr, gettext("%ws,%ws: %s\n"), 4599 staticTargetName, staticTargetAddress, 4600 gettext("not found")); 4601 } 4602 } 4603 return (ret); 4604 } 4605 4606 /* 4607 * Remove one or more target params. 4608 */ 4609 static int 4610 removeTargetParam(int operandLen, char *operand[], int *funcRet) 4611 { 4612 char *commaPos; 4613 IMA_STATUS status; 4614 IMA_OID initiatorOid; 4615 IMA_OID_LIST *targetList; 4616 SUN_IMA_TARGET_PROPERTIES targetProps; 4617 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 4618 int ret; 4619 boolean_t found; 4620 int i, j; 4621 IMA_NODE_NAME bootTargetName; 4622 IMA_BOOL iscsiBoot = IMA_FALSE; 4623 IMA_BOOL mpxioEnabled = IMA_FALSE; 4624 4625 /* Get boot session's info */ 4626 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 4627 if (iscsiBoot == IMA_TRUE) { 4628 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 4629 if (!IMA_SUCCESS(status)) { 4630 (void) fprintf(stderr, "%s: %s\n", 4631 cmdName, gettext("unable to get MPxIO info of" 4632 " root disk")); 4633 *funcRet = 1; 4634 return (1); 4635 } 4636 status = SUN_IMA_GetBootTargetName(bootTargetName); 4637 if (!IMA_SUCCESS(status)) { 4638 (void) fprintf(stderr, "%s: %s\n", 4639 cmdName, gettext("unable to get boot" 4640 " target's name")); 4641 *funcRet = 1; 4642 return (1); 4643 } 4644 } 4645 4646 assert(funcRet != NULL); 4647 4648 /* Find Sun initiator */ 4649 ret = sunInitiatorFind(&initiatorOid); 4650 if (ret > 0) { 4651 (void) fprintf(stderr, "%s: %s\n", 4652 cmdName, gettext("no initiator found")); 4653 } 4654 4655 if (ret != 0) { 4656 return (ret); 4657 } 4658 4659 status = IMA_GetTargetOidList(initiatorOid, &targetList); 4660 if (!IMA_SUCCESS(status)) { 4661 printLibError(status); 4662 *funcRet = 1; 4663 return (ret); 4664 } 4665 4666 for (i = 0; i < operandLen; i++) { 4667 /* initialize */ 4668 commaPos = strchr(operand[i], ','); 4669 if (commaPos) { 4670 /* Ignore IP address. */ 4671 *commaPos = NULL; 4672 } 4673 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4674 if (mbstowcs(wcInputObject, operand[i], 4675 MAX_ISCSI_NAME_LEN + 1) == (size_t)-1) { 4676 (void) fprintf(stderr, "%s: %s\n", cmdName, 4677 gettext("conversion error")); 4678 ret = 1; 4679 continue; 4680 } 4681 4682 for (found = B_FALSE, j = 0; j < targetList->oidCount; 4683 j++) { 4684 status = SUN_IMA_GetTargetProperties( 4685 targetList->oids[j], &targetProps); 4686 if (!IMA_SUCCESS(status)) { 4687 printLibError(status); 4688 (void) IMA_FreeMemory(targetList); 4689 *funcRet = 1; 4690 return (ret); 4691 } 4692 4693 /* 4694 * Compare the target name with the input if 4695 * one was input 4696 */ 4697 if (targetNamesEqual(targetProps.imaProps.name, 4698 wcInputObject) == B_TRUE) { 4699 found = B_TRUE; 4700 if ((targetNamesEqual(bootTargetName, 4701 wcInputObject) == B_TRUE) && 4702 (iscsiBoot == IMA_TRUE)) { 4703 /* 4704 * iscsi booting, need changed target 4705 * param is booting target, booting 4706 * session mpxio disabled, not 4707 * allow to update 4708 */ 4709 if (mpxioEnabled == IMA_FALSE) { 4710 (void) fprintf(stderr, 4711 "%s: %s\n", cmdName, 4712 gettext("iscsi boot" 4713 " with MPxIO disabled," 4714 " not allowed to remove" 4715 " boot sess param")); 4716 ret = 1; 4717 continue; 4718 } 4719 4720 } 4721 4722 status = SUN_IMA_RemoveTargetParam( 4723 targetList->oids[j]); 4724 if (!IMA_SUCCESS(status)) { 4725 printLibError(status); 4726 (void) IMA_FreeMemory(targetList); 4727 *funcRet = 1; 4728 return (ret); 4729 } 4730 } 4731 } 4732 if (!found) { 4733 /* Silently ignoring it? */ 4734 (void) fprintf(stderr, gettext("%ws: %s\n"), 4735 wcInputObject, gettext("not found")); 4736 } 4737 } 4738 4739 (void) IMA_FreeMemory(targetList); 4740 return (ret); 4741 } 4742 4743 /*ARGSUSED*/ 4744 static int 4745 addFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4746 void *addArgs, int *funcRet) 4747 { 4748 int ret; 4749 4750 assert(funcRet != NULL); 4751 4752 switch (object) { 4753 case DISCOVERY_ADDRESS: 4754 case ISNS_SERVER_ADDRESS: 4755 ret = addAddress(object, operandLen, operand, funcRet); 4756 break; 4757 case STATIC_CONFIG: 4758 ret = addStaticConfig(operandLen, operand, funcRet); 4759 break; 4760 default: 4761 (void) fprintf(stderr, "%s: %s\n", 4762 cmdName, gettext("unknown object")); 4763 ret = 1; 4764 break; 4765 } 4766 return (ret); 4767 } 4768 4769 /*ARGSUSED*/ 4770 static int 4771 listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4772 void *addArgs, int *funcRet) 4773 { 4774 int ret; 4775 4776 assert(funcRet != NULL); 4777 4778 switch (object) { 4779 case DISCOVERY: 4780 ret = listDiscovery(funcRet); 4781 break; 4782 case DISCOVERY_ADDRESS: 4783 ret = listDiscoveryAddress(operandLen, operand, options, 4784 funcRet); 4785 break; 4786 case ISNS_SERVER_ADDRESS: 4787 ret = listISNSServerAddress(operandLen, operand, options, 4788 funcRet); 4789 break; 4790 case NODE: 4791 ret = listNode(funcRet); 4792 break; 4793 case STATIC_CONFIG: 4794 ret = listStaticConfig(operandLen, operand, funcRet); 4795 break; 4796 case TARGET: 4797 ret = listTarget(operandLen, operand, options, funcRet); 4798 break; 4799 case TARGET_PARAM: 4800 ret = listTargetParam(operandLen, operand, options, funcRet); 4801 break; 4802 default: 4803 (void) fprintf(stderr, "%s: %s\n", 4804 cmdName, gettext("unknown object")); 4805 ret = 1; 4806 break; 4807 } 4808 return (ret); 4809 } 4810 4811 /*ARGSUSED*/ 4812 static int 4813 modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4814 void *addArgs, int *funcRet) 4815 { 4816 int ret, i; 4817 4818 assert(funcRet != NULL); 4819 4820 switch (object) { 4821 case DISCOVERY: 4822 ret = modifyDiscovery(options, funcRet); 4823 break; 4824 case NODE: 4825 ret = modifyNode(options, funcRet); 4826 break; 4827 case TARGET_PARAM: 4828 i = 0; 4829 while (operand[i]) { 4830 ret = modifyTargetParam(options, operand[i], funcRet); 4831 4832 if (ret) { 4833 (void) fprintf(stderr, "%s: %s: %s\n", 4834 cmdName, gettext("modify failed"), 4835 operand[i]); 4836 return (ret); 4837 } 4838 i++; 4839 } 4840 4841 break; 4842 default: 4843 (void) fprintf(stderr, "%s: %s\n", 4844 cmdName, gettext("unknown object")); 4845 ret = 1; 4846 break; 4847 } 4848 return (ret); 4849 } 4850 4851 /*ARGSUSED*/ 4852 static int 4853 removeFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4854 void *addArgs, int *funcRet) 4855 { 4856 int ret; 4857 4858 switch (object) { 4859 case DISCOVERY_ADDRESS: 4860 case ISNS_SERVER_ADDRESS: 4861 ret = removeAddress(object, operandLen, operand, 4862 funcRet); 4863 break; 4864 case STATIC_CONFIG: 4865 ret = removeStaticConfig(operandLen, operand, funcRet); 4866 break; 4867 case TARGET_PARAM: 4868 ret = removeTargetParam(operandLen, operand, funcRet); 4869 break; 4870 default: 4871 (void) fprintf(stderr, "%s: %s\n", 4872 cmdName, gettext("unknown object")); 4873 ret = 1; 4874 break; 4875 } 4876 return (ret); 4877 } 4878 4879 static void 4880 iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status) 4881 { 4882 switch (status) { 4883 case iSCSINameLenZero: 4884 (void) fprintf(stderr, "%s: %s\n", 4885 cmdName, gettext("empty iSCSI name.")); 4886 break; 4887 case iSCSINameLenExceededMax: 4888 (void) fprintf(stderr, "%s: %s\n", cmdName, 4889 gettext("iSCSI name exceeded maximum length.")); 4890 break; 4891 case iSCSINameUnknownType: 4892 (void) fprintf(stderr, "%s: %s\n", cmdName, 4893 gettext("unknown iSCSI name type.")); 4894 break; 4895 case iSCSINameInvalidCharacter: 4896 (void) fprintf(stderr, "%s: %s\n", 4897 cmdName, 4898 gettext("iSCSI name invalid character used")); 4899 break; 4900 case iSCSINameIqnFormatError: 4901 (void) fprintf(stderr, "%s: %s\n", cmdName, 4902 gettext("iqn formatting error.")); 4903 break; 4904 case iSCSINameIqnDateFormatError: 4905 (void) fprintf(stderr, "%s: %s\n", 4906 cmdName, gettext("invalid iqn date." \ 4907 " format is: YYYY-MM")); 4908 break; 4909 case iSCSINameIqnSubdomainFormatError: 4910 (void) fprintf(stderr, "%s: %s\n", 4911 cmdName, gettext("missing subdomain after \":\"")); 4912 break; 4913 case iSCSINameIqnInvalidYearError: 4914 (void) fprintf(stderr, "%s: %s\n", 4915 cmdName, gettext("invalid year")); 4916 break; 4917 case iSCSINameIqnInvalidMonthError: 4918 (void) fprintf(stderr, "%s: %s\n", 4919 cmdName, gettext("invalid month")); 4920 break; 4921 case iSCSINameIqnFQDNError: 4922 (void) fprintf(stderr, "%s: %s\n", 4923 cmdName, gettext("missing reversed fully qualified"\ 4924 " domain name")); 4925 break; 4926 case iSCSINameEUIFormatError: 4927 (void) fprintf(stderr, "%s: %s\n", cmdName, 4928 gettext("eui formatting error.")); 4929 break; 4930 } 4931 } 4932 4933 /* 4934 * A convenient function to modify the target parameters of an individual 4935 * target. 4936 * 4937 * Return 0 if successful 4938 * Return 1 if failed 4939 */ 4940 static int 4941 modifyIndividualTargetParam(cmdOptions_t *optionList, IMA_OID targetOid, 4942 int *funcRet) 4943 { 4944 assert(funcRet != NULL); 4945 4946 for (; optionList->optval; optionList++) { 4947 switch (optionList->optval) { 4948 case 'a': 4949 if (modifyTargetAuthMethod(targetOid, 4950 optionList->optarg, funcRet) != 0) { 4951 return (1); 4952 } 4953 break; 4954 case 'B': 4955 if (modifyTargetBidirAuthFlag(targetOid, 4956 optionList->optarg, funcRet) != 0) { 4957 return (1); 4958 } 4959 break; 4960 case 'C': 4961 if (modifyTargetAuthParam(targetOid, 4962 AUTH_PASSWORD, NULL, funcRet) != 0) { 4963 return (1); 4964 } 4965 break; 4966 case 'd': 4967 if (setLoginParameter(targetOid, DATA_DIGEST, 4968 optionList->optarg) != 0) { 4969 return (1); 4970 } 4971 break; 4972 case 'h': 4973 if (setLoginParameter(targetOid, HEADER_DIGEST, 4974 optionList->optarg) != 0) { 4975 return (1); 4976 } 4977 break; 4978 case 'p': 4979 /* Login parameter */ 4980 if (setLoginParameters(targetOid, 4981 optionList->optarg) != 0) { 4982 return (1); 4983 } 4984 break; 4985 case 'c': 4986 /* Modify configure sessions */ 4987 if (modifyConfiguredSessions(targetOid, 4988 optionList->optarg) != 0) { 4989 return (1); 4990 } 4991 break; 4992 case 'H': 4993 if (modifyTargetAuthParam(targetOid, AUTH_NAME, 4994 optionList->optarg, funcRet) != 0) { 4995 return (1); 4996 } 4997 break; 4998 case 'T': 4999 if (setTunableParameters(targetOid, 5000 optionList->optarg) != 0) { 5001 return (1); 5002 } 5003 break; 5004 } 5005 } 5006 5007 return (0); 5008 } 5009 5010 /* 5011 * This helper function could go into a utility module for general use. 5012 */ 5013 static int 5014 parseAddress(char *address_port_str, 5015 uint16_t defaultPort, 5016 char *address_str, 5017 size_t address_str_len, 5018 uint16_t *port, 5019 boolean_t *isIpv6) 5020 { 5021 char port_str[64]; 5022 int tmp_port; 5023 char *errchr; 5024 5025 if (address_port_str[0] == '[') { 5026 /* IPv6 address */ 5027 char *close_bracket_pos; 5028 close_bracket_pos = strchr(address_port_str, ']'); 5029 if (!close_bracket_pos) { 5030 syslog(LOG_USER|LOG_DEBUG, 5031 "IP address format error: %s\n", address_str); 5032 return (PARSE_ADDR_MISSING_CLOSING_BRACKET); 5033 } 5034 5035 *close_bracket_pos = NULL; 5036 (void) strlcpy(address_str, &address_port_str[1], 5037 address_str_len); 5038 5039 /* Extract the port number */ 5040 close_bracket_pos++; 5041 if (*close_bracket_pos == ':') { 5042 close_bracket_pos++; 5043 if (*close_bracket_pos != NULL) { 5044 (void) strlcpy(port_str, close_bracket_pos, 64); 5045 tmp_port = strtol(port_str, &errchr, 10); 5046 if (tmp_port == 0 && errchr != NULL) { 5047 (void) fprintf(stderr, "%s: %s:%s %s\n", 5048 cmdName, address_str, 5049 close_bracket_pos, 5050 gettext("port number invalid")); 5051 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5052 } 5053 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 5054 (tmp_port < 0)) { 5055 /* Port number out of range */ 5056 syslog(LOG_USER|LOG_DEBUG, 5057 "Specified port out of range: %d", 5058 tmp_port); 5059 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5060 } else { 5061 *port = (uint16_t)tmp_port; 5062 } 5063 } else { 5064 *port = defaultPort; 5065 } 5066 } else { 5067 *port = defaultPort; 5068 } 5069 5070 *isIpv6 = B_TRUE; 5071 } else { 5072 /* IPv4 address */ 5073 char *colon_pos; 5074 colon_pos = strchr(address_port_str, ':'); 5075 if (!colon_pos) { 5076 /* No port number specified. */ 5077 *port = defaultPort; 5078 (void) strlcpy(address_str, address_port_str, 5079 address_str_len); 5080 } else { 5081 *colon_pos = (char)NULL; 5082 (void) strlcpy(address_str, address_port_str, 5083 address_str_len); 5084 5085 /* Extract the port number */ 5086 colon_pos++; 5087 if (*colon_pos != NULL) { 5088 5089 (void) strlcpy(port_str, colon_pos, 64); 5090 tmp_port = strtol(port_str, &errchr, 10); 5091 if (tmp_port == 0 && errchr != NULL) { 5092 (void) fprintf(stderr, "%s: %s:%s %s\n", 5093 cmdName, address_str, colon_pos, 5094 gettext("port number invalid")); 5095 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5096 } 5097 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 5098 (tmp_port < 0)) { 5099 /* Port number out of range */ 5100 syslog(LOG_USER|LOG_DEBUG, 5101 "Specified port out of range: %d", 5102 tmp_port); 5103 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5104 } else { 5105 *port = (uint16_t)tmp_port; 5106 } 5107 } else { 5108 *port = defaultPort; 5109 } 5110 } 5111 5112 *isIpv6 = B_FALSE; 5113 } 5114 5115 return (PARSE_ADDR_OK); 5116 } 5117 5118 /* 5119 * This helper function could go into a utility module for general use. 5120 */ 5121 iSCSINameCheckStatusType 5122 iSCSINameStringProfileCheck(wchar_t *name) 5123 { 5124 char mb_name[MAX_ISCSI_NAME_LEN + 1]; 5125 size_t name_len; 5126 char *tmp; 5127 5128 (void) wcstombs(mb_name, name, MAX_ISCSI_NAME_LEN + 1); 5129 5130 if ((name_len = strlen(mb_name)) == 0) { 5131 return (iSCSINameLenZero); 5132 } else if (name_len > MAX_ISCSI_NAME_LEN) { 5133 return (iSCSINameLenExceededMax); 5134 } 5135 5136 /* 5137 * check for invalid characters 5138 * According to RFC 3722 iSCSI name must be either a letter, 5139 * a digit or one of the following '-' '.' ':' 5140 */ 5141 for (tmp = mb_name; *tmp != NULL; tmp++) { 5142 if ((isalnum(*tmp) == 0) && 5143 (*tmp != '-') && 5144 (*tmp != '.') && 5145 (*tmp != ':')) { 5146 return (iSCSINameInvalidCharacter); 5147 } 5148 } 5149 5150 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 5151 strlen(ISCSI_IQN_NAME_PREFIX)) == 0) { 5152 /* 5153 * If name is of type iqn, check date string and naming 5154 * authority. 5155 */ 5156 char *strp = NULL; 5157 5158 /* 5159 * Don't allow the string to end with a colon. If there is a 5160 * colon then there must be a subdomain provided. 5161 */ 5162 if (mb_name[strlen(mb_name) - 1] == ':') { 5163 return (iSCSINameIqnSubdomainFormatError); 5164 } 5165 5166 /* Date string */ 5167 strp = strtok(&mb_name[3], "."); 5168 if (strp) { 5169 char tmpYear[5], tmpMonth[3], *endPtr = NULL; 5170 int year, month; 5171 5172 /* Date string should be in YYYY-MM format */ 5173 if (strlen(strp) != strlen("YYYY-MM") || 5174 strp[4] != '-') { 5175 return (iSCSINameIqnDateFormatError); 5176 } 5177 5178 /* 5179 * Validate year. Only validating that the 5180 * year can be converted to a number. No 5181 * validation will be done on year's actual 5182 * value. 5183 */ 5184 (void) strncpy(tmpYear, strp, 4); 5185 tmpYear[4] = '\0'; 5186 5187 errno = 0; 5188 year = strtol(tmpYear, &endPtr, 10); 5189 if (errno != 0 || *endPtr != '\0' || 5190 year < 0 || year > 9999) { 5191 return (iSCSINameIqnInvalidYearError); 5192 } 5193 5194 /* 5195 * Validate month is valid. 5196 */ 5197 (void) strncpy(tmpMonth, &strp[5], 2); 5198 tmpMonth[2] = '\0'; 5199 errno = 0; 5200 month = strtol(tmpMonth, &endPtr, 10); 5201 5202 if (errno != 0 || *endPtr != '\0' || 5203 month < 1 || month > 12) { 5204 return (iSCSINameIqnInvalidMonthError); 5205 } 5206 5207 /* 5208 * A reversed FQDN needs to be provided. We 5209 * will only check for a "." followed by more 5210 * than two or more characters. The list of domains is 5211 * too large and changes too frequently to 5212 * add validation for. 5213 */ 5214 strp = strtok(NULL, "."); 5215 if (!strp || strlen(strp) < 2) { 5216 return (iSCSINameIqnFQDNError); 5217 } 5218 5219 /* Name authority string */ 5220 strp = strtok(NULL, ":"); 5221 if (strp) { 5222 return (iSCSINameCheckOK); 5223 } else { 5224 return (iSCSINameIqnFQDNError); 5225 } 5226 } else { 5227 return (iSCSINameIqnFormatError); 5228 } 5229 } else if (strncmp(mb_name, ISCSI_EUI_NAME_PREFIX, 5230 strlen(ISCSI_EUI_NAME_PREFIX)) == 0) { 5231 /* If name is of type EUI, change its length */ 5232 5233 if (strlen(mb_name) != ISCSI_EUI_NAME_LEN) { 5234 return (iSCSINameEUIFormatError); 5235 } 5236 5237 for (tmp = mb_name + strlen(ISCSI_EUI_NAME_PREFIX) + 1; 5238 *tmp != '\0'; tmp++) { 5239 if (isxdigit(*tmp)) { 5240 continue; 5241 } 5242 return (iSCSINameEUIFormatError); 5243 } 5244 5245 return (iSCSINameCheckOK); 5246 } else { 5247 return (iSCSINameUnknownType); 5248 } 5249 } 5250 5251 /* 5252 * This helper function could go into a utility module for general use. 5253 * 5254 * Returns: 5255 * B_TRUE is the numberStr is an unsigned natural number and within the 5256 * specified bound. 5257 * B_FALSE otherwise. 5258 */ 5259 boolean_t 5260 isNaturalNumber(char *numberStr, uint32_t upperBound) 5261 { 5262 int i; 5263 int number_str_len; 5264 5265 if ((number_str_len = strlen(numberStr)) == 0) { 5266 return (B_FALSE); 5267 } 5268 5269 for (i = 0; i < number_str_len; i++) { 5270 if (numberStr[i] < 060 || numberStr[i] > 071) { 5271 return (B_FALSE); 5272 } 5273 } 5274 5275 if (atoi(numberStr) > upperBound) { 5276 return (B_FALSE); 5277 } 5278 5279 return (B_TRUE); 5280 } 5281 5282 /* 5283 * This helper function could go into a utility module for general use. 5284 * It parses a target string in the format of: 5285 * 5286 * <target_name>,[<ip_address>[:port][,tpgt]] 5287 * 5288 * and creates wchar strings for target name and target address. It 5289 * also populates port and tpgt if found. 5290 * 5291 * Returns: 5292 * PARSE_TARGET_OK if parsing is successful. 5293 * PARSE_TARGET_INVALID_TPGT if the specified tpgt is 5294 * invalid. 5295 * PARSE_TARGET_INVALID_ADDR if the address specified is 5296 * invalid. 5297 */ 5298 int 5299 parseTarget(char *targetStr, 5300 wchar_t *targetNameStr, 5301 size_t targetNameStrLen, 5302 boolean_t *targetAddressSpecified, 5303 wchar_t *targetAddressStr, 5304 size_t targetAddressStrLen, 5305 uint16_t *port, 5306 boolean_t *tpgtSpecified, 5307 uint16_t *tpgt, 5308 boolean_t *isIpv6) 5309 { 5310 char *commaPos; 5311 char *commaPos2; 5312 char targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 5313 int i; 5314 int lowerCase; 5315 5316 (void) memset(targetNameStr, 0, 5317 targetNameStrLen * sizeof (wchar_t)); 5318 (void) memset(targetAddressStr, 0, 5319 targetAddressStrLen * sizeof (wchar_t)); 5320 5321 commaPos = strchr(targetStr, ','); 5322 if (commaPos != NULL) { 5323 *commaPos = NULL; 5324 commaPos++; 5325 *targetAddressSpecified = B_TRUE; 5326 5327 /* 5328 * Checking of tpgt makes sense only when 5329 * the target address/port are specified. 5330 */ 5331 commaPos2 = strchr(commaPos, ','); 5332 if (commaPos2 != NULL) { 5333 *commaPos2 = NULL; 5334 commaPos2++; 5335 if (isNaturalNumber(commaPos2, ISCSI_MAX_TPGT_VALUE) == 5336 B_TRUE) { 5337 *tpgt = atoi(commaPos2); 5338 *tpgtSpecified = B_TRUE; 5339 } else { 5340 (void) fprintf(stderr, "%s: %s\n", cmdName, 5341 gettext("parse target invalid TPGT")); 5342 return (PARSE_TARGET_INVALID_TPGT); 5343 } 5344 } 5345 5346 switch (parseAddress(commaPos, ISCSI_LISTEN_PORT, 5347 &targetAddress[0], MAX_ADDRESS_LEN + 1, port, isIpv6)) { 5348 case PARSE_ADDR_PORT_OUT_OF_RANGE: 5349 return (PARSE_TARGET_INVALID_ADDR); 5350 case PARSE_ADDR_OK: 5351 break; 5352 default: 5353 (void) fprintf(stderr, "%s: %s\n", 5354 cmdName, gettext("cannot parse target name")); 5355 return (PARSE_TARGET_INVALID_ADDR); 5356 } 5357 (void) mbstowcs(targetAddressStr, targetAddress, 5358 targetAddressStrLen); 5359 for (i = 0; targetAddressStr[i] != 0; i++) { 5360 lowerCase = tolower(targetAddressStr[i]); 5361 targetAddressStr[i] = lowerCase; 5362 } 5363 } else { 5364 *targetAddressSpecified = B_FALSE; 5365 *tpgtSpecified = B_FALSE; 5366 } 5367 5368 (void) mbstowcs(targetNameStr, targetStr, targetNameStrLen); 5369 for (i = 0; targetNameStr[i] != 0; i++) { 5370 lowerCase = tolower(targetNameStr[i]); 5371 targetNameStr[i] = lowerCase; 5372 } 5373 5374 return (PARSE_TARGET_OK); 5375 } 5376 5377 /*ARGSUSED*/ 5378 static void 5379 listCHAPName(IMA_OID oid) 5380 { 5381 IMA_INITIATOR_AUTHPARMS authParams; 5382 IMA_STATUS status; 5383 IMA_BYTE chapName [MAX_CHAP_NAME_LEN + 1]; 5384 5385 /* Get Chap Name depending upon oid object type */ 5386 if (oid.objectType == IMA_OBJECT_TYPE_LHBA) { 5387 status = IMA_GetInitiatorAuthParms(oid, 5388 IMA_AUTHMETHOD_CHAP, &authParams); 5389 } else { 5390 status = SUN_IMA_GetTargetAuthParms(oid, 5391 IMA_AUTHMETHOD_CHAP, &authParams); 5392 } 5393 5394 (void) fprintf(stdout, "\n\t\t%s: ", gettext("CHAP Name")); 5395 5396 if (IMA_SUCCESS(status)) { 5397 /* 5398 * Default chap name will be the node name. The default will 5399 * be set by the driver. 5400 */ 5401 if (authParams.chapParms.nameLength != 0) { 5402 (void) memset(chapName, 0, sizeof (chapName)); 5403 (void) memcpy(chapName, authParams.chapParms.name, 5404 authParams.chapParms.nameLength); 5405 (void) fprintf(stdout, "%s", chapName); 5406 5407 } else { 5408 (void) fprintf(stdout, "%s", "-"); 5409 } 5410 } else { 5411 (void) fprintf(stdout, "%s", "-"); 5412 } 5413 } 5414 5415 static boolean_t 5416 checkServiceStatus(void) 5417 { 5418 IMA_STATUS status = IMA_ERROR_UNKNOWN_ERROR; 5419 IMA_BOOL enabled = 0; 5420 5421 status = SUN_IMA_GetSvcStatus(&enabled); 5422 5423 if (status != IMA_STATUS_SUCCESS) { 5424 (void) fprintf(stdout, "%s\n%s\n", 5425 gettext("Unable to query the service status of" 5426 " iSCSI initiator."), 5427 gettext("For more information, please refer to" 5428 " iscsi(7D).")); 5429 return (B_FALSE); 5430 } 5431 5432 if (enabled == 0) { 5433 (void) fprintf(stdout, "%s\n%s\n", 5434 gettext("iSCSI Initiator Service is disabled," 5435 " try 'svcadm enable network/iscsi/initiator' to" 5436 " enable the service."), 5437 gettext("For more information, please refer to" 5438 " iscsi(7D).")); 5439 return (B_FALSE); 5440 } 5441 5442 return (B_TRUE); 5443 } 5444 5445 /* 5446 * Prints out see manual page. 5447 * Called out through atexit(3C) so is always last thing displayed. 5448 */ 5449 void 5450 seeMan(void) 5451 { 5452 static int sent = 0; 5453 5454 if (sent) 5455 return; 5456 5457 (void) fprintf(stdout, "%s %s(1M)\n", 5458 gettext("For more information, please see"), cmdName); 5459 5460 sent = 1; 5461 } 5462 5463 5464 /* 5465 * main calls a parser that checks syntax of the input command against 5466 * various rules tables. 5467 * 5468 * The parser provides usage feedback based upon same tables by calling 5469 * two usage functions, usage and subUsage, handling command and subcommand 5470 * usage respectively. 5471 * 5472 * The parser handles all printing of usage syntactical errors 5473 * 5474 * When syntax is successfully validated, the parser calls the associated 5475 * function using the subcommands table functions. 5476 * 5477 * Syntax is as follows: 5478 * command subcommand [options] resource-type [<object>] 5479 * 5480 * The return value from the function is placed in funcRet 5481 */ 5482 int 5483 main(int argc, char *argv[]) 5484 { 5485 synTables_t synTables; 5486 char versionString[VERSION_STRING_MAX_LEN]; 5487 int ret; 5488 int funcRet = 0; 5489 void *subcommandArgs = NULL; 5490 5491 if (geteuid() != 0) { 5492 (void) fprintf(stderr, "%s\n", gettext("permission denied")); 5493 return (1); 5494 } 5495 5496 if (checkServiceStatus() == B_FALSE) { 5497 return (1); 5498 } 5499 5500 /* set global command name */ 5501 cmdName = getExecBasename(argv[0]); 5502 5503 (void) snprintf(versionString, sizeof (versionString), "%s.%s", 5504 VERSION_STRING_MAJOR, VERSION_STRING_MINOR); 5505 synTables.versionString = versionString; 5506 synTables.longOptionTbl = &longOptions[0]; 5507 synTables.subcommandTbl = &subcommands[0]; 5508 synTables.objectTbl = &objects[0]; 5509 synTables.objectRulesTbl = &objectRules[0]; 5510 synTables.optionRulesTbl = &optionRules[0]; 5511 5512 /* call the CLI parser */ 5513 ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); 5514 if (ret == -1) { 5515 perror(cmdName); 5516 ret = 1; 5517 } 5518 5519 if (funcRet != 0) { 5520 (void) fprintf(stderr, "%s: %s\n", 5521 cmdName, gettext("Unable to complete operation")); 5522 ret = 1; 5523 } 5524 return (ret); 5525 } 5526 5527 static int 5528 setTunableParameters(IMA_OID oid, char *optarg) 5529 { 5530 char keyp[MAXOPTARGLEN]; 5531 char valp[MAXOPTARGLEN]; 5532 int key; 5533 IMA_STATUS status; 5534 IMA_UINT uintValue; 5535 ISCSI_TUNABLE_PARAM tunableObj; 5536 char *nameValueString, *endptr; 5537 5538 if ((nameValueString = strdup(optarg)) == NULL) { 5539 if (errno == ENOMEM) { 5540 (void) fprintf(stderr, "%s: %s\n", 5541 cmdName, strerror(errno)); 5542 } else { 5543 (void) fprintf(stderr, "%s: %s\n", cmdName, 5544 gettext("unknown error")); 5545 } 5546 return (1); 5547 } 5548 5549 (void) memset(keyp, 0, sizeof (keyp)); 5550 (void) memset(valp, 0, sizeof (valp)); 5551 if (sscanf(nameValueString, gettext("%[^=]=%s"), keyp, valp) != 2) { 5552 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5553 gettext("Unknown param"), nameValueString); 5554 if (nameValueString) { 5555 free(nameValueString); 5556 nameValueString = NULL; 5557 } 5558 return (1); 5559 } 5560 if ((key = getTunableParam(keyp)) == -1) { 5561 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5562 gettext("Unknown key"), keyp); 5563 if (nameValueString) { 5564 free(nameValueString); 5565 nameValueString = NULL; 5566 } 5567 return (1); 5568 } 5569 switch (key) { 5570 case RECV_LOGIN_RSP_TIMEOUT: 5571 case CONN_LOGIN_MAX: 5572 case POLLING_LOGIN_DELAY: 5573 errno = 0; 5574 uintValue = strtoul(valp, &endptr, 0); 5575 if (*endptr != '\0' || errno != 0) { 5576 (void) fprintf(stderr, "%s: %s - %s\n", 5577 cmdName, 5578 gettext("invalid option argument"), 5579 optarg); 5580 if (nameValueString) { 5581 free(nameValueString); 5582 nameValueString = NULL; 5583 } 5584 return (1); 5585 } 5586 if (uintValue > 3600) { 5587 (void) fprintf(stderr, "%s: %s\n", 5588 cmdName, 5589 gettext("value must be between 0 and 3600")); 5590 if (nameValueString) { 5591 free(nameValueString); 5592 nameValueString = NULL; 5593 } 5594 return (1); 5595 } 5596 5597 if (chkConnLoginMaxPollingLoginDelay(oid, key, uintValue) > 0) { 5598 if (nameValueString) { 5599 free(nameValueString); 5600 nameValueString = NULL; 5601 } 5602 return (1); 5603 } 5604 5605 if (key == RECV_LOGIN_RSP_TIMEOUT) { 5606 tunableObj.tunable_objectType = 5607 ISCSI_RX_TIMEOUT_VALUE; 5608 } else if (key == CONN_LOGIN_MAX) { 5609 tunableObj.tunable_objectType = 5610 ISCSI_CONN_DEFAULT_LOGIN_MAX; 5611 } else if (key == POLLING_LOGIN_DELAY) { 5612 tunableObj.tunable_objectType = 5613 ISCSI_LOGIN_POLLING_DELAY; 5614 } 5615 tunableObj.tunable_objectValue = valp; 5616 status = SUN_IMA_SetTunableProperties(oid, &tunableObj); 5617 break; 5618 default: 5619 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5620 gettext("Unsupported key"), keyp); 5621 if (nameValueString) { 5622 free(nameValueString); 5623 nameValueString = NULL; 5624 } 5625 return (1); 5626 } 5627 if (!IMA_SUCCESS(status)) { 5628 printLibError(status); 5629 if (nameValueString) { 5630 free(nameValueString); 5631 nameValueString = NULL; 5632 } 5633 return (1); 5634 } 5635 5636 if (nameValueString) { 5637 free(nameValueString); 5638 nameValueString = NULL; 5639 } 5640 return (0); 5641 } 5642 5643 /* 5644 * Print tunable parameters information 5645 */ 5646 static int 5647 printTunableParameters(IMA_OID oid) 5648 { 5649 ISCSI_TUNABLE_PARAM tunableObj; 5650 char value[MAXOPTARGLEN] = "\0"; 5651 IMA_STATUS status; 5652 5653 tunableObj.tunable_objectValue = value; 5654 (void) fprintf(stdout, "\t%s:\n", 5655 gettext("Tunable Parameters (Default/Configured)")); 5656 tunableObj.tunable_objectType = ISCSI_RX_TIMEOUT_VALUE; 5657 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5658 if (!IMA_SUCCESS(status)) { 5659 printLibError(status); 5660 return (1); 5661 } 5662 if (value[0] == '\0') { 5663 value[0] = '-'; 5664 value[1] = '\0'; 5665 } 5666 (void) fprintf(stdout, "\t\t%s: ", 5667 gettext("Session Login Response Time")); 5668 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_RX_TIMEOUT_VALUE, 5669 tunableObj.tunable_objectValue); 5670 5671 value[0] = '\0'; 5672 tunableObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX; 5673 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5674 if (!IMA_SUCCESS(status)) { 5675 printLibError(status); 5676 return (1); 5677 } 5678 if (value[0] == '\0') { 5679 value[0] = '-'; 5680 value[1] = '\0'; 5681 } 5682 (void) fprintf(stdout, "\t\t%s: ", 5683 gettext("Maximum Connection Retry Time")); 5684 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX, 5685 tunableObj.tunable_objectValue); 5686 5687 value[0] = '\0'; 5688 tunableObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY; 5689 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5690 if (!IMA_SUCCESS(status)) { 5691 printLibError(status); 5692 return (1); 5693 } 5694 if (value[0] == '\0') { 5695 value[0] = '-'; 5696 value[1] = '\0'; 5697 } 5698 (void) fprintf(stdout, "\t\t%s: ", 5699 gettext("Login Retry Time Interval")); 5700 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_LOGIN_POLLING_DELAY, 5701 tunableObj.tunable_objectValue); 5702 return (0); 5703 } 5704 5705 /* 5706 * This is helper function to check conn_login_max and polling_login_delay. 5707 */ 5708 static int 5709 chkConnLoginMaxPollingLoginDelay(IMA_OID oid, int key, int uintValue) 5710 { 5711 char valuep[MAXOPTARGLEN]; 5712 IMA_STATUS status; 5713 IMA_UINT getValue; 5714 ISCSI_TUNABLE_PARAM getObj; 5715 char *endptr; 5716 5717 if (key == CONN_LOGIN_MAX) { 5718 getObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY; 5719 } else { 5720 getObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX; 5721 } 5722 valuep[0] = '\0'; 5723 getObj.tunable_objectValue = valuep; 5724 status = SUN_IMA_GetTunableProperties(oid, &getObj); 5725 if (!IMA_SUCCESS(status)) { 5726 printLibError(status); 5727 return (1); 5728 } 5729 if (valuep[0] == '\0') { 5730 if (key == CONN_LOGIN_MAX) { 5731 (void) strlcpy(valuep, 5732 ISCSI_DEFAULT_LOGIN_POLLING_DELAY, 5733 strlen(ISCSI_DEFAULT_LOGIN_POLLING_DELAY) +1); 5734 } else { 5735 (void) strlcpy(valuep, 5736 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX, 5737 strlen(ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX) +1); 5738 } 5739 } 5740 5741 errno = 0; 5742 getValue = strtoul(valuep, &endptr, 0); 5743 if (*endptr != '\0' || errno != 0) { 5744 (void) fprintf(stderr, "%s: %s - %s\n", 5745 cmdName, 5746 gettext("cannot convert tunable string"), 5747 valuep); 5748 return (1); 5749 } 5750 if (key == CONN_LOGIN_MAX) { 5751 if (uintValue < getValue) { 5752 (void) fprintf(stderr, "%s: %s %ld\n", 5753 cmdName, gettext("value must larger than"), 5754 getValue); 5755 return (1); 5756 } 5757 } else { 5758 if (uintValue > getValue) { 5759 (void) fprintf(stderr, "%s: %s %ld\n", 5760 cmdName, gettext("value must smaller than"), 5761 getValue); 5762 return (1); 5763 } 5764 } 5765 return (0); 5766 } 5767