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