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 * befgijklmnoquwxyz 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 (void) fprintf(stdout, "\tLUN: %lld\n", 1488 lunProps.imaProps.targetLun); 1489 (void) fprintf(stdout, "\t Vendor: %s\n", 1490 lunProps.vendorId); 1491 (void) fprintf(stdout, "\t Product: %s\n", 1492 lunProps.productId); 1493 /* 1494 * The lun is valid though the os Device Name is not. 1495 * Give this information to users for judgement. 1496 */ 1497 if (lunProps.imaProps.osDeviceNameValid == IMA_TRUE) { 1498 (void) fprintf(stdout, 1499 gettext("\t OS Device Name: %ws\n"), 1500 lunProps.imaProps.osDeviceName); 1501 } else { 1502 (void) fprintf(stdout, 1503 gettext("\t OS Device Name: Not" 1504 " Available\n")); 1505 } 1506 } 1507 } 1508 1509 /* 1510 * Retrieve CHAP secret from input 1511 */ 1512 static int 1513 getSecret(char *secret, int *secretLen, int minSecretLen, int maxSecretLen) 1514 { 1515 char *chapSecret; 1516 1517 /* get password */ 1518 chapSecret = getpassphrase(gettext("Enter secret:")); 1519 1520 if (chapSecret == NULL) { 1521 (void) fprintf(stderr, "%s: %s\n", cmdName, 1522 gettext("Unable to get secret")); 1523 *secret = NULL; 1524 return (1); 1525 } 1526 1527 if (strlen(chapSecret) > maxSecretLen) { 1528 (void) fprintf(stderr, "%s: %s %d\n", cmdName, 1529 gettext("secret too long, maximum length is"), 1530 maxSecretLen); 1531 *secret = NULL; 1532 return (1); 1533 } 1534 1535 if (strlen(chapSecret) < minSecretLen) { 1536 (void) fprintf(stderr, "%s: %s %d\n", cmdName, 1537 gettext("secret too short, minimum length is"), 1538 minSecretLen); 1539 *secret = NULL; 1540 return (1); 1541 } 1542 1543 (void) strcpy(secret, chapSecret); 1544 1545 chapSecret = getpassphrase(gettext("Re-enter secret:")); 1546 1547 if (chapSecret == NULL) { 1548 (void) fprintf(stderr, "%s: %s\n", cmdName, 1549 gettext("Unable to get secret")); 1550 *secret = NULL; 1551 return (1); 1552 } 1553 1554 if (strcmp(secret, chapSecret) != 0) { 1555 (void) fprintf(stderr, "%s: %s\n", cmdName, 1556 gettext("secrets do not match, secret not changed")); 1557 *secret = NULL; 1558 return (1); 1559 } 1560 *secretLen = strlen(chapSecret); 1561 return (0); 1562 } 1563 1564 /* 1565 * Lists the discovery attributes 1566 */ 1567 static int 1568 listDiscovery(int *funcRet) 1569 { 1570 IMA_OID initiatorOid; 1571 IMA_DISCOVERY_PROPERTIES discProps; 1572 int ret; 1573 IMA_STATUS status; 1574 1575 assert(funcRet != NULL); 1576 1577 1578 /* Find Sun initiator */ 1579 ret = sunInitiatorFind(&initiatorOid); 1580 if (ret > 0) { 1581 (void) fprintf(stderr, "%s: %s\n", 1582 cmdName, gettext("no initiator found")); 1583 } 1584 1585 if (ret != 0) { 1586 return (ret); 1587 } 1588 1589 /* Get discovery attributes from IMA */ 1590 status = IMA_GetDiscoveryProperties(initiatorOid, &discProps); 1591 if (!IMA_SUCCESS(status)) { 1592 printLibError(status); 1593 *funcRet = 1; 1594 return (ret); 1595 } 1596 1597 1598 (void) fprintf(stdout, "%s:\n", "Discovery"); 1599 (void) fprintf(stdout, "\tStatic: %s\n", 1600 discProps.staticDiscoveryEnabled == IMA_TRUE ? \ 1601 gettext("enabled") : gettext("disabled")); 1602 (void) fprintf(stdout, "\tSend Targets: %s\n", 1603 discProps.sendTargetsDiscoveryEnabled == IMA_TRUE ? \ 1604 gettext("enabled") : gettext("disabled")); 1605 (void) fprintf(stdout, "\tiSNS: %s\n", 1606 discProps.iSnsDiscoveryEnabled == IMA_TRUE ? \ 1607 gettext("enabled") : gettext("disabled")); 1608 1609 return (0); 1610 } 1611 1612 /* 1613 * Print all initiator node attributes 1614 */ 1615 static int 1616 listNode(int *funcRet) 1617 { 1618 IMA_OID initiatorOid; 1619 IMA_NODE_PROPERTIES nodeProps; 1620 IMA_STATUS status; 1621 int ret; 1622 IMA_UINT maxEntries = MAX_AUTH_METHODS; 1623 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 1624 SUN_IMA_RADIUS_CONFIG radiusConfig; 1625 SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms; 1626 IMA_BOOL radiusAccess; 1627 1628 int i; 1629 1630 assert(funcRet != NULL); 1631 1632 ret = getNodeProps(&nodeProps); 1633 if (ret != 0) { 1634 return (ret); 1635 } 1636 1637 if (nodeProps.nameValid == IMA_FALSE) { 1638 return (INVALID_NODE_NAME); 1639 } 1640 1641 /* Find Sun initiator */ 1642 ret = sunInitiatorFind(&initiatorOid); 1643 if (ret > 0) { 1644 (void) fprintf(stderr, "%s: %s\n", 1645 cmdName, gettext("no initiator found")); 1646 } 1647 1648 if (ret != 0) { 1649 return (ret); 1650 } 1651 /* Begin output */ 1652 (void) fprintf(stdout, gettext("%s: %ws\n"), 1653 gettext("Initiator node name"), 1654 nodeProps.name); 1655 (void) fprintf(stdout, gettext("Initiator node alias: ")); 1656 if (nodeProps.aliasValid == IMA_TRUE) { 1657 (void) fprintf(stdout, gettext("%ws\n"), nodeProps.alias); 1658 } else { 1659 (void) fprintf(stdout, "%s\n", "-"); 1660 } 1661 (void) fprintf(stdout, "\t%s:\n", 1662 gettext("Login Parameters (Default/Configured)")); 1663 1664 /* Get Digest configuration */ 1665 status = SUN_IMA_GetHeaderDigest(initiatorOid, &digestAlgorithms); 1666 if (IMA_SUCCESS(status)) { 1667 (void) fprintf(stdout, "\t\t%s: ", gettext("Header Digest")); 1668 printDigestAlgorithm(&digestAlgorithms, 1669 PRINT_CONFIGURED_PARAMS); 1670 } else { 1671 printLibError(status); 1672 *funcRet = 1; 1673 return (ret); 1674 } 1675 1676 status = SUN_IMA_GetDataDigest(initiatorOid, &digestAlgorithms); 1677 if (IMA_SUCCESS(status)) { 1678 (void) fprintf(stdout, "\t\t%s: ", gettext("Data Digest")); 1679 printDigestAlgorithm(&digestAlgorithms, 1680 PRINT_CONFIGURED_PARAMS); 1681 } else { 1682 printLibError(status); 1683 *funcRet = 1; 1684 return (ret); 1685 } 1686 1687 /* Get authentication type for this lhba */ 1688 status = IMA_GetInUseInitiatorAuthMethods(initiatorOid, &maxEntries, 1689 &methodList[0]); 1690 (void) fprintf(stdout, "\t%s: ", gettext("Authentication Type")); 1691 if (!IMA_SUCCESS(status)) { 1692 /* No authentication method set - default is NONE */ 1693 (void) fprintf(stdout, gettext("NONE")); 1694 } else { 1695 for (i = 0; i < maxEntries; i++) { 1696 if (i > 0) { 1697 (void) fprintf(stdout, "|"); 1698 } 1699 switch (methodList[i]) { 1700 case IMA_AUTHMETHOD_NONE: 1701 (void) fprintf(stdout, gettext("NONE")); 1702 break; 1703 case IMA_AUTHMETHOD_CHAP: 1704 (void) fprintf(stdout, gettext("CHAP")); 1705 listCHAPName(initiatorOid); 1706 break; 1707 default: 1708 (void) fprintf(stdout, 1709 gettext("unknown type")); 1710 break; 1711 } 1712 } 1713 } 1714 (void) fprintf(stdout, "\n"); 1715 1716 1717 /* Get RADIUS configuration */ 1718 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 1719 (void) fprintf(stdout, "\t%s: ", gettext("RADIUS Server")); 1720 if (IMA_SUCCESS(status)) { 1721 if (strlen(radiusConfig.hostnameIpAddress) > 0) { 1722 (void) fprintf(stdout, "%s:%d", 1723 radiusConfig.hostnameIpAddress, 1724 radiusConfig.port); 1725 } else { 1726 (void) fprintf(stdout, "%s", gettext("NONE")); 1727 } 1728 } else { 1729 (void) fprintf(stdout, "%s", gettext("NONE")); 1730 } 1731 (void) fprintf(stdout, "\n"); 1732 1733 status = SUN_IMA_GetInitiatorRadiusAccess(initiatorOid, 1734 &radiusAccess); 1735 (void) fprintf(stdout, "\t%s: ", gettext("RADIUS Access")); 1736 if (IMA_SUCCESS(status)) { 1737 if (radiusAccess == IMA_TRUE) { 1738 (void) fprintf(stdout, "%s", gettext("enabled")); 1739 } else { 1740 (void) fprintf(stdout, "%s", gettext("disabled")); 1741 } 1742 } else if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 1743 (void) fprintf(stdout, "%s", gettext("disabled")); 1744 } else { 1745 (void) fprintf(stdout, "%s", gettext("unknown")); 1746 } 1747 (void) fprintf(stdout, "\n"); 1748 1749 /* print tunable parameters information. */ 1750 ret = printTunableParameters(initiatorOid); 1751 1752 /* print configured session information. */ 1753 ret = printConfiguredSessions(initiatorOid); 1754 1755 return (ret); 1756 } 1757 1758 /* 1759 * Print discovery addresses 1760 */ 1761 static int 1762 listDiscoveryAddress(int objectLen, char *objects[], cmdOptions_t *options, 1763 int *funcRet) 1764 { 1765 IMA_OID initiatorOid; 1766 SUN_IMA_DISC_ADDR_PROP_LIST *discoveryAddressPropertiesList; 1767 IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps; 1768 IMA_TARGET_ADDRESS address; 1769 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList; 1770 IMA_STATUS status; 1771 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 1772 int ret; 1773 boolean_t object = B_FALSE; 1774 int outerLoop; 1775 boolean_t found; 1776 boolean_t verbose = B_FALSE; 1777 int i, j; 1778 cmdOptions_t *optionList = options; 1779 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 1780 1781 assert(funcRet != NULL); 1782 1783 /* Find Sun initiator */ 1784 ret = sunInitiatorFind(&initiatorOid); 1785 if (ret > 0) { 1786 (void) fprintf(stderr, "%s: %s\n", 1787 cmdName, gettext("no initiator found")); 1788 } 1789 1790 if (ret != 0) { 1791 return (ret); 1792 } 1793 1794 for (; optionList->optval; optionList++) { 1795 switch (optionList->optval) { 1796 case 'v': 1797 verbose = B_TRUE; 1798 break; 1799 default: 1800 (void) fprintf(stderr, "%s: %c: %s\n", 1801 cmdName, optionList->optval, 1802 gettext("unknown option")); 1803 return (1); 1804 } 1805 } 1806 1807 /* 1808 * If there are multiple objects, execute outer 'for' loop that 1809 * many times for each target detail, otherwise, execute it only 1810 * once with summaries only 1811 */ 1812 if (objectLen > 0) { 1813 object = B_TRUE; 1814 outerLoop = objectLen; 1815 } else { 1816 object = B_FALSE; 1817 outerLoop = 1; 1818 } 1819 1820 status = SUN_IMA_GetDiscoveryAddressPropertiesList( 1821 &discoveryAddressPropertiesList); 1822 if (!IMA_SUCCESS(status)) { 1823 printLibError(status); 1824 *funcRet = 1; 1825 return (ret); 1826 } 1827 1828 for (i = 0; i < outerLoop; i++) { 1829 if (object) { 1830 /* initialize */ 1831 (void) memset(&wcInputObject[0], 0, 1832 sizeof (wcInputObject)); 1833 (void) memset(&address, 0, sizeof (address)); 1834 if (mbstowcs(wcInputObject, objects[i], 1835 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 1836 (void) fprintf(stderr, "%s: %s\n", 1837 cmdName, 1838 gettext("conversion error")); 1839 ret = 1; 1840 continue; 1841 } 1842 1843 /* 1844 * if one or more objects were input, 1845 * get the values 1846 */ 1847 if (getTargetAddress(DISCOVERY_ADDRESS, 1848 objects[i], &address) != 0) { 1849 ret = 1; 1850 continue; 1851 } 1852 } 1853 for (found = B_FALSE, j = 0; 1854 j < discoveryAddressPropertiesList->discAddrCount; 1855 j++) { 1856 discAddrProps = 1857 discoveryAddressPropertiesList->props[j]; 1858 1859 /* 1860 * Compare the discovery address with the input if 1861 * one was input 1862 */ 1863 if (object && 1864 ipAddressesEqual(discAddrProps.discoveryAddress, 1865 address) && (discAddrProps.discoveryAddress. 1866 portNumber == address.portNumber)) { 1867 found = B_TRUE; 1868 } 1869 1870 if (!object || found) { 1871 /* Print summary - always */ 1872 if (discAddrProps.discoveryAddress. 1873 hostnameIpAddress.id.ipAddress. 1874 ipv4Address) { 1875 (void) inet_ntop(AF_INET, discAddrProps. 1876 discoveryAddress.hostnameIpAddress. 1877 id.ipAddress.ipAddress, sAddr, 1878 sizeof (sAddr)); 1879 (void) fprintf(stdout, 1880 "Discovery Address: %s:%u\n", 1881 sAddr, discAddrProps. 1882 discoveryAddress.portNumber); 1883 } else { 1884 (void) inet_ntop(AF_INET6, 1885 discAddrProps. 1886 discoveryAddress.hostnameIpAddress. 1887 id.ipAddress.ipAddress, sAddr, 1888 sizeof (sAddr)); 1889 (void) fprintf(stdout, 1890 "DiscoveryAddress: [%s]:%u\n", 1891 sAddr, discAddrProps. 1892 discoveryAddress.portNumber); 1893 } 1894 } 1895 1896 if ((!object || found) && verbose) { 1897 IMA_NODE_PROPERTIES nodeProps; 1898 1899 if (getNodeProps(&nodeProps) != 0) { 1900 break; 1901 } 1902 1903 /* 1904 * Issue sendTargets only when an addr is 1905 * specified. 1906 */ 1907 status = SUN_IMA_SendTargets(nodeProps.name, 1908 discAddrProps.discoveryAddress, &pList); 1909 if (!IMA_SUCCESS(status)) { 1910 (void) fprintf(stderr, "%s\n", 1911 gettext("\tUnable to get "\ 1912 "targets.")); 1913 *funcRet = 1; 1914 continue; 1915 } 1916 printSendTargets(pList); 1917 } 1918 1919 if (found) { 1920 /* we found the discovery address - break */ 1921 break; 1922 } 1923 } 1924 /* 1925 * There was an object entered but we didn't 1926 * find it. 1927 */ 1928 if (object && !found) { 1929 (void) fprintf(stdout, "%s: %s\n", 1930 objects[i], gettext("not found")); 1931 } 1932 } 1933 return (ret); 1934 } 1935 1936 /* 1937 * Print ISNS Server addresses 1938 */ 1939 static int 1940 listISNSServerAddress(int objectLen, char *objects[], cmdOptions_t *options, 1941 int *funcRet) 1942 { 1943 IMA_OID initiatorOid; 1944 SUN_IMA_DISC_ADDR_PROP_LIST *discoveryAddressPropertiesList; 1945 IMA_DISCOVERY_ADDRESS_PROPERTIES discAddrProps; 1946 IMA_TARGET_ADDRESS address; 1947 SUN_IMA_DISC_ADDRESS_KEY_PROPERTIES *pList; 1948 IMA_STATUS status; 1949 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 1950 int ret; 1951 boolean_t object = B_FALSE; 1952 int outerLoop; 1953 boolean_t found; 1954 boolean_t showTarget = B_FALSE; 1955 int i, j; 1956 cmdOptions_t *optionList = options; 1957 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 1958 1959 assert(funcRet != NULL); 1960 1961 /* Find Sun initiator */ 1962 ret = sunInitiatorFind(&initiatorOid); 1963 if (ret > 0) { 1964 (void) fprintf(stderr, "%s: %s\n", 1965 cmdName, gettext("no initiator found")); 1966 } 1967 1968 if (ret != 0) { 1969 return (ret); 1970 } 1971 1972 for (; optionList->optval; optionList++) { 1973 switch (optionList->optval) { 1974 case 'v': 1975 showTarget = B_TRUE; 1976 break; 1977 default: 1978 (void) fprintf(stderr, "%s: %c: %s\n", 1979 cmdName, optionList->optval, 1980 gettext("unknown option")); 1981 return (1); 1982 } 1983 } 1984 1985 /* 1986 * If there are multiple objects, execute outer 'for' loop that 1987 * many times for each target detail, otherwise, execute it only 1988 * once with summaries only 1989 */ 1990 if (objectLen > 0) { 1991 object = B_TRUE; 1992 outerLoop = objectLen; 1993 } else { 1994 object = B_FALSE; 1995 outerLoop = 1; 1996 } 1997 1998 status = SUN_IMA_GetISNSServerAddressPropertiesList( 1999 &discoveryAddressPropertiesList); 2000 if (!IMA_SUCCESS(status)) { 2001 printLibError(status); 2002 *funcRet = 1; 2003 return (ret); 2004 } 2005 2006 for (i = 0; i < outerLoop; i++) { 2007 if (object) { 2008 /* initialize */ 2009 (void) memset(&wcInputObject[0], 0, 2010 sizeof (wcInputObject)); 2011 (void) memset(&address, 0, sizeof (address)); 2012 if (mbstowcs(wcInputObject, objects[i], 2013 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 2014 (void) fprintf(stderr, "%s: %s\n", 2015 cmdName, 2016 gettext("conversion error")); 2017 ret = 1; 2018 continue; 2019 } 2020 2021 /* 2022 * if one or more objects were input, 2023 * get the values 2024 */ 2025 if (getTargetAddress(ISNS_SERVER_ADDRESS, 2026 objects[i], &address) != 0) { 2027 ret = 1; 2028 continue; 2029 } 2030 } 2031 for (found = B_FALSE, j = 0; 2032 j < discoveryAddressPropertiesList->discAddrCount; 2033 j++) { 2034 discAddrProps = 2035 discoveryAddressPropertiesList->props[j]; 2036 2037 /* 2038 * Compare the discovery address with the input if 2039 * one was input 2040 */ 2041 if (object && 2042 ipAddressesEqual(discAddrProps.discoveryAddress, 2043 address) && 2044 (discAddrProps.discoveryAddress.portNumber == 2045 address.portNumber)) { 2046 found = B_TRUE; 2047 } 2048 2049 if (!object || found) { 2050 /* Print summary - always */ 2051 if (discAddrProps.discoveryAddress. 2052 hostnameIpAddress.id.ipAddress. 2053 ipv4Address) { 2054 (void) inet_ntop(AF_INET, discAddrProps. 2055 discoveryAddress.hostnameIpAddress. 2056 id.ipAddress.ipAddress, sAddr, 2057 sizeof (sAddr)); 2058 } else { 2059 (void) inet_ntop(AF_INET6, 2060 discAddrProps. 2061 discoveryAddress.hostnameIpAddress. 2062 id.ipAddress.ipAddress, sAddr, 2063 sizeof (sAddr)); 2064 } 2065 (void) fprintf(stdout, 2066 "iSNS Server IP Address: %s:%u\n", 2067 sAddr, 2068 discAddrProps.discoveryAddress.portNumber); 2069 } 2070 2071 if ((!object || found) && showTarget) { 2072 IMA_NODE_PROPERTIES nodeProps; 2073 2074 if (getNodeProps(&nodeProps) != 0) { 2075 break; 2076 } 2077 2078 /* 2079 * Issue sendTargets only when an addr is 2080 * specified. 2081 */ 2082 status = SUN_IMA_RetrieveISNSServerTargets( 2083 discAddrProps.discoveryAddress, 2084 &pList); 2085 if (!IMA_SUCCESS(status)) { 2086 /* 2087 * Check if the discovery mode is 2088 * disabled. 2089 */ 2090 if (status == 2091 IMA_ERROR_OBJECT_NOT_FOUND) { 2092 (void) fprintf(stderr, "%s\n", 2093 gettext("\tiSNS "\ 2094 "discovery "\ 2095 "mode "\ 2096 "disabled. "\ 2097 "No targets "\ 2098 "to report.")); 2099 2100 } else { 2101 (void) fprintf(stderr, "%s\n", 2102 gettext("\tUnable "\ 2103 "to get "\ 2104 "targets.")); 2105 } 2106 continue; 2107 } 2108 printSendTargets(pList); 2109 } 2110 2111 if (found) { 2112 /* we found the discovery address - break */ 2113 break; 2114 } 2115 } 2116 /* 2117 * There was an object entered but we didn't 2118 * find it. 2119 */ 2120 if (object && !found) { 2121 (void) fprintf(stdout, "%s: %s\n", 2122 objects[i], gettext("not found")); 2123 } 2124 } 2125 return (ret); 2126 } 2127 2128 /* 2129 * Print static configuration targets 2130 */ 2131 static int 2132 listStaticConfig(int operandLen, char *operand[], int *funcRet) 2133 { 2134 IMA_STATUS status; 2135 IMA_OID initiatorOid; 2136 IMA_OID_LIST *staticTargetList; 2137 SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps; 2138 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 2139 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2140 wchar_t wcCol; 2141 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2142 int ret; 2143 boolean_t object = B_FALSE; 2144 int outerLoop; 2145 boolean_t found; /* B_TRUE if a target name is found */ 2146 boolean_t matched; /* B_TRUE if a specific target is found */ 2147 boolean_t targetAddressSpecified = B_FALSE; 2148 boolean_t tpgtSpecified = B_FALSE; 2149 boolean_t isIpv6; 2150 int i, j; 2151 IMA_UINT16 port = 0; 2152 IMA_UINT16 tpgt = 0; 2153 char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2154 wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2155 2156 assert(funcRet != NULL); 2157 2158 /* Find Sun initiator */ 2159 ret = sunInitiatorFind(&initiatorOid); 2160 if (ret > 0) { 2161 (void) fprintf(stderr, "%s: %s\n", 2162 cmdName, gettext("no initiator found")); 2163 } 2164 2165 if (ret != 0) { 2166 return (ret); 2167 } 2168 2169 /* 2170 * If there are multiple objects, execute outer 'for' loop that 2171 * many times for each static config detail, otherwise, execute it only 2172 * once with summaries only 2173 */ 2174 if (operandLen > 0) { 2175 object = B_TRUE; 2176 outerLoop = operandLen; 2177 } else { 2178 object = B_FALSE; 2179 outerLoop = 1; 2180 } 2181 2182 /* convert ':' to wide char for wchar string search */ 2183 if (mbtowc(&wcCol, ":", sizeof (wcCol)) == -1) { 2184 (void) fprintf(stderr, "%s: %s\n", 2185 cmdName, gettext("conversion error")); 2186 return (1); 2187 } 2188 2189 status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid, 2190 &staticTargetList); 2191 if (!IMA_SUCCESS(status)) { 2192 printLibError(status); 2193 *funcRet = 1; 2194 return (ret); 2195 } 2196 2197 for (i = 0; i < outerLoop; i++) { 2198 if (object) { 2199 if (parseTarget(operand[i], 2200 &staticTargetName[0], 2201 MAX_ISCSI_NAME_LEN + 1, 2202 &targetAddressSpecified, 2203 &staticTargetAddress[0], 2204 SUN_IMA_IP_ADDRESS_PORT_LEN, 2205 &port, 2206 &tpgtSpecified, 2207 &tpgt, 2208 &isIpv6) != PARSE_TARGET_OK) { 2209 ret = 1; 2210 continue; 2211 } 2212 } 2213 2214 for (found = B_FALSE, j = 0; j < staticTargetList->oidCount; 2215 j++) { 2216 boolean_t isIpv6 = B_FALSE; 2217 IMA_UINT16 stpgt; 2218 IMA_BOOL defaultTpgt; 2219 2220 matched = B_FALSE; 2221 (void) memset(&staticTargetProps, 0, 2222 sizeof (staticTargetProps)); 2223 2224 status = SUN_IMA_GetStaticTargetProperties( 2225 staticTargetList->oids[j], &staticTargetProps); 2226 if (!IMA_SUCCESS(status)) { 2227 printLibError(status); 2228 (void) IMA_FreeMemory(staticTargetList); 2229 *funcRet = 1; 2230 return (ret); 2231 } 2232 2233 stpgt = staticTargetProps.staticTarget.targetAddress. 2234 tpgt; 2235 2236 defaultTpgt = staticTargetProps.staticTarget. 2237 targetAddress.defaultTpgt; 2238 2239 isIpv6 = !staticTargetProps.staticTarget.targetAddress. 2240 imaStruct.hostnameIpAddress.id.ipAddress. 2241 ipv4Address; 2242 2243 /* 2244 * Compare the static target name with the input if 2245 * one was input 2246 */ 2247 2248 if (object && 2249 (targetNamesEqual( 2250 staticTargetProps.staticTarget.targetName, 2251 staticTargetName) == B_TRUE)) { 2252 /* targetName found - found = B_TRUE */ 2253 found = B_TRUE; 2254 if (targetAddressSpecified == B_FALSE) { 2255 matched = B_TRUE; 2256 } else { 2257 2258 if (staticTargetProps.staticTarget. 2259 targetAddress.imaStruct. 2260 hostnameIpAddress.id.ipAddress. 2261 ipv4Address == IMA_TRUE) { 2262 (void) inet_ntop(AF_INET, 2263 staticTargetProps. 2264 staticTarget.targetAddress. 2265 imaStruct.hostnameIpAddress.id. 2266 ipAddress.ipAddress, tmpStr, 2267 sizeof (tmpStr)); 2268 } else { 2269 (void) inet_ntop(AF_INET6, 2270 staticTargetProps. 2271 staticTarget.targetAddress. 2272 imaStruct.hostnameIpAddress.id. 2273 ipAddress.ipAddress, tmpStr, 2274 sizeof (tmpStr)); 2275 } 2276 2277 if (mbstowcs(tmpTargetAddress, tmpStr, 2278 SUN_IMA_IP_ADDRESS_PORT_LEN) == 2279 (size_t)-1) { 2280 (void) fprintf(stderr, "%s: %s\n", 2281 cmdName, 2282 gettext("conversion error")); 2283 ret = 1; 2284 continue; 2285 } 2286 2287 if (wcsncmp(tmpTargetAddress, 2288 staticTargetAddress, 2289 SUN_IMA_IP_ADDRESS_PORT_LEN) 2290 == 0 && 2291 staticTargetProps. 2292 staticTarget.targetAddress. 2293 imaStruct.portNumber == port) { 2294 /* 2295 * Since an object is 2296 * specified, it should also 2297 * have a tpgt specified. If 2298 * not, that means the object 2299 * specified is associated with 2300 * the default tpgt. In 2301 * either case, a tpgt 2302 * comparison should be done 2303 * before claiming that a 2304 * match is found. 2305 */ 2306 if ((tpgt == stpgt && 2307 tpgtSpecified == B_TRUE && 2308 defaultTpgt == IMA_FALSE) || 2309 (tpgt == stpgt && 2310 tpgtSpecified == B_FALSE && 2311 defaultTpgt == IMA_TRUE)) { 2312 matched = B_TRUE; 2313 } 2314 } 2315 2316 } 2317 } 2318 2319 if (!object || matched) { 2320 /* print summary - always */ 2321 (void) fprintf(stdout, gettext("%s: %ws,"), 2322 "Static Configuration Target", 2323 staticTargetProps.staticTarget.targetName); 2324 2325 if (isIpv6 == B_FALSE) { 2326 (void) inet_ntop(AF_INET, 2327 staticTargetProps. 2328 staticTarget.targetAddress. 2329 imaStruct.hostnameIpAddress.id. 2330 ipAddress.ipAddress, sAddr, 2331 sizeof (sAddr)); 2332 (void) fprintf(stdout, "%s:%d", 2333 sAddr, 2334 staticTargetProps.staticTarget. 2335 targetAddress.imaStruct.portNumber); 2336 } else { 2337 (void) inet_ntop(AF_INET6, 2338 staticTargetProps. 2339 staticTarget.targetAddress. 2340 imaStruct.hostnameIpAddress.id. 2341 ipAddress.ipAddress, sAddr, 2342 sizeof (sAddr)); 2343 (void) fprintf(stdout, "[%s]:%d", 2344 sAddr, 2345 staticTargetProps.staticTarget. 2346 targetAddress.imaStruct.portNumber); 2347 } 2348 2349 if (staticTargetProps.staticTarget. 2350 targetAddress. 2351 defaultTpgt == IMA_FALSE) { 2352 (void) fprintf(stdout, ",%d\n", 2353 staticTargetProps. 2354 staticTarget.targetAddress.tpgt); 2355 } else { 2356 (void) fprintf(stdout, "\n"); 2357 } 2358 } 2359 2360 } 2361 /* 2362 * No details to display, but if there were: 2363 * if (object && found)... 2364 * 2365 */ 2366 2367 /* 2368 * There was an object entered but we didn't 2369 * find it. 2370 */ 2371 if (object && !found) { 2372 (void) fprintf(stdout, "%s: %s\n", 2373 operand[i], gettext("not found")); 2374 ret = 1; /* DIY test fix */ 2375 } 2376 } 2377 return (ret); 2378 } 2379 2380 /* 2381 * Print targets 2382 */ 2383 /*ARGSUSED*/ 2384 static int 2385 listTarget(int objectLen, char *objects[], cmdOptions_t *options, int *funcRet) 2386 { 2387 IMA_OID initiatorOid; 2388 IMA_OID_LIST *targetList; 2389 IMA_OID_LIST *lunList; 2390 SUN_IMA_TARGET_PROPERTIES targetProps; 2391 IMA_STATUS status; 2392 IMA_OID_LIST *pConnList; 2393 SUN_IMA_CONN_PROPERTIES *connProps; 2394 2395 int ret; 2396 wchar_t targetName[MAX_ISCSI_NAME_LEN + 1]; 2397 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2398 int outerLoop; 2399 boolean_t found; 2400 boolean_t operandEntered = B_FALSE; 2401 boolean_t verbose = B_FALSE; 2402 boolean_t scsi_target = B_FALSE; 2403 boolean_t targetAddressSpecified = B_FALSE; 2404 boolean_t isIpv6 = B_FALSE; 2405 int i, j; 2406 cmdOptions_t *optionList = options; 2407 boolean_t tpgtSpecified = B_FALSE; 2408 IMA_UINT16 port = 0; 2409 uint16_t tpgt; 2410 2411 assert(funcRet != NULL); 2412 2413 /* Find Sun initiator */ 2414 ret = sunInitiatorFind(&initiatorOid); 2415 if (ret > 0) { 2416 (void) fprintf(stderr, "%s: %s\n", 2417 cmdName, gettext("no initiator found")); 2418 } 2419 2420 if (ret != 0) { 2421 return (ret); 2422 } 2423 2424 for (; optionList->optval; optionList++) { 2425 switch (optionList->optval) { 2426 case 'S': 2427 scsi_target = B_TRUE; 2428 break; 2429 case 'v': 2430 verbose = B_TRUE; 2431 break; 2432 default: 2433 (void) fprintf(stderr, "%s: %c: %s\n", 2434 cmdName, optionList->optval, 2435 gettext("unknown option")); 2436 return (1); 2437 } 2438 } 2439 2440 /* 2441 * If there are multiple objects, execute outer 'for' loop that 2442 * many times for each target detail, otherwise, execute it only 2443 * once with summaries only 2444 */ 2445 if (objectLen > 0) { 2446 operandEntered = B_TRUE; 2447 outerLoop = objectLen; 2448 } else { 2449 operandEntered = B_FALSE; 2450 outerLoop = 1; 2451 } 2452 2453 status = SUN_IMA_GetSessionOidList(initiatorOid, &targetList); 2454 if (!IMA_SUCCESS(status)) { 2455 printLibError(status); 2456 *funcRet = 1; 2457 return (ret); 2458 } 2459 2460 for (i = 0; i < outerLoop; i++) { 2461 2462 tpgtSpecified = B_FALSE; 2463 if (operandEntered) { 2464 if (parseTarget(objects[i], 2465 &targetName[0], 2466 MAX_ISCSI_NAME_LEN + 1, 2467 &targetAddressSpecified, 2468 &targetAddress[0], 2469 SUN_IMA_IP_ADDRESS_PORT_LEN, 2470 &port, 2471 &tpgtSpecified, 2472 &tpgt, 2473 &isIpv6) != PARSE_TARGET_OK) { 2474 ret = 1; 2475 continue; 2476 } 2477 } 2478 for (found = B_FALSE, j = 0; j < targetList->oidCount; j++) { 2479 status = SUN_IMA_GetTargetProperties( 2480 targetList->oids[j], 2481 &targetProps); 2482 if (!IMA_SUCCESS(status)) { 2483 printLibError(status); 2484 (void) IMA_FreeMemory(targetList); 2485 *funcRet = 1; 2486 return (ret); 2487 } 2488 2489 /* 2490 * Compare the target name with the input if 2491 * one was input, if they match, print the target's info 2492 * 2493 * if no target name was input, continue printing this 2494 * target 2495 */ 2496 if (operandEntered) { 2497 if (targetNamesEqual(targetProps.imaProps.name, 2498 targetName) == B_TRUE) { 2499 if (tpgtSpecified == B_TRUE) { 2500 if (targetProps. 2501 defaultTpgtConf == 2502 IMA_FALSE && 2503 targetProps. 2504 tpgtConf == tpgt) { 2505 found = B_TRUE; 2506 } else { 2507 /* 2508 * tpgt does not match, 2509 * move on to next 2510 * target 2511 */ 2512 continue; 2513 } 2514 } else { 2515 found = B_TRUE; 2516 } 2517 } else { 2518 /* 2519 * target name does not match, move on 2520 * to next target 2521 */ 2522 continue; 2523 } 2524 } 2525 2526 /* print summary - always */ 2527 (void) fprintf(stdout, gettext("%s: %ws\n"), 2528 gettext("Target"), targetProps.imaProps.name); 2529 2530 /* Alias */ 2531 (void) fprintf(stdout, "\t%s: ", gettext("Alias")); 2532 if (wslen(targetProps.imaProps.alias) > (size_t)0) { 2533 (void) fprintf(stdout, gettext("%ws\n"), 2534 targetProps.imaProps.alias); 2535 } else { 2536 (void) fprintf(stdout, "%s\n", "-"); 2537 } 2538 2539 if (targetProps.defaultTpgtNego != IMA_TRUE) { 2540 (void) fprintf(stdout, "%s%s: %d\n", 2541 "\t", gettext("TPGT"), 2542 targetProps.tpgtNego); 2543 } else if (targetProps.defaultTpgtConf != IMA_TRUE) { 2544 (void) fprintf(stdout, "%s%s: %d\n", 2545 "\t", gettext("TPGT"), 2546 targetProps.tpgtConf); 2547 } 2548 2549 (void) fprintf(stdout, 2550 "%s%s: %02x%02x%02x%02x%02x%02x\n", 2551 "\t", gettext("ISID"), 2552 targetProps.isid[0], targetProps.isid[1], 2553 targetProps.isid[2], targetProps.isid[3], 2554 targetProps.isid[4], targetProps.isid[5]); 2555 2556 pConnList = NULL; 2557 status = SUN_IMA_GetConnOidList( 2558 &targetList->oids[j], 2559 &pConnList); 2560 2561 if (!IMA_SUCCESS(status)) { 2562 printLibError(status); 2563 (void) IMA_FreeMemory(targetList); 2564 *funcRet = 1; 2565 return (ret); 2566 } 2567 2568 (void) fprintf(stdout, "%s%s: %lu\n", 2569 "\t", 2570 gettext("Connections"), 2571 pConnList->oidCount); 2572 2573 if (verbose) { 2574 SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms; 2575 2576 printConnectionList("\t\t", pConnList); 2577 printDiscoveryMethod( 2578 "\t\t ", 2579 targetProps.imaProps.discoveryMethodFlags); 2580 (void) printLoginParameters( 2581 "\t\t ", 2582 targetList->oids[j], 2583 PRINT_NEGOTIATED_PARAMS); 2584 2585 /* Get Digest configuration */ 2586 status = SUN_IMA_GetConnProperties( 2587 &pConnList->oids[0], &connProps); 2588 2589 (void) getNegotiatedDigest( 2590 ISCSI_LOGIN_PARAM_HEADER_DIGEST, 2591 &digestAlgorithms, connProps); 2592 2593 if (IMA_SUCCESS(status)) { 2594 (void) fprintf(stdout, "\t\t \t%s: ", 2595 gettext("Header Digest")); 2596 printDigestAlgorithm( 2597 &digestAlgorithms, 2598 PRINT_NEGOTIATED_PARAMS); 2599 } else { 2600 (void) IMA_FreeMemory(pConnList); 2601 (void) IMA_FreeMemory(targetList); 2602 printLibError(status); 2603 *funcRet = 1; 2604 return (ret); 2605 } 2606 2607 (void) getNegotiatedDigest( 2608 ISCSI_LOGIN_PARAM_DATA_DIGEST, 2609 &digestAlgorithms, connProps); 2610 2611 if (IMA_SUCCESS(status)) { 2612 (void) fprintf(stdout, "\t\t \t%s: ", 2613 gettext("Data Digest")); 2614 printDigestAlgorithm( 2615 &digestAlgorithms, 2616 PRINT_NEGOTIATED_PARAMS); 2617 } else { 2618 (void) IMA_FreeMemory(pConnList); 2619 (void) IMA_FreeMemory(targetList); 2620 printLibError(status); 2621 *funcRet = 1; 2622 return (ret); 2623 } 2624 2625 (void) fprintf(stdout, "\n"); 2626 } 2627 2628 if (scsi_target) { 2629 status = SUN_IMA_ReEnumeration( 2630 targetList->oids[j]); 2631 if (!IMA_SUCCESS(status)) { 2632 /* 2633 * Proceeds the listing 2634 * but indicates the 2635 * error in return value 2636 */ 2637 ret = 1; 2638 } 2639 2640 status = IMA_GetLuOidList( 2641 targetList->oids[j], 2642 &lunList); 2643 if (!IMA_SUCCESS(status)) { 2644 printLibError(status); 2645 (void) IMA_FreeMemory(targetList); 2646 *funcRet = 1; 2647 return (ret); 2648 } 2649 if (lunList->oidCount != 0) { 2650 printTargetLuns(lunList); 2651 } 2652 (void) fprintf(stdout, "\n"); 2653 (void) IMA_FreeMemory(lunList); 2654 } 2655 } 2656 /* 2657 * did we find the object 2658 */ 2659 2660 if (operandEntered && !found) { 2661 (void) fprintf(stdout, "%s: %s\n", 2662 objects[i], gettext("not found")); 2663 } 2664 } 2665 2666 (void) IMA_FreeMemory(targetList); 2667 return (ret); 2668 } 2669 2670 2671 /* 2672 * Print configured session information 2673 */ 2674 static int 2675 printConfiguredSessions(IMA_OID oid) 2676 { 2677 IMA_STATUS status; 2678 const char *rtn; 2679 SUN_IMA_CONFIG_SESSIONS *pConfigSessions; 2680 char address[MAX_ADDRESS_LEN]; 2681 int out; 2682 2683 /* Get configured session information */ 2684 status = SUN_IMA_GetConfigSessions(oid, &pConfigSessions); 2685 2686 if (IMA_SUCCESS(status)) { 2687 (void) fprintf(stdout, "\t%s: ", 2688 gettext("Configured Sessions")); 2689 if (pConfigSessions->bound == IMA_FALSE) { 2690 /* default binding */ 2691 (void) fprintf(stdout, "%lu\n", pConfigSessions->out); 2692 } else { 2693 /* hardcoded binding */ 2694 for (out = 0; 2695 out < pConfigSessions->out; out++) { 2696 if (pConfigSessions->bindings[out]. 2697 ipAddress.ipv4Address == IMA_TRUE) { 2698 rtn = inet_ntop(AF_INET, 2699 pConfigSessions->bindings[out]. 2700 ipAddress.ipAddress, address, 2701 MAX_ADDRESS_LEN); 2702 } else { 2703 rtn = inet_ntop(AF_INET6, 2704 pConfigSessions->bindings[out]. 2705 ipAddress.ipAddress, address, 2706 MAX_ADDRESS_LEN); 2707 } 2708 if (rtn != NULL) { 2709 (void) printf("%s ", address); 2710 } 2711 } 2712 (void) fprintf(stdout, "\n"); 2713 } 2714 } else { 2715 free(pConfigSessions); 2716 printLibError(status); 2717 return (1); 2718 } 2719 2720 free(pConfigSessions); 2721 return (0); 2722 } 2723 2724 /* 2725 * Print target parameters 2726 */ 2727 static int 2728 listTargetParam(int operandLen, char *operand[], cmdOptions_t *options, 2729 int *funcRet) 2730 { 2731 IMA_STATUS status; 2732 IMA_OID initiatorOid; 2733 IMA_OID_LIST *targetList; 2734 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 2735 SUN_IMA_TARGET_PROPERTIES targetProps; 2736 IMA_UINT maxEntries = MAX_AUTH_METHODS; 2737 IMA_BOOL bidirAuth; 2738 int ret; 2739 wchar_t targetName[MAX_ISCSI_NAME_LEN + 1]; 2740 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 2741 boolean_t operandEntered = B_FALSE; 2742 boolean_t targetAddressSpecified = B_FALSE; 2743 boolean_t printObject = B_FALSE; 2744 boolean_t tpgtSpecified = B_FALSE; 2745 boolean_t isIpv6 = B_FALSE; 2746 int outerLoop; 2747 boolean_t found; 2748 int i, j; 2749 SUN_IMA_DIGEST_ALGORITHM_VALUE digestAlgorithms; 2750 boolean_t verbose = B_FALSE; 2751 cmdOptions_t *optionList = options; 2752 IMA_UINT16 port = 0; 2753 IMA_UINT16 tpgt = 0; 2754 2755 assert(funcRet != NULL); 2756 2757 /* Find Sun initiator */ 2758 ret = sunInitiatorFind(&initiatorOid); 2759 if (ret > 0) { 2760 (void) fprintf(stderr, "%s: %s\n", 2761 cmdName, gettext("no initiator found")); 2762 } 2763 2764 if (ret != 0) { 2765 return (ret); 2766 } 2767 2768 for (; optionList->optval; optionList++) { 2769 switch (optionList->optval) { 2770 case 'v': 2771 verbose = B_TRUE; 2772 break; 2773 default: 2774 (void) fprintf(stderr, "%s: %c: %s\n", 2775 cmdName, optionList->optval, 2776 gettext("unknown option")); 2777 return (1); 2778 } 2779 } 2780 2781 /* 2782 * If there are multiple operands, execute outer 'for' loop that 2783 * many times to find each target parameter operand entered, otherwise, 2784 * execute it only once for all target parameters returned. 2785 */ 2786 if (operandLen > 0) { 2787 operandEntered = B_TRUE; 2788 outerLoop = operandLen; 2789 } else { 2790 operandEntered = B_FALSE; 2791 outerLoop = 1; 2792 } 2793 2794 /* 2795 * Ideally there should be an interface available for obtaining 2796 * the list of target-param objects. Since the driver currently 2797 * creates a target OID and the associated session structure when 2798 * a target-param object is created, we can leverage the target 2799 * OID list and use it to manage the target-param objects. When 2800 * we stop creating a session for target-param object in the 2801 * driver, we will switch to using a different interface to 2802 * obtain target-param objects. 2803 */ 2804 status = IMA_GetTargetOidList(initiatorOid, &targetList); 2805 if (!IMA_SUCCESS(status)) { 2806 printLibError(status); 2807 *funcRet = 1; 2808 return (ret); 2809 } 2810 2811 for (i = 0; i < outerLoop; i++) { 2812 if (operandEntered) { 2813 if (parseTarget(operand[i], 2814 &targetName[0], 2815 MAX_ISCSI_NAME_LEN + 1, 2816 &targetAddressSpecified, 2817 &targetAddress[0], 2818 SUN_IMA_IP_ADDRESS_PORT_LEN, 2819 &port, 2820 &tpgtSpecified, 2821 &tpgt, 2822 &isIpv6) != PARSE_TARGET_OK) { 2823 ret = 1; 2824 continue; 2825 } 2826 } 2827 for (j = 0; j < targetList->oidCount; j++) { 2828 found = B_FALSE; 2829 printObject = B_FALSE; 2830 status = SUN_IMA_GetTargetProperties( 2831 targetList->oids[j], 2832 &targetProps); 2833 if (!IMA_SUCCESS(status)) { 2834 printLibError(status); 2835 (void) IMA_FreeMemory(targetList); 2836 *funcRet = 1; 2837 return (ret); 2838 } 2839 2840 /* 2841 * Compare the target name with the input if 2842 * one was input 2843 */ 2844 if (operandEntered && 2845 (targetNamesEqual(targetProps.imaProps.name, 2846 targetName) == B_TRUE)) { 2847 /* 2848 * For now, regardless of whether a target 2849 * address is specified, we return B_TRUE 2850 * because IMA_TARGET_PROPERTIES does not 2851 * have a field for specifying address. 2852 */ 2853 found = B_TRUE; 2854 } 2855 2856 /* 2857 * if no operand was entered OR 2858 * an operand was entered and it was 2859 * found, we want to print 2860 */ 2861 if (!operandEntered || found) { 2862 printObject = B_TRUE; 2863 } 2864 2865 if (printObject) { 2866 (void) fprintf(stdout, gettext("%s: %ws\n"), 2867 gettext("Target"), 2868 targetProps.imaProps.name); 2869 2870 (void) fprintf(stdout, 2871 "\t%s: ", gettext("Alias")); 2872 if (wslen(targetProps.imaProps.alias) > 2873 (size_t)0) { 2874 (void) fprintf(stdout, 2875 gettext("%ws\n"), 2876 targetProps.imaProps.alias); 2877 } else { 2878 (void) fprintf(stdout, "%s\n", "-"); 2879 } 2880 } 2881 2882 if (printObject && verbose) { 2883 /* Get bidirectional authentication flag */ 2884 (void) fprintf(stdout, "\t%s: ", 2885 gettext("Bi-directional Authentication")); 2886 status = SUN_IMA_GetTargetBidirAuthFlag( 2887 targetList->oids[j], 2888 &bidirAuth); 2889 if (IMA_SUCCESS(status)) { 2890 if (bidirAuth == IMA_TRUE) { 2891 (void) fprintf(stdout, 2892 gettext("enabled")); 2893 } else { 2894 (void) fprintf(stdout, 2895 gettext("disabled")); 2896 } 2897 } else { 2898 (void) fprintf(stdout, 2899 gettext("disabled")); 2900 } 2901 (void) fprintf(stdout, "\n"); 2902 2903 /* Get authentication type for this target */ 2904 status = SUN_IMA_GetTargetAuthMethods( 2905 initiatorOid, 2906 targetList->oids[j], 2907 &maxEntries, 2908 &methodList[0]); 2909 (void) fprintf(stdout, "\t%s: ", 2910 gettext("Authentication Type")); 2911 if (!IMA_SUCCESS(status)) { 2912 /* 2913 * No authentication method define 2914 * NONE by default. 2915 */ 2916 (void) fprintf(stdout, gettext("NONE")); 2917 } else { 2918 for (i = 0; i < maxEntries; i++) { 2919 if (i > 0) { 2920 (void) fprintf(stdout, 2921 "|"); 2922 } 2923 switch (methodList[i]) { 2924 case IMA_AUTHMETHOD_NONE: 2925 (void) fprintf(stdout, 2926 gettext("NONE")); 2927 break; 2928 2929 case IMA_AUTHMETHOD_CHAP: 2930 (void) fprintf(stdout, 2931 gettext("CHAP")); 2932 listCHAPName( 2933 targetList-> 2934 oids[j]); 2935 break; 2936 2937 default: 2938 (void) fprintf(stdout, 2939 gettext( 2940 "unknown " 2941 "type")); 2942 break; 2943 } 2944 } 2945 } 2946 (void) fprintf(stdout, "\n"); 2947 if (printLoginParameters("\t", 2948 targetList->oids[j], 2949 PRINT_CONFIGURED_PARAMS) 2950 != 0) { 2951 (void) IMA_FreeMemory(targetList); 2952 *funcRet = 1; 2953 return (ret); 2954 } 2955 2956 /* Get Digest configuration */ 2957 status = SUN_IMA_GetHeaderDigest( 2958 targetList->oids[j], 2959 &digestAlgorithms); 2960 if (IMA_SUCCESS(status)) { 2961 (void) fprintf(stdout, "\t\t%s: ", 2962 gettext("Header Digest")); 2963 printDigestAlgorithm(&digestAlgorithms, 2964 PRINT_CONFIGURED_PARAMS); 2965 } else { 2966 printLibError(status); 2967 *funcRet = 1; 2968 return (ret); 2969 } 2970 2971 status = SUN_IMA_GetDataDigest( 2972 targetList->oids[j], 2973 &digestAlgorithms); 2974 if (IMA_SUCCESS(status)) { 2975 (void) fprintf(stdout, "\t\t%s: ", 2976 gettext("Data Digest")); 2977 printDigestAlgorithm(&digestAlgorithms, 2978 PRINT_CONFIGURED_PARAMS); 2979 } else { 2980 printLibError(status); 2981 *funcRet = 1; 2982 return (ret); 2983 } 2984 2985 /* print tunable parameters infomation */ 2986 if (printTunableParameters( 2987 targetList->oids[j]) != 0) { 2988 *funcRet = 1; 2989 return (ret); 2990 } 2991 2992 /* print configured session information */ 2993 if (printConfiguredSessions( 2994 targetList->oids[j]) != 0) { 2995 *funcRet = 1; 2996 return (ret); 2997 } 2998 2999 (void) fprintf(stdout, "\n"); 3000 } 3001 3002 if (found) { 3003 break; 3004 } 3005 } 3006 if (operandEntered && !found) { 3007 *funcRet = 1; /* DIY message fix */ 3008 (void) fprintf(stdout, "%s: %s\n", 3009 operand[i], gettext("not found")); 3010 } 3011 } 3012 3013 (void) IMA_FreeMemory(targetList); 3014 return (ret); 3015 } 3016 3017 /* 3018 * Modify discovery attributes 3019 */ 3020 static int 3021 modifyDiscovery(cmdOptions_t *options, int *funcRet) 3022 { 3023 IMA_OID oid; 3024 IMA_STATUS status; 3025 IMA_BOOL setDiscovery; 3026 IMA_HOST_ID hostId; 3027 3028 int ret; 3029 cmdOptions_t *optionList = options; 3030 3031 assert(funcRet != NULL); 3032 3033 /* Find Sun initiator */ 3034 ret = sunInitiatorFind(&oid); 3035 if (ret > 0) { 3036 (void) fprintf(stderr, "%s: %s\n", 3037 cmdName, gettext("no initiator found")); 3038 } 3039 3040 if (ret != 0) { 3041 return (ret); 3042 } 3043 3044 for (; optionList->optval; optionList++) { 3045 /* check optarg and set bool accordingly */ 3046 if (strcasecmp(optionList->optarg, ISCSIADM_ARG_ENABLE) == 0) { 3047 setDiscovery = IMA_TRUE; 3048 } else if (strcasecmp(optionList->optarg, ISCSIADM_ARG_DISABLE) 3049 == 0) { 3050 setDiscovery = IMA_FALSE; 3051 } else { 3052 (void) fprintf(stderr, "%s: %s\n", 3053 cmdName, gettext("invalid option argument")); 3054 return (1); 3055 } 3056 3057 switch (optionList->optval) { 3058 case 's': 3059 /* Set static discovery */ 3060 status = IMA_SetStaticDiscovery(oid, 3061 setDiscovery); 3062 if (!IMA_SUCCESS(status)) { 3063 printLibError(status); 3064 *funcRet = 1; 3065 return (ret); 3066 } 3067 break; 3068 case 't': 3069 /* Set send targets discovery */ 3070 status = IMA_SetSendTargetsDiscovery(oid, 3071 setDiscovery); 3072 if (!IMA_SUCCESS(status)) { 3073 printLibError(status); 3074 *funcRet = 1; 3075 return (ret); 3076 } 3077 break; 3078 case 'i': 3079 /* Set iSNS discovery */ 3080 (void) memset(&hostId, 0, sizeof (hostId)); 3081 status = IMA_SetIsnsDiscovery(oid, setDiscovery, 3082 IMA_ISNS_DISCOVERY_METHOD_STATIC, &hostId); 3083 if (!IMA_SUCCESS(status)) { 3084 printLibError(status); 3085 *funcRet = 1; 3086 return (ret); 3087 } 3088 break; 3089 default: 3090 (void) fprintf(stderr, "%s: %c: %s\n", 3091 cmdName, optionList->optval, 3092 gettext("unknown option")); 3093 return (1); 3094 } 3095 } 3096 3097 return (ret); 3098 } 3099 3100 /* 3101 * Set the initiator node's authentication method 3102 */ 3103 static int 3104 modifyNodeAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet) 3105 { 3106 IMA_INITIATOR_AUTHPARMS authParams; 3107 IMA_STATUS status; 3108 int ret; 3109 int secretLen = MAX_CHAP_SECRET_LEN; 3110 3111 IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1]; 3112 3113 assert(funcRet != NULL); 3114 3115 /* 3116 * Start with existing parameters and modify with the desired change 3117 * before passing along. We ignore any failures as they probably 3118 * are caused by non-existence of auth params for the given node. 3119 */ 3120 status = IMA_GetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3121 &authParams); 3122 3123 switch (param) { 3124 case AUTH_NAME: 3125 if (chapName == NULL) { 3126 (void) fprintf(stderr, "CHAP name cannot be NULL.\n"); 3127 return (1); 3128 } 3129 if (strlen(chapName) == 0) { 3130 (void) fprintf(stderr, "CHAP name cannot be empty.\n"); 3131 return (1); 3132 } 3133 (void) memset(&authParams.chapParms.name, 0, 3134 sizeof (authParams.chapParms.name)); 3135 (void) memcpy(&authParams.chapParms.name, 3136 &chapName[0], strlen(chapName)); 3137 authParams.chapParms.nameLength = strlen(chapName); 3138 break; 3139 3140 case AUTH_PASSWORD : 3141 ret = getSecret((char *)&chapSecret[0], &secretLen, 3142 MIN_CHAP_SECRET_LEN, MAX_CHAP_SECRET_LEN); 3143 3144 if (ret != 0) { 3145 return (ret); 3146 } 3147 3148 (void) memset(&authParams.chapParms.challengeSecret, 0, 3149 sizeof (authParams.chapParms.challengeSecret)); 3150 (void) memcpy(&authParams.chapParms.challengeSecret, 3151 &chapSecret[0], secretLen); 3152 authParams.chapParms.challengeSecretLength = secretLen; 3153 break; 3154 3155 default: 3156 (void) fprintf(stderr, "Invalid auth parameter %d\n", param); 3157 return (1); 3158 } 3159 3160 status = IMA_SetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3161 &authParams); 3162 if (!IMA_SUCCESS(status)) { 3163 printLibError(status); 3164 *funcRet = 1; 3165 } 3166 return (ret); 3167 } 3168 3169 /* 3170 * Set the target's authentication method 3171 */ 3172 static int 3173 modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet) 3174 { 3175 IMA_INITIATOR_AUTHPARMS authParams; 3176 IMA_STATUS status; 3177 int ret; 3178 int secretLen = MAX_CHAP_SECRET_LEN; 3179 3180 IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1]; 3181 3182 assert(funcRet != NULL); 3183 3184 /* 3185 * Start with existing parameters and modify with the desired change 3186 * before passing along. We ignore any get failures as they probably 3187 * are caused by non-existence of auth params for the given target. 3188 */ 3189 status = SUN_IMA_GetTargetAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3190 &authParams); 3191 3192 switch (param) { 3193 case AUTH_NAME: 3194 if (chapName == NULL) { 3195 (void) fprintf(stderr, "CHAP name cannot be NULL.\n"); 3196 return (1); 3197 } 3198 if (strlen(chapName) == 0) { 3199 (void) fprintf(stderr, "CHAP name cannot be empty.\n"); 3200 return (1); 3201 } 3202 (void) memset(&authParams.chapParms.name, 0, 3203 sizeof (authParams.chapParms.name)); 3204 (void) memcpy(&authParams.chapParms.name, 3205 &chapName[0], strlen(chapName)); 3206 authParams.chapParms.nameLength = strlen(chapName); 3207 break; 3208 3209 case AUTH_PASSWORD : 3210 ret = getSecret((char *)&chapSecret[0], &secretLen, 3211 1, MAX_CHAP_SECRET_LEN); 3212 3213 if (ret != 0) { 3214 return (ret); 3215 } 3216 3217 (void) memset(&authParams.chapParms.challengeSecret, 0, 3218 sizeof (authParams.chapParms.challengeSecret)); 3219 (void) memcpy(&authParams.chapParms.challengeSecret, 3220 &chapSecret[0], secretLen); 3221 authParams.chapParms.challengeSecretLength = secretLen; 3222 break; 3223 3224 default: 3225 (void) fprintf(stderr, "Invalid auth parameter %d\n", param); 3226 return (1); 3227 } 3228 3229 status = SUN_IMA_SetTargetAuthParams(oid, IMA_AUTHMETHOD_CHAP, 3230 &authParams); 3231 if (!IMA_SUCCESS(status)) { 3232 printLibError(status); 3233 *funcRet = 1; 3234 } 3235 return (0); 3236 } 3237 3238 static int 3239 modifyTargetBidirAuthFlag(IMA_OID targetOid, char *optarg, int *funcRet) 3240 { 3241 IMA_BOOL boolValue; 3242 IMA_STATUS status; 3243 3244 assert(funcRet != NULL); 3245 3246 if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) { 3247 boolValue = IMA_TRUE; 3248 } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) { 3249 boolValue = IMA_FALSE; 3250 } else { 3251 (void) fprintf(stderr, "%s: %s %s\n", 3252 cmdName, gettext("invalid option argument"), optarg); 3253 return (1); 3254 } 3255 3256 status = SUN_IMA_SetTargetBidirAuthFlag(targetOid, &boolValue); 3257 if (!IMA_SUCCESS(status)) { 3258 printLibError(status); 3259 *funcRet = 1; 3260 } 3261 return (0); 3262 } 3263 3264 static int 3265 modifyConfiguredSessions(IMA_OID targetOid, char *optarg) 3266 { 3267 SUN_IMA_CONFIG_SESSIONS *pConfigSessions; 3268 IMA_STATUS status; 3269 int sessions; 3270 int size; 3271 char tmp[1024]; 3272 boolean_t isIpv6 = B_FALSE; 3273 uint16_t port; 3274 char address[MAX_ADDRESS_LEN]; 3275 char *commaPos; 3276 char *addressPos; 3277 int rtn; 3278 3279 /* 3280 * Strip the first int value from the string. If we sprintf 3281 * this back to a string and it matches the original string 3282 * then this command is using default binding. If not a 3283 * match we have hard coded binding or a usage error. 3284 */ 3285 sessions = atoi(optarg); 3286 (void) sprintf(tmp, "%d", sessions); 3287 if (strcmp(optarg, tmp) == 0) { 3288 /* default binding */ 3289 3290 /* allocate the required pConfigSessions */ 3291 size = sizeof (SUN_IMA_CONFIG_SESSIONS); 3292 pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 3293 if (pConfigSessions == NULL) { 3294 return (1); 3295 } 3296 3297 /* setup pConfigSessions */ 3298 pConfigSessions->bound = IMA_FALSE; 3299 pConfigSessions->in = sessions; 3300 pConfigSessions->out = 0; 3301 } else { 3302 /* hardcoded binding */ 3303 3304 /* 3305 * First we need to determine how many bindings 3306 * are available. This can be done by scanning 3307 * for the number of ',' + 1. 3308 */ 3309 sessions = 1; 3310 commaPos = strchr(optarg, ','); 3311 while (commaPos != NULL) { 3312 sessions++; 3313 commaPos = strchr(++commaPos, ','); 3314 } 3315 3316 /* allocate the required pConfigSessions */ 3317 size = sizeof (SUN_IMA_CONFIG_SESSIONS) + ((sessions - 1) * 3318 sizeof (IMA_ADDRESS_KEY)); 3319 pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 3320 if (pConfigSessions == NULL) { 3321 return (1); 3322 } 3323 3324 /* setup pConfigSessions */ 3325 pConfigSessions->bound = IMA_TRUE; 3326 pConfigSessions->in = sessions; 3327 pConfigSessions->out = 0; 3328 3329 /* Now fill in the binding information. */ 3330 sessions = 0; 3331 addressPos = optarg; 3332 /* 3333 * Walk thru possible address strings 3334 * stop once all strings are processed. 3335 */ 3336 while (addressPos != NULL) { 3337 /* 3338 * Check if there is another address after this 3339 * one. If so terminate the current address and 3340 * keep a pointer to the next one. 3341 */ 3342 commaPos = strchr(addressPos, ','); 3343 if (commaPos != NULL) { 3344 *commaPos++ = 0x00; 3345 } 3346 3347 /* 3348 * Parse current address. If invalid abort 3349 * processing of addresses and free memory. 3350 */ 3351 if (parseAddress(addressPos, 0, address, 3352 MAX_ADDRESS_LEN, &port, &isIpv6) != PARSE_ADDR_OK) { 3353 free(pConfigSessions); 3354 printLibError(IMA_ERROR_INVALID_PARAMETER); 3355 return (1); 3356 } 3357 3358 /* Convert address into binary form */ 3359 if (isIpv6 == B_FALSE) { 3360 pConfigSessions->bindings[sessions]. 3361 ipAddress.ipv4Address = IMA_TRUE; 3362 rtn = inet_pton(AF_INET, address, 3363 pConfigSessions->bindings[sessions]. 3364 ipAddress.ipAddress); 3365 } else { 3366 pConfigSessions->bindings[sessions].ipAddress. 3367 ipv4Address = 3368 IMA_FALSE; 3369 rtn = inet_pton(AF_INET6, address, 3370 pConfigSessions->bindings[sessions]. 3371 ipAddress.ipAddress); 3372 } 3373 if (rtn == 0) { 3374 /* inet_pton found address invalid */ 3375 free(pConfigSessions); 3376 printLibError(IMA_ERROR_INVALID_PARAMETER); 3377 return (1); 3378 } 3379 3380 /* update addressPos to next address */ 3381 sessions++; 3382 addressPos = commaPos; 3383 } 3384 } 3385 3386 /* issue SUN_IMA request */ 3387 status = SUN_IMA_SetConfigSessions(targetOid, 3388 pConfigSessions); 3389 if (!IMA_SUCCESS(status)) { 3390 printLibError(status); 3391 free(pConfigSessions); 3392 return (1); 3393 } 3394 3395 free(pConfigSessions); 3396 return (0); 3397 } 3398 3399 static int 3400 getAuthMethodValue(char *method, IMA_AUTHMETHOD *value) 3401 { 3402 if (strcasecmp(method, "chap") == 0) { 3403 *value = IMA_AUTHMETHOD_CHAP; 3404 return (0); 3405 } 3406 3407 if (strcasecmp(method, "none") == 0) { 3408 *value = IMA_AUTHMETHOD_NONE; 3409 return (0); 3410 } 3411 3412 return (1); 3413 } 3414 3415 3416 /* 3417 * Set the authentication method 3418 * Currently only supports CHAP and NONE 3419 */ 3420 static int 3421 modifyNodeAuthMethod(IMA_OID oid, char *optarg, int *funcRet) 3422 { 3423 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 3424 IMA_UINT methodCount = 0; 3425 IMA_STATUS status; 3426 IMA_AUTHMETHOD value; 3427 char *method; 3428 char *commaPos; 3429 3430 assert(funcRet != NULL); 3431 3432 /* 3433 * optarg will be a , delimited set of auth methods, in order 3434 * of preference 3435 * if any values here are incorrect, return without setting 3436 * anything. 3437 */ 3438 method = optarg; 3439 3440 commaPos = strchr(optarg, ','); 3441 3442 while (commaPos && methodCount < MAX_AUTH_METHODS) { 3443 *commaPos = NULL; 3444 if (getAuthMethodValue(method, &value) != 0) { 3445 (void) fprintf(stderr, "%s: a: %s\n", 3446 cmdName, gettext("invalid option argument")); 3447 return (1); 3448 } 3449 methodList[methodCount++] = value; 3450 commaPos++; 3451 method = commaPos; 3452 commaPos = strchr(method, ','); 3453 } 3454 /* Should not find more method specified - if found, error */ 3455 if (commaPos) { 3456 (void) fprintf(stderr, "%s: -a: %s\n", 3457 cmdName, gettext("invalid option argument")); 3458 return (1); 3459 } 3460 if (getAuthMethodValue(method, &value) != 0) { 3461 (void) fprintf(stderr, "%s: -a: %s\n", 3462 cmdName, gettext("invalid option argument")); 3463 return (1); 3464 } 3465 methodList[methodCount++] = value; 3466 3467 status = IMA_SetInitiatorAuthMethods(oid, methodCount, &methodList[0]); 3468 if (!IMA_SUCCESS(status)) { 3469 printLibError(status); 3470 *funcRet = 1; 3471 } 3472 return (0); 3473 } 3474 3475 static int 3476 modifyTargetAuthMethod(IMA_OID oid, char *optarg, int *funcRet) 3477 { 3478 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 3479 IMA_UINT methodCount = 0; 3480 IMA_STATUS status; 3481 IMA_AUTHMETHOD value; 3482 char *method; 3483 char *commaPos; 3484 3485 assert(funcRet != NULL); 3486 3487 /* 3488 * optarg will be a , delimited set of auth methods, in order 3489 * of preference 3490 * if any values here are incorrect, return without setting 3491 * anything. 3492 */ 3493 method = optarg; 3494 3495 commaPos = strchr(optarg, ','); 3496 3497 while (commaPos && methodCount < MAX_AUTH_METHODS) { 3498 *commaPos = NULL; 3499 if (getAuthMethodValue(method, &value) != 0) { 3500 (void) fprintf(stderr, "%s: a: %s\n", 3501 cmdName, gettext("invalid option argument")); 3502 return (1); 3503 } 3504 methodList[methodCount++] = value; 3505 commaPos++; 3506 method = commaPos; 3507 commaPos = strchr(method, ','); 3508 } 3509 /* Should not find more method specified - if found, error */ 3510 if (commaPos) { 3511 (void) fprintf(stderr, "%s: -a: %s\n", 3512 cmdName, gettext("invalid option argument")); 3513 return (1); 3514 } 3515 if (getAuthMethodValue(method, &value) != 0) { 3516 (void) fprintf(stderr, "%s: -a: %s\n", 3517 cmdName, gettext("invalid option argument")); 3518 return (1); 3519 } 3520 methodList[methodCount++] = value; 3521 3522 status = SUN_IMA_SetTargetAuthMethods(oid, &methodCount, 3523 &methodList[0]); 3524 if (!IMA_SUCCESS(status)) { 3525 printLibError(status); 3526 *funcRet = 1; 3527 } 3528 return (0); 3529 } 3530 3531 /* 3532 * Modify the RADIUS configuration of the initiator node. 3533 * 3534 * Return 0 on success. 3535 */ 3536 static int 3537 modifyNodeRadiusConfig(IMA_OID oid, char *optarg, int *funcRet) 3538 { 3539 SUN_IMA_RADIUS_CONFIG config; 3540 IMA_STATUS status; 3541 boolean_t isIpv6 = B_FALSE; 3542 uint16_t port; 3543 3544 assert(funcRet != NULL); 3545 3546 (void) memset(&config, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3547 if (parseAddress(optarg, DEFAULT_RADIUS_PORT, 3548 &config.hostnameIpAddress[0], SUN_IMA_IP_ADDRESS_PORT_LEN, 3549 &port, &isIpv6) != 3550 PARSE_ADDR_OK) { 3551 return (1); 3552 } 3553 config.port = (IMA_UINT16)port; 3554 config.isIpv6 = (isIpv6 == B_TRUE) ? IMA_TRUE : IMA_FALSE; 3555 /* Not setting shared secret here. */ 3556 config.sharedSecretValid = IMA_FALSE; 3557 3558 status = SUN_IMA_SetInitiatorRadiusConfig(oid, &config); 3559 if (!IMA_SUCCESS(status)) { 3560 printLibError(status); 3561 *funcRet = 1; 3562 } 3563 3564 return (0); 3565 } 3566 3567 /* 3568 * Modify the RADIUS access flag of the initiator node. 3569 * 3570 * Return 0 on success. 3571 */ 3572 static int 3573 modifyNodeRadiusAccess(IMA_OID oid, char *optarg, int *funcRet) 3574 { 3575 IMA_BOOL radiusAccess; 3576 IMA_OID initiatorOid; 3577 IMA_STATUS status; 3578 SUN_IMA_RADIUS_CONFIG radiusConfig; 3579 int ret; 3580 3581 assert(funcRet != NULL); 3582 3583 /* Check if Radius Config is there */ 3584 ret = sunInitiatorFind(&initiatorOid); 3585 if (ret != 0) { 3586 (void) fprintf(stderr, "%s: %s\n", 3587 cmdName, gettext("no initiator found")); 3588 return (1); 3589 } 3590 (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3591 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 3592 if (!IMA_SUCCESS(status)) { 3593 (void) fprintf(stderr, "%s: %s\n", 3594 cmdName, gettext("RADIUS server not configured yet")); 3595 *funcRet = 1; 3596 return (ret); 3597 } 3598 3599 /* Check if Radius Shared is set */ 3600 if (radiusConfig.sharedSecretValid == IMA_FALSE) { 3601 (void) fprintf(stderr, "%s: %s\n", cmdName, 3602 gettext("RADIUS server secret not configured yet")); 3603 return (1); 3604 } 3605 3606 if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) { 3607 radiusAccess = IMA_TRUE; 3608 } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) { 3609 radiusAccess = IMA_FALSE; 3610 } else { 3611 (void) fprintf(stderr, "%s: %s %s\n", 3612 cmdName, 3613 gettext("invalid option argument"), 3614 optarg); 3615 return (1); 3616 } 3617 status = SUN_IMA_SetInitiatorRadiusAccess(oid, radiusAccess); 3618 if (!IMA_SUCCESS(status)) { 3619 printLibError(status); 3620 *funcRet = 1; 3621 } 3622 3623 return (ret); 3624 } 3625 3626 /* 3627 * Modify the RADIUS shared secret. 3628 * 3629 * Returns: 3630 * zero on success. 3631 * > 0 on failure. 3632 */ 3633 static int 3634 modifyNodeRadiusSharedSecret(IMA_OID oid, int *funcRet) 3635 { 3636 IMA_BYTE radiusSharedSecret[SUN_IMA_MAX_RADIUS_SECRET_LEN + 1]; 3637 IMA_OID initiatorOid; 3638 IMA_STATUS status; 3639 SUN_IMA_RADIUS_CONFIG radiusConfig; 3640 int ret; 3641 int secretLen = SUN_IMA_MAX_RADIUS_SECRET_LEN; 3642 3643 assert(funcRet != NULL); 3644 3645 ret = getSecret((char *)&radiusSharedSecret[0], &secretLen, 3646 0, SUN_IMA_MAX_RADIUS_SECRET_LEN); 3647 if (ret != 0) { 3648 return (1); 3649 } 3650 3651 ret = sunInitiatorFind(&initiatorOid); 3652 if (ret > 0) { 3653 (void) fprintf(stderr, "%s: %s\n", 3654 cmdName, gettext("no initiator found")); 3655 } 3656 if (ret != 0) { 3657 return (1); 3658 } 3659 /* First obtain existing RADIUS configuration (if any) */ 3660 (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3661 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 3662 if (!IMA_SUCCESS(status)) { 3663 (void) fprintf(stderr, "%s: %s\n", 3664 cmdName, gettext("RADIUS server not configured yet")); 3665 return (1); 3666 } 3667 3668 /* Modify the shared secret only */ 3669 radiusConfig.sharedSecretLength = secretLen; 3670 (void) memcpy(&radiusConfig.sharedSecret, 3671 &radiusSharedSecret[0], secretLen); 3672 radiusConfig.sharedSecretValid = IMA_TRUE; 3673 status = SUN_IMA_SetInitiatorRadiusConfig(oid, &radiusConfig); 3674 if (!IMA_SUCCESS(status)) { 3675 printLibError(status); 3676 *funcRet = 1; 3677 } 3678 3679 return (0); 3680 } 3681 3682 /* 3683 * Set initiator node attributes. 3684 */ 3685 static int 3686 modifyNode(cmdOptions_t *options, int *funcRet) 3687 { 3688 IMA_NODE_NAME nodeName; 3689 IMA_NODE_ALIAS nodeAlias; 3690 IMA_OID oid; 3691 IMA_STATUS status; 3692 cmdOptions_t *optionList = options; 3693 int ret; 3694 iSCSINameCheckStatusType nameCheckStatus; 3695 IMA_OID sharedNodeOid; 3696 int i; 3697 int lowerCase; 3698 IMA_BOOL iscsiBoot = IMA_FALSE; 3699 IMA_BOOL mpxioEnabled = IMA_FALSE; 3700 char *mb_name = NULL; 3701 int prefixlen = 0; 3702 3703 assert(funcRet != NULL); 3704 3705 /* Get boot session's info */ 3706 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 3707 if (iscsiBoot == IMA_TRUE) { 3708 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 3709 if (!IMA_SUCCESS(status)) { 3710 (void) fprintf(stderr, "%s: %s\n", 3711 cmdName, gettext("unable to get MPxIO info" 3712 " of root disk")); 3713 *funcRet = 1; 3714 return (1); 3715 } 3716 } 3717 3718 /* Find Sun initiator */ 3719 ret = sunInitiatorFind(&oid); 3720 if (ret != 0) { 3721 (void) fprintf(stderr, "%s: %s\n", 3722 cmdName, gettext("no initiator found")); 3723 return (ret); 3724 } 3725 3726 for (; optionList->optval; optionList++) { 3727 switch (optionList->optval) { 3728 case 'N': 3729 if (strlen(optionList->optarg) >= 3730 MAX_ISCSI_NAME_LEN) { 3731 (void) fprintf(stderr, "%s: %s %d\n", 3732 cmdName, 3733 gettext("name too long, \ 3734 maximum length is:"), 3735 MAX_ISCSI_NAME_LEN); 3736 } 3737 3738 /* Take the first operand as node name. */ 3739 (void) memset(&nodeName, 0, 3740 sizeof (IMA_NODE_NAME)); 3741 if (mbstowcs(nodeName, optionList->optarg, 3742 IMA_NODE_NAME_LEN) == (size_t)-1) { 3743 (void) fprintf(stderr, "%s: %s\n", 3744 cmdName, 3745 gettext("conversion error")); 3746 return (1); 3747 } 3748 3749 prefixlen = strlen(ISCSI_IQN_NAME_PREFIX); 3750 mb_name = (char *)calloc(1, prefixlen + 1); 3751 if (mb_name == NULL) { 3752 return (1); 3753 } 3754 3755 if (wcstombs(mb_name, nodeName, 3756 prefixlen) == (size_t)-1) { 3757 (void) fprintf(stderr, "%s: %s\n", 3758 cmdName, 3759 gettext("conversion error")); 3760 (void) IMA_FreeMemory(mb_name); 3761 return (1); 3762 } 3763 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 3764 prefixlen) == 0) { 3765 /* 3766 * For iqn format, we should map 3767 * the upper-case characters to 3768 * their lower-case equivalents. 3769 */ 3770 for (i = 0; nodeName[i] != 0; i++) { 3771 lowerCase = 3772 tolower(nodeName[i]); 3773 nodeName[i] = lowerCase; 3774 } 3775 } 3776 (void) IMA_FreeMemory(mb_name); 3777 3778 /* Perform string profile checks */ 3779 nameCheckStatus = 3780 iSCSINameStringProfileCheck(nodeName); 3781 iSCSINameCheckStatusDisplay(nameCheckStatus); 3782 if (nameCheckStatus != iSCSINameCheckOK) { 3783 *funcRet = 1; /* DIY message fix */ 3784 return (1); 3785 } 3786 3787 /* 3788 * IMA_GetSharedNodeOid(&sharedNodeOid); 3789 * if (!IMA_SUCCESS(status)) { 3790 * printLibError(status); 3791 * return (INF_ERROR); 3792 * } 3793 */ 3794 if (iscsiBoot == IMA_TRUE) { 3795 (void) fprintf(stderr, "%s: %s\n", 3796 cmdName, gettext("iscsi boot, not" 3797 " allowed to change" 3798 " initiator's name")); 3799 return (1); 3800 } 3801 oid.objectType = IMA_OBJECT_TYPE_NODE; 3802 status = IMA_SetNodeName(oid, nodeName); 3803 if (!IMA_SUCCESS(status)) { 3804 printLibError(status); 3805 *funcRet = 1; 3806 return (ret); 3807 } 3808 break; 3809 3810 case 'A': 3811 if (iscsiBoot == IMA_TRUE) { 3812 (void) fprintf(stderr, "%s: %s\n", 3813 cmdName, gettext("iscsi boot, not" 3814 " allowed to change" 3815 " initiator's alias")); 3816 return (1); 3817 } 3818 /* Take the first operand as node alias. */ 3819 if (strlen(optionList->optarg) >= 3820 MAX_ISCSI_NAME_LEN) { 3821 (void) fprintf(stderr, "%s: %s %d\n", 3822 cmdName, 3823 gettext("alias too long, maximum \ 3824 length is:"), 3825 MAX_ISCSI_NAME_LEN); 3826 } 3827 3828 (void) memset(&nodeAlias, 0, 3829 sizeof (IMA_NODE_ALIAS)); 3830 if (mbstowcs(nodeAlias, optionList->optarg, 3831 IMA_NODE_ALIAS_LEN) == (size_t)-1) { 3832 (void) fprintf(stderr, "%s: %s\n", 3833 cmdName, 3834 gettext("conversion error")); 3835 return (1); 3836 } 3837 3838 status = IMA_GetSharedNodeOid(&sharedNodeOid); 3839 if (!IMA_SUCCESS(status)) { 3840 printLibError(status); 3841 *funcRet = 1; 3842 return (ret); 3843 } 3844 3845 status = IMA_SetNodeAlias(sharedNodeOid, 3846 nodeAlias); 3847 if (!IMA_SUCCESS(status)) { 3848 printLibError(status); 3849 *funcRet = 1; 3850 return (ret); 3851 } 3852 break; 3853 3854 case 'a': 3855 if (iscsiBoot == IMA_TRUE) { 3856 (void) fprintf(stderr, "%s: %s\n", 3857 cmdName, gettext("iscsi boot, not" 3858 " allowed to change authentication" 3859 " method")); 3860 return (1); 3861 } 3862 if (modifyNodeAuthMethod(oid, options->optarg, 3863 funcRet) != 0) { 3864 return (1); 3865 } 3866 break; 3867 3868 case 'R': 3869 if (modifyNodeRadiusAccess(oid, options->optarg, 3870 funcRet) != 0) { 3871 return (1); 3872 } 3873 break; 3874 3875 case 'r': 3876 if (modifyNodeRadiusConfig(oid, options->optarg, 3877 funcRet) != 0) { 3878 return (1); 3879 } 3880 break; 3881 3882 case 'P': 3883 if (modifyNodeRadiusSharedSecret(oid, funcRet) 3884 != 0) { 3885 return (1); 3886 } 3887 break; 3888 3889 case 'C': 3890 if (iscsiBoot == IMA_TRUE) { 3891 (void) fprintf(stderr, "%s: %s\n", 3892 cmdName, gettext("iscsi boot, not" 3893 " allowed to change CHAP secret")); 3894 return (1); 3895 } 3896 if (modifyNodeAuthParam(oid, AUTH_PASSWORD, 3897 NULL, funcRet) != 0) { 3898 return (1); 3899 } 3900 break; 3901 3902 case 'c': 3903 if (iscsiBoot == IMA_TRUE) { 3904 if (mpxioEnabled == IMA_FALSE) { 3905 (void) fprintf(stderr, 3906 "%s: %s\n", cmdName, 3907 gettext("iscsi" 3908 " boot and MPxIO" 3909 " is disabled, not allowed" 3910 " to change number of" 3911 " sessions to be" 3912 " configured")); 3913 return (1); 3914 } 3915 } 3916 if (modifyConfiguredSessions(oid, 3917 optionList->optarg) != 0) { 3918 if (iscsiBoot == IMA_TRUE) { 3919 (void) fprintf(stderr, 3920 "%s: %s\n", cmdName, 3921 gettext("iscsi boot," 3922 " fail to set configured" 3923 " session")); 3924 } 3925 return (1); 3926 } 3927 break; 3928 3929 3930 case 'H': 3931 if (iscsiBoot == IMA_TRUE) { 3932 (void) fprintf(stderr, "%s: %s\n", 3933 cmdName, gettext("iscsi boot, not" 3934 " allowed to change CHAP name")); 3935 return (1); 3936 } 3937 if (modifyNodeAuthParam(oid, AUTH_NAME, 3938 optionList->optarg, funcRet) != 0) { 3939 return (1); 3940 } 3941 break; 3942 3943 3944 case 'd': 3945 if (iscsiBoot == IMA_TRUE) { 3946 if (mpxioEnabled == IMA_FALSE) { 3947 (void) fprintf(stderr, 3948 "%s: %s\n", cmdName, 3949 gettext("iscsi" 3950 " boot and MPxIO" 3951 " is disabled, not" 3952 " allowed to" 3953 " change initiator's" 3954 " login params")); 3955 return (1); 3956 } 3957 } 3958 if (setLoginParameter(oid, DATA_DIGEST, 3959 optionList->optarg) != 0) { 3960 return (1); 3961 } 3962 break; 3963 3964 case 'h': 3965 if (iscsiBoot == IMA_TRUE) { 3966 if (mpxioEnabled == IMA_FALSE) { 3967 (void) fprintf(stderr, 3968 "%s: %s\n", cmdName, 3969 gettext("iscsi" 3970 " boot and MPxIO" 3971 " is disabled, not" 3972 " allowed to" 3973 " change initiator's" 3974 " login params")); 3975 return (1); 3976 } 3977 } 3978 if (setLoginParameter(oid, HEADER_DIGEST, 3979 optionList->optarg) != 0) { 3980 return (1); 3981 } 3982 break; 3983 3984 case 'T': 3985 if (setTunableParameters(oid, 3986 optionList->optarg) != 0) { 3987 return (1); 3988 } 3989 break; 3990 default: 3991 (void) fprintf(stderr, "%s: %c: %s\n", 3992 cmdName, optionList->optval, 3993 gettext("unknown option")); 3994 break; 3995 } 3996 } 3997 3998 return (ret); 3999 } 4000 4001 /* 4002 * Modify target parameters 4003 */ 4004 static int 4005 modifyTargetParam(cmdOptions_t *options, char *targetName, int *funcRet) 4006 { 4007 IMA_OID oid; 4008 IMA_OID targetOid; 4009 IMA_STATUS status; 4010 IMA_OID_LIST *targetList; 4011 SUN_IMA_TARGET_PROPERTIES targetProps; 4012 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 4013 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4014 int ret; 4015 boolean_t found; 4016 boolean_t targetAddressSpecified = B_TRUE; 4017 boolean_t tpgtSpecified = B_FALSE; 4018 boolean_t isIpv6 = B_FALSE; 4019 int i; 4020 iSCSINameCheckStatusType nameCheckStatus; 4021 IMA_UINT16 port = 0; 4022 IMA_UINT16 tpgt = 0; 4023 4024 IMA_NODE_NAME bootTargetName; 4025 IMA_INITIATOR_AUTHPARMS bootTargetCHAP; 4026 IMA_BOOL iscsiBoot; 4027 IMA_BOOL mpxioEnabled; 4028 4029 cmdOptions_t *optionList = options; 4030 4031 assert(funcRet != NULL); 4032 4033 /* Find Sun initiator */ 4034 ret = sunInitiatorFind(&oid); 4035 if (ret > 0) { 4036 (void) fprintf(stderr, "%s: %s\n", 4037 cmdName, gettext("no initiator found")); 4038 } 4039 4040 if (ret != 0) { 4041 return (ret); 4042 } 4043 4044 if (parseTarget(targetName, 4045 &wcInputObject[0], 4046 MAX_ISCSI_NAME_LEN + 1, 4047 &targetAddressSpecified, 4048 &targetAddress[0], 4049 SUN_IMA_IP_ADDRESS_PORT_LEN, 4050 &port, 4051 &tpgtSpecified, 4052 &tpgt, 4053 &isIpv6) != PARSE_TARGET_OK) { 4054 return (1); 4055 } 4056 4057 /* Perform string profile checks */ 4058 nameCheckStatus = iSCSINameStringProfileCheck(wcInputObject); 4059 iSCSINameCheckStatusDisplay(nameCheckStatus); 4060 if (nameCheckStatus != iSCSINameCheckOK) { 4061 return (1); 4062 } 4063 4064 status = IMA_GetTargetOidList(oid, &targetList); 4065 if (!IMA_SUCCESS(status)) { 4066 printLibError(status); 4067 *funcRet = 1; 4068 return (0); 4069 } 4070 4071 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 4072 if (iscsiBoot == IMA_TRUE) { 4073 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 4074 if (!IMA_SUCCESS(status)) { 4075 (void) fprintf(stderr, "%s: %s\n", 4076 cmdName, gettext("unable to get MPxIO info" 4077 " of root disk")); 4078 *funcRet = 1; 4079 return (ret); 4080 } 4081 status = SUN_IMA_GetBootTargetName(bootTargetName); 4082 if (!IMA_SUCCESS(status)) { 4083 (void) fprintf(stderr, "%s: %s\n", 4084 cmdName, gettext("unable to get boot target's" 4085 " name")); 4086 *funcRet = 1; 4087 return (ret); 4088 } 4089 status = SUN_IMA_GetBootTargetAuthParams(&bootTargetCHAP); 4090 if (!IMA_SUCCESS(status)) { 4091 (void) fprintf(stderr, "%s: %s\n", 4092 cmdName, gettext("unable to get boot target's" 4093 " auth param")); 4094 *funcRet = 1; 4095 return (ret); 4096 } 4097 } 4098 4099 /* find target oid */ 4100 for (found = B_FALSE, i = 0; i < targetList->oidCount; i++) { 4101 status = SUN_IMA_GetTargetProperties(targetList->oids[i], 4102 &targetProps); 4103 if (!IMA_SUCCESS(status)) { 4104 printLibError(status); 4105 (void) IMA_FreeMemory(targetList); 4106 *funcRet = 1; 4107 return (ret); 4108 } 4109 4110 /* 4111 * Compare the target name with the input name 4112 */ 4113 if ((targetNamesEqual(wcInputObject, targetProps.imaProps.name) 4114 == B_TRUE)) { 4115 /* 4116 * For now, regardless of whether a target address 4117 * is specified, we return B_TRUE because 4118 * IMA_TARGET_PROPERTIES does not have a field for 4119 * specifying address. 4120 */ 4121 found = B_TRUE; 4122 targetOid = targetList->oids[i]; 4123 4124 if ((targetNamesEqual(bootTargetName, wcInputObject) 4125 == B_TRUE) && (iscsiBoot == IMA_TRUE)) { 4126 /* 4127 * iscsi booting, need changed target param is 4128 * booting target, for auth param, not allow 4129 * to change, for others dependent on mpxio 4130 */ 4131 4132 if ((optionList->optval == 'C') || 4133 (optionList->optval == 'H') || 4134 (optionList->optval == 'B') || 4135 (optionList->optval == 'a')) { 4136 /* 4137 * -C CHAP secret set 4138 * -H CHAP name set 4139 * -a authentication 4140 * -B bi-directional-authentication 4141 */ 4142 (void) fprintf(stderr, "%s: %s\n", 4143 cmdName, gettext("iscsi boot," 4144 " not allowed to modify" 4145 " authentication parameters" 4146 " of boot target")); 4147 return (1); 4148 } 4149 if (mpxioEnabled == IMA_FALSE) { 4150 (void) fprintf(stderr, "%s: %s\n", 4151 cmdName, gettext("iscsi boot and" 4152 " MPxIO is disabled, not allowed" 4153 " to modify boot target's" 4154 " parameters")); 4155 return (1); 4156 } 4157 4158 } 4159 4160 if (modifyIndividualTargetParam(optionList, targetOid, 4161 funcRet) != 0) { 4162 return (ret); 4163 } 4164 4165 /* 4166 * Even after finding a matched target, keep going 4167 * since there could be multiple target objects 4168 * associated with one target name in the system 4169 * because of different TPGTs. 4170 */ 4171 } 4172 } 4173 4174 /* If the target OID cannot be found create one */ 4175 if (!found) { 4176 status = SUN_IMA_CreateTargetOid(wcInputObject, &targetOid); 4177 if (!IMA_SUCCESS(status)) { 4178 printLibError(status); 4179 (void) IMA_FreeMemory(targetList); 4180 *funcRet = 1; 4181 return (ret); 4182 } 4183 if (modifyIndividualTargetParam(optionList, targetOid, 4184 funcRet) != 0) { 4185 return (ret); 4186 } 4187 } 4188 4189 (void) IMA_FreeMemory(targetList); 4190 return (ret); 4191 } 4192 4193 /* 4194 * Add one or more addresses 4195 */ 4196 static int 4197 addAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4198 { 4199 IMA_STATUS status; 4200 IMA_OID oid, addressOid; 4201 SUN_IMA_TARGET_ADDRESS address; 4202 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4203 int ret; 4204 int i; 4205 4206 assert(funcRet != NULL); 4207 4208 /* Find Sun initiator */ 4209 ret = sunInitiatorFind(&oid); 4210 if (ret > 0) { 4211 (void) fprintf(stderr, "%s: %s\n", 4212 cmdName, gettext("no initiator found")); 4213 } 4214 4215 if (ret != 0) { 4216 return (ret); 4217 } 4218 4219 /* 4220 * Format of discovery address operand: 4221 * 4222 * <IP address|hostname>:<port> 4223 */ 4224 for (i = 0; i < operandLen; i++) { 4225 /* initialize */ 4226 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4227 (void) memset(&address, 0, sizeof (address)); 4228 4229 if (mbstowcs(wcInputObject, operand[i], 4230 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 4231 (void) fprintf(stderr, "%s: %s\n", 4232 cmdName, gettext("conversion error")); 4233 ret = 1; 4234 continue; 4235 } 4236 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4237 != 0) { 4238 ret = 1; 4239 continue; 4240 } 4241 if (addrType == DISCOVERY_ADDRESS) { 4242 status = IMA_AddDiscoveryAddress(oid, 4243 address.imaStruct, &addressOid); 4244 if (!IMA_SUCCESS(status)) { 4245 printLibError(status); 4246 *funcRet = 1; 4247 return (ret); 4248 } 4249 } else if (addrType == ISNS_SERVER_ADDRESS) { 4250 status = SUN_IMA_AddISNSServerAddress(address); 4251 if (!IMA_SUCCESS(status)) { 4252 printLibError(status); 4253 *funcRet = 1; 4254 return (ret); 4255 } 4256 } 4257 } 4258 return (ret); 4259 } 4260 4261 /* 4262 * Add one or more static configuration targets 4263 */ 4264 static int 4265 addStaticConfig(int operandLen, char *operand[], int *funcRet) 4266 { 4267 int i; 4268 boolean_t targetAddressSpecified = B_FALSE; 4269 boolean_t tpgtSpecified = B_FALSE; 4270 boolean_t isIpv6 = B_FALSE; 4271 int ret; 4272 int addrType; 4273 IMA_STATUS status; 4274 IMA_OID oid; 4275 SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig; 4276 IMA_UINT16 port = 0; 4277 IMA_UINT16 tpgt = 0; 4278 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4279 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4280 iSCSINameCheckStatusType nameCheckStatus; 4281 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4282 4283 assert(funcRet != NULL); 4284 4285 /* Find Sun initiator */ 4286 ret = sunInitiatorFind(&oid); 4287 if (ret > 0) { 4288 (void) fprintf(stderr, "%s: %s\n", 4289 cmdName, gettext("no initiator found")); 4290 } 4291 4292 if (ret != 0) { 4293 return (ret); 4294 } 4295 4296 /* 4297 * Format of static config operand: 4298 * <target-name>,<IP address|hostname>[:port][,tpgt] 4299 */ 4300 for (i = 0; i < operandLen; i++) { 4301 if (parseTarget(operand[i], 4302 &staticTargetName[0], 4303 MAX_ISCSI_NAME_LEN + 1, 4304 &targetAddressSpecified, 4305 &staticTargetAddress[0], 4306 SUN_IMA_IP_ADDRESS_PORT_LEN, 4307 &port, 4308 &tpgtSpecified, 4309 &tpgt, 4310 &isIpv6) != PARSE_TARGET_OK) { 4311 ret = 1; 4312 continue; 4313 } 4314 4315 if (targetAddressSpecified != B_TRUE) { 4316 (void) fprintf(stderr, "%s: %s\n", 4317 cmdName, gettext("missing target address")); 4318 *funcRet = 1; /* DIY message fix */ 4319 return (1); 4320 } 4321 /* Perform string profile checks */ 4322 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4323 iSCSINameCheckStatusDisplay(nameCheckStatus); 4324 if (nameCheckStatus != iSCSINameCheckOK) { 4325 *funcRet = 1; /* DIY message fix */ 4326 return (1); 4327 } 4328 (void) wcsncpy(staticConfig.targetName, staticTargetName, 4329 MAX_ISCSI_NAME_LEN + 1); 4330 4331 (void) wcstombs(sAddr, staticTargetAddress, sizeof (sAddr)); 4332 4333 if (isIpv6 == B_TRUE) { 4334 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4335 id.ipAddress.ipv4Address = B_FALSE; 4336 addrType = AF_INET6; 4337 } else { 4338 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4339 id.ipAddress.ipv4Address = B_TRUE; 4340 addrType = AF_INET; 4341 } 4342 4343 if (inet_pton(addrType, sAddr, staticConfig.targetAddress. 4344 imaStruct.hostnameIpAddress.id.ipAddress.ipAddress) != 1) { 4345 (void) fprintf(stderr, "%s: %s\n", 4346 cmdName, gettext("static config conversion error")); 4347 ret = 1; 4348 continue; 4349 } 4350 4351 staticConfig.targetAddress.imaStruct.portNumber = port; 4352 if (tpgtSpecified == B_TRUE) { 4353 staticConfig.targetAddress.defaultTpgt = B_FALSE; 4354 staticConfig.targetAddress.tpgt = tpgt; 4355 } else { 4356 staticConfig.targetAddress.defaultTpgt = B_TRUE; 4357 staticConfig.targetAddress.tpgt = 0; 4358 } 4359 4360 status = SUN_IMA_AddStaticTarget(oid, staticConfig, &oid); 4361 if (!IMA_SUCCESS(status)) { 4362 printLibError(status); 4363 *funcRet = 1; 4364 return (1); 4365 } 4366 } 4367 4368 if (ret != 0) { 4369 *funcRet = 1; 4370 } 4371 4372 return (ret); 4373 } 4374 4375 /* 4376 * Remove one or more addresses 4377 */ 4378 static int 4379 removeAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4380 { 4381 IMA_STATUS status; 4382 IMA_OID initiatorOid; 4383 SUN_IMA_TARGET_ADDRESS address; 4384 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4385 int ret; 4386 int i; 4387 4388 assert(funcRet != NULL); 4389 4390 /* Find Sun initiator */ 4391 ret = sunInitiatorFind(&initiatorOid); 4392 if (ret > 0) { 4393 (void) fprintf(stderr, "%s: %s\n", 4394 cmdName, gettext("no initiator found")); 4395 } 4396 4397 if (ret != 0) { 4398 return (ret); 4399 } 4400 4401 for (i = 0; i < operandLen; i++) { 4402 /* initialize */ 4403 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4404 (void) memset(&address, 0, sizeof (address)); 4405 4406 if (mbstowcs(wcInputObject, operand[i], 4407 MAX_ADDRESS_LEN + 1) == (size_t)-1) { 4408 (void) fprintf(stderr, "%s: %s\n", 4409 cmdName, gettext("conversion error")); 4410 ret = 1; 4411 continue; 4412 } 4413 4414 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4415 != 0) { 4416 ret = 1; 4417 continue; 4418 } 4419 4420 if (addrType == DISCOVERY_ADDRESS) { 4421 status = SUN_IMA_RemoveDiscoveryAddress(address); 4422 if (!IMA_SUCCESS(status)) { 4423 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4424 (void) fprintf(stderr, "%s: %s\n", 4425 operand[i], gettext("not found")); 4426 } else { 4427 printLibError(status); 4428 } 4429 *funcRet = 1; 4430 } 4431 } else { 4432 status = SUN_IMA_RemoveISNSServerAddress(address); 4433 if (!IMA_SUCCESS(status)) { 4434 printLibError(status); 4435 *funcRet = 1; 4436 } 4437 } 4438 } 4439 return (ret); 4440 } 4441 4442 /* 4443 * Remove one or more static configuration targets 4444 */ 4445 static int 4446 removeStaticConfig(int operandLen, char *operand[], int *funcRet) 4447 { 4448 IMA_STATUS status; 4449 IMA_OID initiatorOid; 4450 IMA_OID_LIST *staticTargetList; 4451 SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps; 4452 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4453 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4454 int ret; 4455 boolean_t atLeastFoundOne; 4456 boolean_t matched; 4457 boolean_t targetAddressSpecified = B_TRUE; 4458 boolean_t tpgtSpecified = B_FALSE; 4459 boolean_t isIpv6 = B_FALSE; 4460 int i, j; 4461 IMA_UINT16 port = 0; 4462 IMA_UINT16 tpgt = 0; 4463 iSCSINameCheckStatusType nameCheckStatus; 4464 char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4465 wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4466 4467 assert(funcRet != NULL); 4468 4469 /* Find Sun initiator */ 4470 ret = sunInitiatorFind(&initiatorOid); 4471 if (ret > 0) { 4472 (void) fprintf(stderr, "%s: %s\n", 4473 cmdName, gettext("no initiator found")); 4474 } 4475 4476 if (ret != 0) { 4477 return (ret); 4478 } 4479 4480 status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid, 4481 &staticTargetList); 4482 if (!IMA_SUCCESS(status)) { 4483 printLibError(status); 4484 *funcRet = 1; 4485 return (ret); 4486 } 4487 4488 for (i = 0; i < operandLen; i++) { 4489 if (parseTarget(operand[i], 4490 &staticTargetName[0], 4491 MAX_ISCSI_NAME_LEN + 1, 4492 &targetAddressSpecified, 4493 &staticTargetAddress[0], 4494 SUN_IMA_IP_ADDRESS_PORT_LEN, 4495 &port, 4496 &tpgtSpecified, 4497 &tpgt, 4498 &isIpv6) != PARSE_TARGET_OK) { 4499 ret = 1; 4500 continue; 4501 } 4502 4503 /* Perform string profile checks */ 4504 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4505 iSCSINameCheckStatusDisplay(nameCheckStatus); 4506 if (nameCheckStatus != iSCSINameCheckOK) { 4507 return (1); 4508 } 4509 4510 for (atLeastFoundOne = B_FALSE, j = 0; 4511 j < staticTargetList->oidCount; 4512 j++) { 4513 IMA_UINT16 stpgt; 4514 4515 matched = B_FALSE; 4516 status = SUN_IMA_GetStaticTargetProperties( 4517 staticTargetList->oids[j], &staticTargetProps); 4518 if (!IMA_SUCCESS(status)) { 4519 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4520 /* 4521 * When removing multiple static-config 4522 * entries we need to expect get 4523 * failures. These failures occur when 4524 * we are trying to get entry 4525 * information we have just removed. 4526 * Ignore the failure and continue. 4527 */ 4528 ret = 1; 4529 continue; 4530 } else { 4531 printLibError(status); 4532 (void) IMA_FreeMemory(staticTargetList); 4533 *funcRet = 1; 4534 return (ret); 4535 } 4536 } 4537 4538 stpgt = 4539 staticTargetProps.staticTarget.targetAddress.tpgt; 4540 4541 /* 4542 * Compare the static target name with the input if 4543 * one was input 4544 */ 4545 if ((targetNamesEqual( 4546 staticTargetProps.staticTarget.targetName, 4547 staticTargetName) == B_TRUE)) { 4548 if (targetAddressSpecified == B_FALSE) { 4549 matched = B_TRUE; 4550 } else { 4551 4552 if (staticTargetProps.staticTarget. 4553 targetAddress.imaStruct. 4554 hostnameIpAddress. 4555 id.ipAddress.ipv4Address == 4556 IMA_TRUE) { 4557 (void) inet_ntop(AF_INET, 4558 staticTargetProps. 4559 staticTarget.targetAddress. 4560 imaStruct.hostnameIpAddress. 4561 id.ipAddress.ipAddress, 4562 tmpStr, 4563 sizeof (tmpStr)); 4564 } else { 4565 (void) inet_ntop(AF_INET6, 4566 staticTargetProps. 4567 staticTarget.targetAddress. 4568 imaStruct.hostnameIpAddress. 4569 id.ipAddress.ipAddress, 4570 tmpStr, 4571 sizeof (tmpStr)); 4572 } 4573 4574 if (mbstowcs(tmpTargetAddress, tmpStr, 4575 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4576 (size_t)-1) { 4577 (void) fprintf(stderr, 4578 "%s: %s\n", 4579 cmdName, gettext( 4580 "conversion error")); 4581 ret = 1; 4582 continue; 4583 } 4584 4585 if ((wcsncmp(tmpTargetAddress, 4586 staticTargetAddress, 4587 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4588 0) && (staticTargetProps. 4589 staticTarget.targetAddress. 4590 imaStruct.portNumber == port)) { 4591 if (tpgtSpecified == B_FALSE) { 4592 matched = B_TRUE; 4593 } else { 4594 if (tpgt == stpgt) { 4595 matched = 4596 B_TRUE; 4597 } 4598 } 4599 } 4600 } 4601 4602 if (matched) { 4603 status = 4604 IMA_RemoveStaticDiscoveryTarget( 4605 staticTargetList->oids[j]); 4606 if (!IMA_SUCCESS(status)) { 4607 printLibError(status); 4608 *funcRet = 1; 4609 return (ret); 4610 } 4611 atLeastFoundOne = B_TRUE; 4612 } 4613 } 4614 } 4615 if (!atLeastFoundOne) { 4616 (void) fprintf(stderr, gettext("%ws,%ws: %s\n"), 4617 staticTargetName, staticTargetAddress, 4618 gettext("not found")); 4619 } 4620 } 4621 return (ret); 4622 } 4623 4624 /* 4625 * Remove one or more target params. 4626 */ 4627 static int 4628 removeTargetParam(int operandLen, char *operand[], int *funcRet) 4629 { 4630 char *commaPos; 4631 IMA_STATUS status; 4632 IMA_OID initiatorOid; 4633 IMA_OID_LIST *targetList; 4634 SUN_IMA_TARGET_PROPERTIES targetProps; 4635 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 4636 int ret; 4637 boolean_t found; 4638 int i, j; 4639 IMA_NODE_NAME bootTargetName; 4640 IMA_BOOL iscsiBoot = IMA_FALSE; 4641 IMA_BOOL mpxioEnabled = IMA_FALSE; 4642 4643 /* Get boot session's info */ 4644 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 4645 if (iscsiBoot == IMA_TRUE) { 4646 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 4647 if (!IMA_SUCCESS(status)) { 4648 (void) fprintf(stderr, "%s: %s\n", 4649 cmdName, gettext("unable to get MPxIO info of" 4650 " root disk")); 4651 *funcRet = 1; 4652 return (1); 4653 } 4654 status = SUN_IMA_GetBootTargetName(bootTargetName); 4655 if (!IMA_SUCCESS(status)) { 4656 (void) fprintf(stderr, "%s: %s\n", 4657 cmdName, gettext("unable to get boot" 4658 " target's name")); 4659 *funcRet = 1; 4660 return (1); 4661 } 4662 } 4663 4664 assert(funcRet != NULL); 4665 4666 /* Find Sun initiator */ 4667 ret = sunInitiatorFind(&initiatorOid); 4668 if (ret > 0) { 4669 (void) fprintf(stderr, "%s: %s\n", 4670 cmdName, gettext("no initiator found")); 4671 } 4672 4673 if (ret != 0) { 4674 return (ret); 4675 } 4676 4677 status = IMA_GetTargetOidList(initiatorOid, &targetList); 4678 if (!IMA_SUCCESS(status)) { 4679 printLibError(status); 4680 *funcRet = 1; 4681 return (ret); 4682 } 4683 4684 for (i = 0; i < operandLen; i++) { 4685 /* initialize */ 4686 commaPos = strchr(operand[i], ','); 4687 if (commaPos) { 4688 /* Ignore IP address. */ 4689 *commaPos = NULL; 4690 } 4691 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4692 if (mbstowcs(wcInputObject, operand[i], 4693 MAX_ISCSI_NAME_LEN + 1) == (size_t)-1) { 4694 (void) fprintf(stderr, "%s: %s\n", cmdName, 4695 gettext("conversion error")); 4696 ret = 1; 4697 continue; 4698 } 4699 4700 for (found = B_FALSE, j = 0; j < targetList->oidCount; 4701 j++) { 4702 status = SUN_IMA_GetTargetProperties( 4703 targetList->oids[j], &targetProps); 4704 if (!IMA_SUCCESS(status)) { 4705 printLibError(status); 4706 (void) IMA_FreeMemory(targetList); 4707 *funcRet = 1; 4708 return (ret); 4709 } 4710 4711 /* 4712 * Compare the target name with the input if 4713 * one was input 4714 */ 4715 if (targetNamesEqual(targetProps.imaProps.name, 4716 wcInputObject) == B_TRUE) { 4717 found = B_TRUE; 4718 if ((targetNamesEqual(bootTargetName, 4719 wcInputObject) == B_TRUE) && 4720 (iscsiBoot == IMA_TRUE)) { 4721 /* 4722 * iscsi booting, need changed target 4723 * param is booting target, booting 4724 * session mpxio disabled, not 4725 * allow to update 4726 */ 4727 if (mpxioEnabled == IMA_FALSE) { 4728 (void) fprintf(stderr, 4729 "%s: %s\n", cmdName, 4730 gettext("iscsi boot" 4731 " with MPxIO disabled," 4732 " not allowed to remove" 4733 " boot sess param")); 4734 ret = 1; 4735 continue; 4736 } 4737 4738 } 4739 4740 status = SUN_IMA_RemoveTargetParam( 4741 targetList->oids[j]); 4742 if (!IMA_SUCCESS(status)) { 4743 printLibError(status); 4744 (void) IMA_FreeMemory(targetList); 4745 *funcRet = 1; 4746 return (ret); 4747 } 4748 } 4749 } 4750 if (!found) { 4751 /* Silently ignoring it? */ 4752 (void) fprintf(stderr, gettext("%ws: %s\n"), 4753 wcInputObject, gettext("not found")); 4754 } 4755 } 4756 4757 (void) IMA_FreeMemory(targetList); 4758 return (ret); 4759 } 4760 4761 /*ARGSUSED*/ 4762 static int 4763 addFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4764 void *addArgs, int *funcRet) 4765 { 4766 int ret; 4767 4768 assert(funcRet != NULL); 4769 4770 switch (object) { 4771 case DISCOVERY_ADDRESS: 4772 case ISNS_SERVER_ADDRESS: 4773 ret = addAddress(object, operandLen, operand, funcRet); 4774 break; 4775 case STATIC_CONFIG: 4776 ret = addStaticConfig(operandLen, operand, funcRet); 4777 break; 4778 default: 4779 (void) fprintf(stderr, "%s: %s\n", 4780 cmdName, gettext("unknown object")); 4781 ret = 1; 4782 break; 4783 } 4784 return (ret); 4785 } 4786 4787 /*ARGSUSED*/ 4788 static int 4789 listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4790 void *addArgs, int *funcRet) 4791 { 4792 int ret; 4793 4794 assert(funcRet != NULL); 4795 4796 switch (object) { 4797 case DISCOVERY: 4798 ret = listDiscovery(funcRet); 4799 break; 4800 case DISCOVERY_ADDRESS: 4801 ret = listDiscoveryAddress(operandLen, operand, options, 4802 funcRet); 4803 break; 4804 case ISNS_SERVER_ADDRESS: 4805 ret = listISNSServerAddress(operandLen, operand, options, 4806 funcRet); 4807 break; 4808 case NODE: 4809 ret = listNode(funcRet); 4810 break; 4811 case STATIC_CONFIG: 4812 ret = listStaticConfig(operandLen, operand, funcRet); 4813 break; 4814 case TARGET: 4815 ret = listTarget(operandLen, operand, options, funcRet); 4816 break; 4817 case TARGET_PARAM: 4818 ret = listTargetParam(operandLen, operand, options, funcRet); 4819 break; 4820 default: 4821 (void) fprintf(stderr, "%s: %s\n", 4822 cmdName, gettext("unknown object")); 4823 ret = 1; 4824 break; 4825 } 4826 return (ret); 4827 } 4828 4829 /*ARGSUSED*/ 4830 static int 4831 modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4832 void *addArgs, int *funcRet) 4833 { 4834 int ret, i; 4835 4836 assert(funcRet != NULL); 4837 4838 switch (object) { 4839 case DISCOVERY: 4840 ret = modifyDiscovery(options, funcRet); 4841 break; 4842 case NODE: 4843 ret = modifyNode(options, funcRet); 4844 break; 4845 case TARGET_PARAM: 4846 i = 0; 4847 while (operand[i]) { 4848 ret = modifyTargetParam(options, operand[i], funcRet); 4849 4850 if (ret) { 4851 (void) fprintf(stderr, "%s: %s: %s\n", 4852 cmdName, gettext("modify failed"), 4853 operand[i]); 4854 return (ret); 4855 } 4856 i++; 4857 } 4858 4859 break; 4860 default: 4861 (void) fprintf(stderr, "%s: %s\n", 4862 cmdName, gettext("unknown object")); 4863 ret = 1; 4864 break; 4865 } 4866 return (ret); 4867 } 4868 4869 /*ARGSUSED*/ 4870 static int 4871 removeFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4872 void *addArgs, int *funcRet) 4873 { 4874 int ret; 4875 4876 switch (object) { 4877 case DISCOVERY_ADDRESS: 4878 case ISNS_SERVER_ADDRESS: 4879 ret = removeAddress(object, operandLen, operand, 4880 funcRet); 4881 break; 4882 case STATIC_CONFIG: 4883 ret = removeStaticConfig(operandLen, operand, funcRet); 4884 break; 4885 case TARGET_PARAM: 4886 ret = removeTargetParam(operandLen, operand, funcRet); 4887 break; 4888 default: 4889 (void) fprintf(stderr, "%s: %s\n", 4890 cmdName, gettext("unknown object")); 4891 ret = 1; 4892 break; 4893 } 4894 return (ret); 4895 } 4896 4897 static void 4898 iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status) 4899 { 4900 switch (status) { 4901 case iSCSINameLenZero: 4902 (void) fprintf(stderr, "%s: %s\n", 4903 cmdName, gettext("empty iSCSI name.")); 4904 break; 4905 case iSCSINameLenExceededMax: 4906 (void) fprintf(stderr, "%s: %s\n", cmdName, 4907 gettext("iSCSI name exceeded maximum length.")); 4908 break; 4909 case iSCSINameUnknownType: 4910 (void) fprintf(stderr, "%s: %s\n", cmdName, 4911 gettext("unknown iSCSI name type.")); 4912 break; 4913 case iSCSINameInvalidCharacter: 4914 (void) fprintf(stderr, "%s: %s\n", 4915 cmdName, 4916 gettext("iSCSI name invalid character used")); 4917 break; 4918 case iSCSINameIqnFormatError: 4919 (void) fprintf(stderr, "%s: %s\n", cmdName, 4920 gettext("iqn formatting error.")); 4921 break; 4922 case iSCSINameIqnDateFormatError: 4923 (void) fprintf(stderr, "%s: %s\n", 4924 cmdName, gettext("invalid iqn date." \ 4925 " format is: YYYY-MM")); 4926 break; 4927 case iSCSINameIqnSubdomainFormatError: 4928 (void) fprintf(stderr, "%s: %s\n", 4929 cmdName, gettext("missing subdomain after \":\"")); 4930 break; 4931 case iSCSINameIqnInvalidYearError: 4932 (void) fprintf(stderr, "%s: %s\n", 4933 cmdName, gettext("invalid year")); 4934 break; 4935 case iSCSINameIqnInvalidMonthError: 4936 (void) fprintf(stderr, "%s: %s\n", 4937 cmdName, gettext("invalid month")); 4938 break; 4939 case iSCSINameIqnFQDNError: 4940 (void) fprintf(stderr, "%s: %s\n", 4941 cmdName, gettext("missing reversed fully qualified"\ 4942 " domain name")); 4943 break; 4944 case iSCSINameEUIFormatError: 4945 (void) fprintf(stderr, "%s: %s\n", cmdName, 4946 gettext("eui formatting error.")); 4947 break; 4948 } 4949 } 4950 4951 /* 4952 * A convenient function to modify the target parameters of an individual 4953 * target. 4954 * 4955 * Return 0 if successful 4956 * Return 1 if failed 4957 */ 4958 static int 4959 modifyIndividualTargetParam(cmdOptions_t *optionList, IMA_OID targetOid, 4960 int *funcRet) 4961 { 4962 assert(funcRet != NULL); 4963 4964 for (; optionList->optval; optionList++) { 4965 switch (optionList->optval) { 4966 case 'a': 4967 if (modifyTargetAuthMethod(targetOid, 4968 optionList->optarg, funcRet) != 0) { 4969 return (1); 4970 } 4971 break; 4972 case 'B': 4973 if (modifyTargetBidirAuthFlag(targetOid, 4974 optionList->optarg, funcRet) != 0) { 4975 return (1); 4976 } 4977 break; 4978 case 'C': 4979 if (modifyTargetAuthParam(targetOid, 4980 AUTH_PASSWORD, NULL, funcRet) != 0) { 4981 return (1); 4982 } 4983 break; 4984 case 'd': 4985 if (setLoginParameter(targetOid, DATA_DIGEST, 4986 optionList->optarg) != 0) { 4987 return (1); 4988 } 4989 break; 4990 case 'h': 4991 if (setLoginParameter(targetOid, HEADER_DIGEST, 4992 optionList->optarg) != 0) { 4993 return (1); 4994 } 4995 break; 4996 case 'p': 4997 /* Login parameter */ 4998 if (setLoginParameters(targetOid, 4999 optionList->optarg) != 0) { 5000 return (1); 5001 } 5002 break; 5003 case 'c': 5004 /* Modify configure sessions */ 5005 if (modifyConfiguredSessions(targetOid, 5006 optionList->optarg) != 0) { 5007 return (1); 5008 } 5009 break; 5010 case 'H': 5011 if (modifyTargetAuthParam(targetOid, AUTH_NAME, 5012 optionList->optarg, funcRet) != 0) { 5013 return (1); 5014 } 5015 break; 5016 case 'T': 5017 if (setTunableParameters(targetOid, 5018 optionList->optarg) != 0) { 5019 return (1); 5020 } 5021 break; 5022 } 5023 } 5024 5025 return (0); 5026 } 5027 5028 /* 5029 * This helper function could go into a utility module for general use. 5030 */ 5031 static int 5032 parseAddress(char *address_port_str, 5033 uint16_t defaultPort, 5034 char *address_str, 5035 size_t address_str_len, 5036 uint16_t *port, 5037 boolean_t *isIpv6) 5038 { 5039 char port_str[64]; 5040 int tmp_port; 5041 char *errchr; 5042 5043 if (address_port_str[0] == '[') { 5044 /* IPv6 address */ 5045 char *close_bracket_pos; 5046 close_bracket_pos = strchr(address_port_str, ']'); 5047 if (!close_bracket_pos) { 5048 syslog(LOG_USER|LOG_DEBUG, 5049 "IP address format error: %s\n", address_str); 5050 return (PARSE_ADDR_MISSING_CLOSING_BRACKET); 5051 } 5052 5053 *close_bracket_pos = NULL; 5054 (void) strlcpy(address_str, &address_port_str[1], 5055 address_str_len); 5056 5057 /* Extract the port number */ 5058 close_bracket_pos++; 5059 if (*close_bracket_pos == ':') { 5060 close_bracket_pos++; 5061 if (*close_bracket_pos != NULL) { 5062 (void) strlcpy(port_str, close_bracket_pos, 64); 5063 tmp_port = strtol(port_str, &errchr, 10); 5064 if (tmp_port == 0 && errchr != NULL) { 5065 (void) fprintf(stderr, "%s: %s:%s %s\n", 5066 cmdName, address_str, 5067 close_bracket_pos, 5068 gettext("port number invalid")); 5069 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5070 } 5071 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 5072 (tmp_port < 0)) { 5073 /* Port number out of range */ 5074 syslog(LOG_USER|LOG_DEBUG, 5075 "Specified port out of range: %d", 5076 tmp_port); 5077 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5078 } else { 5079 *port = (uint16_t)tmp_port; 5080 } 5081 } else { 5082 *port = defaultPort; 5083 } 5084 } else { 5085 *port = defaultPort; 5086 } 5087 5088 *isIpv6 = B_TRUE; 5089 } else { 5090 /* IPv4 address */ 5091 char *colon_pos; 5092 colon_pos = strchr(address_port_str, ':'); 5093 if (!colon_pos) { 5094 /* No port number specified. */ 5095 *port = defaultPort; 5096 (void) strlcpy(address_str, address_port_str, 5097 address_str_len); 5098 } else { 5099 *colon_pos = (char)NULL; 5100 (void) strlcpy(address_str, address_port_str, 5101 address_str_len); 5102 5103 /* Extract the port number */ 5104 colon_pos++; 5105 if (*colon_pos != NULL) { 5106 5107 (void) strlcpy(port_str, colon_pos, 64); 5108 tmp_port = strtol(port_str, &errchr, 10); 5109 if (tmp_port == 0 && errchr != NULL) { 5110 (void) fprintf(stderr, "%s: %s:%s %s\n", 5111 cmdName, address_str, colon_pos, 5112 gettext("port number invalid")); 5113 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5114 } 5115 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 5116 (tmp_port < 0)) { 5117 /* Port number out of range */ 5118 syslog(LOG_USER|LOG_DEBUG, 5119 "Specified port out of range: %d", 5120 tmp_port); 5121 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5122 } else { 5123 *port = (uint16_t)tmp_port; 5124 } 5125 } else { 5126 *port = defaultPort; 5127 } 5128 } 5129 5130 *isIpv6 = B_FALSE; 5131 } 5132 5133 return (PARSE_ADDR_OK); 5134 } 5135 5136 /* 5137 * This helper function could go into a utility module for general use. 5138 */ 5139 iSCSINameCheckStatusType 5140 iSCSINameStringProfileCheck(wchar_t *name) 5141 { 5142 char mb_name[MAX_ISCSI_NAME_LEN + 1]; 5143 size_t name_len; 5144 char *tmp; 5145 5146 (void) wcstombs(mb_name, name, MAX_ISCSI_NAME_LEN + 1); 5147 5148 if ((name_len = strlen(mb_name)) == 0) { 5149 return (iSCSINameLenZero); 5150 } else if (name_len > MAX_ISCSI_NAME_LEN) { 5151 return (iSCSINameLenExceededMax); 5152 } 5153 5154 /* 5155 * check for invalid characters 5156 * According to RFC 3722 iSCSI name must be either a letter, 5157 * a digit or one of the following '-' '.' ':' 5158 */ 5159 for (tmp = mb_name; *tmp != NULL; tmp++) { 5160 if ((isalnum(*tmp) == 0) && 5161 (*tmp != '-') && 5162 (*tmp != '.') && 5163 (*tmp != ':')) { 5164 return (iSCSINameInvalidCharacter); 5165 } 5166 } 5167 5168 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 5169 strlen(ISCSI_IQN_NAME_PREFIX)) == 0) { 5170 /* 5171 * If name is of type iqn, check date string and naming 5172 * authority. 5173 */ 5174 char *strp = NULL; 5175 5176 /* 5177 * Don't allow the string to end with a colon. If there is a 5178 * colon then there must be a subdomain provided. 5179 */ 5180 if (mb_name[strlen(mb_name) - 1] == ':') { 5181 return (iSCSINameIqnSubdomainFormatError); 5182 } 5183 5184 /* Date string */ 5185 strp = strtok(&mb_name[3], "."); 5186 if (strp) { 5187 char tmpYear[5], tmpMonth[3], *endPtr = NULL; 5188 int year, month; 5189 5190 /* Date string should be in YYYY-MM format */ 5191 if (strlen(strp) != strlen("YYYY-MM") || 5192 strp[4] != '-') { 5193 return (iSCSINameIqnDateFormatError); 5194 } 5195 5196 /* 5197 * Validate year. Only validating that the 5198 * year can be converted to a number. No 5199 * validation will be done on year's actual 5200 * value. 5201 */ 5202 (void) strncpy(tmpYear, strp, 4); 5203 tmpYear[4] = '\0'; 5204 5205 errno = 0; 5206 year = strtol(tmpYear, &endPtr, 10); 5207 if (errno != 0 || *endPtr != '\0' || 5208 year < 0 || year > 9999) { 5209 return (iSCSINameIqnInvalidYearError); 5210 } 5211 5212 /* 5213 * Validate month is valid. 5214 */ 5215 (void) strncpy(tmpMonth, &strp[5], 2); 5216 tmpMonth[2] = '\0'; 5217 errno = 0; 5218 month = strtol(tmpMonth, &endPtr, 10); 5219 5220 if (errno != 0 || *endPtr != '\0' || 5221 month < 1 || month > 12) { 5222 return (iSCSINameIqnInvalidMonthError); 5223 } 5224 5225 /* 5226 * A reversed FQDN needs to be provided. We 5227 * will only check for a "." followed by more 5228 * than two or more characters. The list of domains is 5229 * too large and changes too frequently to 5230 * add validation for. 5231 */ 5232 strp = strtok(NULL, "."); 5233 if (!strp || strlen(strp) < 2) { 5234 return (iSCSINameIqnFQDNError); 5235 } 5236 5237 /* Name authority string */ 5238 strp = strtok(NULL, ":"); 5239 if (strp) { 5240 return (iSCSINameCheckOK); 5241 } else { 5242 return (iSCSINameIqnFQDNError); 5243 } 5244 } else { 5245 return (iSCSINameIqnFormatError); 5246 } 5247 } else if (strncmp(mb_name, ISCSI_EUI_NAME_PREFIX, 5248 strlen(ISCSI_EUI_NAME_PREFIX)) == 0) { 5249 /* If name is of type EUI, change its length */ 5250 5251 if (strlen(mb_name) != ISCSI_EUI_NAME_LEN) { 5252 return (iSCSINameEUIFormatError); 5253 } 5254 5255 for (tmp = mb_name + strlen(ISCSI_EUI_NAME_PREFIX) + 1; 5256 *tmp != '\0'; tmp++) { 5257 if (isxdigit(*tmp)) { 5258 continue; 5259 } 5260 return (iSCSINameEUIFormatError); 5261 } 5262 5263 return (iSCSINameCheckOK); 5264 } else { 5265 return (iSCSINameUnknownType); 5266 } 5267 } 5268 5269 /* 5270 * This helper function could go into a utility module for general use. 5271 * 5272 * Returns: 5273 * B_TRUE is the numberStr is an unsigned natural number and within the 5274 * specified bound. 5275 * B_FALSE otherwise. 5276 */ 5277 boolean_t 5278 isNaturalNumber(char *numberStr, uint32_t upperBound) 5279 { 5280 int i; 5281 int number_str_len; 5282 5283 if ((number_str_len = strlen(numberStr)) == 0) { 5284 return (B_FALSE); 5285 } 5286 5287 for (i = 0; i < number_str_len; i++) { 5288 if (numberStr[i] < 060 || numberStr[i] > 071) { 5289 return (B_FALSE); 5290 } 5291 } 5292 5293 if (atoi(numberStr) > upperBound) { 5294 return (B_FALSE); 5295 } 5296 5297 return (B_TRUE); 5298 } 5299 5300 /* 5301 * This helper function could go into a utility module for general use. 5302 * It parses a target string in the format of: 5303 * 5304 * <target_name>,[<ip_address>[:port][,tpgt]] 5305 * 5306 * and creates wchar strings for target name and target address. It 5307 * also populates port and tpgt if found. 5308 * 5309 * Returns: 5310 * PARSE_TARGET_OK if parsing is successful. 5311 * PARSE_TARGET_INVALID_TPGT if the specified tpgt is 5312 * invalid. 5313 * PARSE_TARGET_INVALID_ADDR if the address specified is 5314 * invalid. 5315 */ 5316 int 5317 parseTarget(char *targetStr, 5318 wchar_t *targetNameStr, 5319 size_t targetNameStrLen, 5320 boolean_t *targetAddressSpecified, 5321 wchar_t *targetAddressStr, 5322 size_t targetAddressStrLen, 5323 uint16_t *port, 5324 boolean_t *tpgtSpecified, 5325 uint16_t *tpgt, 5326 boolean_t *isIpv6) 5327 { 5328 char *commaPos; 5329 char *commaPos2; 5330 char targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 5331 int i; 5332 int lowerCase; 5333 5334 (void) memset(targetNameStr, 0, 5335 targetNameStrLen * sizeof (wchar_t)); 5336 (void) memset(targetAddressStr, 0, 5337 targetAddressStrLen * sizeof (wchar_t)); 5338 5339 commaPos = strchr(targetStr, ','); 5340 if (commaPos != NULL) { 5341 *commaPos = NULL; 5342 commaPos++; 5343 *targetAddressSpecified = B_TRUE; 5344 5345 /* 5346 * Checking of tpgt makes sense only when 5347 * the target address/port are specified. 5348 */ 5349 commaPos2 = strchr(commaPos, ','); 5350 if (commaPos2 != NULL) { 5351 *commaPos2 = NULL; 5352 commaPos2++; 5353 if (isNaturalNumber(commaPos2, ISCSI_MAX_TPGT_VALUE) == 5354 B_TRUE) { 5355 *tpgt = atoi(commaPos2); 5356 *tpgtSpecified = B_TRUE; 5357 } else { 5358 (void) fprintf(stderr, "%s: %s\n", cmdName, 5359 gettext("parse target invalid TPGT")); 5360 return (PARSE_TARGET_INVALID_TPGT); 5361 } 5362 } 5363 5364 switch (parseAddress(commaPos, ISCSI_LISTEN_PORT, 5365 &targetAddress[0], MAX_ADDRESS_LEN + 1, port, isIpv6)) { 5366 case PARSE_ADDR_PORT_OUT_OF_RANGE: 5367 return (PARSE_TARGET_INVALID_ADDR); 5368 case PARSE_ADDR_OK: 5369 break; 5370 default: 5371 (void) fprintf(stderr, "%s: %s\n", 5372 cmdName, gettext("cannot parse target name")); 5373 return (PARSE_TARGET_INVALID_ADDR); 5374 } 5375 (void) mbstowcs(targetAddressStr, targetAddress, 5376 targetAddressStrLen); 5377 for (i = 0; targetAddressStr[i] != 0; i++) { 5378 lowerCase = tolower(targetAddressStr[i]); 5379 targetAddressStr[i] = lowerCase; 5380 } 5381 } else { 5382 *targetAddressSpecified = B_FALSE; 5383 *tpgtSpecified = B_FALSE; 5384 } 5385 5386 (void) mbstowcs(targetNameStr, targetStr, targetNameStrLen); 5387 for (i = 0; targetNameStr[i] != 0; i++) { 5388 lowerCase = tolower(targetNameStr[i]); 5389 targetNameStr[i] = lowerCase; 5390 } 5391 5392 return (PARSE_TARGET_OK); 5393 } 5394 5395 /*ARGSUSED*/ 5396 static void 5397 listCHAPName(IMA_OID oid) 5398 { 5399 IMA_INITIATOR_AUTHPARMS authParams; 5400 IMA_STATUS status; 5401 IMA_BYTE chapName [MAX_CHAP_NAME_LEN + 1]; 5402 5403 /* Get Chap Name depending upon oid object type */ 5404 if (oid.objectType == IMA_OBJECT_TYPE_LHBA) { 5405 status = IMA_GetInitiatorAuthParms(oid, 5406 IMA_AUTHMETHOD_CHAP, &authParams); 5407 } else { 5408 status = SUN_IMA_GetTargetAuthParms(oid, 5409 IMA_AUTHMETHOD_CHAP, &authParams); 5410 } 5411 5412 (void) fprintf(stdout, "\n\t\t%s: ", gettext("CHAP Name")); 5413 5414 if (IMA_SUCCESS(status)) { 5415 /* 5416 * Default chap name will be the node name. The default will 5417 * be set by the driver. 5418 */ 5419 if (authParams.chapParms.nameLength != 0) { 5420 (void) memset(chapName, 0, sizeof (chapName)); 5421 (void) memcpy(chapName, authParams.chapParms.name, 5422 authParams.chapParms.nameLength); 5423 (void) fprintf(stdout, "%s", chapName); 5424 5425 } else { 5426 (void) fprintf(stdout, "%s", "-"); 5427 } 5428 } else { 5429 (void) fprintf(stdout, "%s", "-"); 5430 } 5431 } 5432 5433 static boolean_t 5434 checkServiceStatus(void) 5435 { 5436 IMA_STATUS status = IMA_ERROR_UNKNOWN_ERROR; 5437 IMA_BOOL enabled = 0; 5438 5439 status = SUN_IMA_GetSvcStatus(&enabled); 5440 5441 if (status != IMA_STATUS_SUCCESS) { 5442 (void) fprintf(stdout, "%s\n%s\n", 5443 gettext("Unable to query the service status of" 5444 " iSCSI initiator."), 5445 gettext("For more information, please refer to" 5446 " iscsi(7D).")); 5447 return (B_FALSE); 5448 } 5449 5450 if (enabled == 0) { 5451 (void) fprintf(stdout, "%s\n%s\n", 5452 gettext("iSCSI Initiator Service is disabled," 5453 " try 'svcadm enable network/iscsi/initiator' to" 5454 " enable the service."), 5455 gettext("For more information, please refer to" 5456 " iscsi(7D).")); 5457 return (B_FALSE); 5458 } 5459 5460 return (B_TRUE); 5461 } 5462 5463 /* 5464 * Prints out see manual page. 5465 * Called out through atexit(3C) so is always last thing displayed. 5466 */ 5467 void 5468 seeMan(void) 5469 { 5470 static int sent = 0; 5471 5472 if (sent) 5473 return; 5474 5475 (void) fprintf(stdout, "%s %s(1M)\n", 5476 gettext("For more information, please see"), cmdName); 5477 5478 sent = 1; 5479 } 5480 5481 5482 /* 5483 * main calls a parser that checks syntax of the input command against 5484 * various rules tables. 5485 * 5486 * The parser provides usage feedback based upon same tables by calling 5487 * two usage functions, usage and subUsage, handling command and subcommand 5488 * usage respectively. 5489 * 5490 * The parser handles all printing of usage syntactical errors 5491 * 5492 * When syntax is successfully validated, the parser calls the associated 5493 * function using the subcommands table functions. 5494 * 5495 * Syntax is as follows: 5496 * command subcommand [options] resource-type [<object>] 5497 * 5498 * The return value from the function is placed in funcRet 5499 */ 5500 int 5501 main(int argc, char *argv[]) 5502 { 5503 synTables_t synTables; 5504 char versionString[VERSION_STRING_MAX_LEN]; 5505 int ret; 5506 int funcRet = 0; 5507 void *subcommandArgs = NULL; 5508 5509 if (geteuid() != 0) { 5510 (void) fprintf(stderr, "%s\n", gettext("permission denied")); 5511 return (1); 5512 } 5513 5514 if (checkServiceStatus() == B_FALSE) { 5515 return (1); 5516 } 5517 5518 /* set global command name */ 5519 cmdName = getExecBasename(argv[0]); 5520 5521 (void) snprintf(versionString, sizeof (versionString), "%s.%s", 5522 VERSION_STRING_MAJOR, VERSION_STRING_MINOR); 5523 synTables.versionString = versionString; 5524 synTables.longOptionTbl = &longOptions[0]; 5525 synTables.subcommandTbl = &subcommands[0]; 5526 synTables.objectTbl = &objects[0]; 5527 synTables.objectRulesTbl = &objectRules[0]; 5528 synTables.optionRulesTbl = &optionRules[0]; 5529 5530 /* call the CLI parser */ 5531 ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); 5532 if (ret == -1) { 5533 perror(cmdName); 5534 ret = 1; 5535 } 5536 5537 if (funcRet != 0) { 5538 (void) fprintf(stderr, "%s: %s\n", 5539 cmdName, gettext("Unable to complete operation")); 5540 ret = 1; 5541 } 5542 return (ret); 5543 } 5544 5545 static int 5546 setTunableParameters(IMA_OID oid, char *optarg) 5547 { 5548 char keyp[MAXOPTARGLEN]; 5549 char valp[MAXOPTARGLEN]; 5550 int key; 5551 IMA_STATUS status; 5552 IMA_UINT uintValue; 5553 ISCSI_TUNABLE_PARAM tunableObj; 5554 char *nameValueString, *endptr; 5555 5556 if ((nameValueString = strdup(optarg)) == NULL) { 5557 if (errno == ENOMEM) { 5558 (void) fprintf(stderr, "%s: %s\n", 5559 cmdName, strerror(errno)); 5560 } else { 5561 (void) fprintf(stderr, "%s: %s\n", cmdName, 5562 gettext("unknown error")); 5563 } 5564 return (1); 5565 } 5566 5567 (void) memset(keyp, 0, sizeof (keyp)); 5568 (void) memset(valp, 0, sizeof (valp)); 5569 if (sscanf(nameValueString, gettext("%[^=]=%s"), keyp, valp) != 2) { 5570 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5571 gettext("Unknown param"), nameValueString); 5572 if (nameValueString) { 5573 free(nameValueString); 5574 nameValueString = NULL; 5575 } 5576 return (1); 5577 } 5578 if ((key = getTunableParam(keyp)) == -1) { 5579 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5580 gettext("Unknown key"), keyp); 5581 if (nameValueString) { 5582 free(nameValueString); 5583 nameValueString = NULL; 5584 } 5585 return (1); 5586 } 5587 switch (key) { 5588 case RECV_LOGIN_RSP_TIMEOUT: 5589 case CONN_LOGIN_MAX: 5590 case POLLING_LOGIN_DELAY: 5591 errno = 0; 5592 uintValue = strtoul(valp, &endptr, 0); 5593 if (*endptr != '\0' || errno != 0) { 5594 (void) fprintf(stderr, "%s: %s - %s\n", 5595 cmdName, 5596 gettext("invalid option argument"), 5597 optarg); 5598 if (nameValueString) { 5599 free(nameValueString); 5600 nameValueString = NULL; 5601 } 5602 return (1); 5603 } 5604 if (uintValue > 3600) { 5605 (void) fprintf(stderr, "%s: %s\n", 5606 cmdName, 5607 gettext("value must be between 0 and 3600")); 5608 if (nameValueString) { 5609 free(nameValueString); 5610 nameValueString = NULL; 5611 } 5612 return (1); 5613 } 5614 5615 if (chkConnLoginMaxPollingLoginDelay(oid, key, uintValue) > 0) { 5616 if (nameValueString) { 5617 free(nameValueString); 5618 nameValueString = NULL; 5619 } 5620 return (1); 5621 } 5622 5623 if (key == RECV_LOGIN_RSP_TIMEOUT) { 5624 tunableObj.tunable_objectType = 5625 ISCSI_RX_TIMEOUT_VALUE; 5626 } else if (key == CONN_LOGIN_MAX) { 5627 tunableObj.tunable_objectType = 5628 ISCSI_CONN_DEFAULT_LOGIN_MAX; 5629 } else if (key == POLLING_LOGIN_DELAY) { 5630 tunableObj.tunable_objectType = 5631 ISCSI_LOGIN_POLLING_DELAY; 5632 } 5633 tunableObj.tunable_objectValue = valp; 5634 status = SUN_IMA_SetTunableProperties(oid, &tunableObj); 5635 break; 5636 default: 5637 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5638 gettext("Unsupported key"), keyp); 5639 if (nameValueString) { 5640 free(nameValueString); 5641 nameValueString = NULL; 5642 } 5643 return (1); 5644 } 5645 if (!IMA_SUCCESS(status)) { 5646 printLibError(status); 5647 if (nameValueString) { 5648 free(nameValueString); 5649 nameValueString = NULL; 5650 } 5651 return (1); 5652 } 5653 5654 if (nameValueString) { 5655 free(nameValueString); 5656 nameValueString = NULL; 5657 } 5658 return (0); 5659 } 5660 5661 /* 5662 * Print tunable parameters information 5663 */ 5664 static int 5665 printTunableParameters(IMA_OID oid) 5666 { 5667 ISCSI_TUNABLE_PARAM tunableObj; 5668 char value[MAXOPTARGLEN] = "\0"; 5669 IMA_STATUS status; 5670 5671 tunableObj.tunable_objectValue = value; 5672 (void) fprintf(stdout, "\t%s:\n", 5673 gettext("Tunable Parameters (Default/Configured)")); 5674 tunableObj.tunable_objectType = ISCSI_RX_TIMEOUT_VALUE; 5675 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5676 if (!IMA_SUCCESS(status)) { 5677 printLibError(status); 5678 return (1); 5679 } 5680 if (value[0] == '\0') { 5681 value[0] = '-'; 5682 value[1] = '\0'; 5683 } 5684 (void) fprintf(stdout, "\t\t%s: ", 5685 gettext("Session Login Response Time")); 5686 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_RX_TIMEOUT_VALUE, 5687 tunableObj.tunable_objectValue); 5688 5689 value[0] = '\0'; 5690 tunableObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX; 5691 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5692 if (!IMA_SUCCESS(status)) { 5693 printLibError(status); 5694 return (1); 5695 } 5696 if (value[0] == '\0') { 5697 value[0] = '-'; 5698 value[1] = '\0'; 5699 } 5700 (void) fprintf(stdout, "\t\t%s: ", 5701 gettext("Maximum Connection Retry Time")); 5702 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX, 5703 tunableObj.tunable_objectValue); 5704 5705 value[0] = '\0'; 5706 tunableObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY; 5707 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5708 if (!IMA_SUCCESS(status)) { 5709 printLibError(status); 5710 return (1); 5711 } 5712 if (value[0] == '\0') { 5713 value[0] = '-'; 5714 value[1] = '\0'; 5715 } 5716 (void) fprintf(stdout, "\t\t%s: ", 5717 gettext("Login Retry Time Interval")); 5718 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_LOGIN_POLLING_DELAY, 5719 tunableObj.tunable_objectValue); 5720 return (0); 5721 } 5722 5723 /* 5724 * This is helper function to check conn_login_max and polling_login_delay. 5725 */ 5726 static int 5727 chkConnLoginMaxPollingLoginDelay(IMA_OID oid, int key, int uintValue) 5728 { 5729 char valuep[MAXOPTARGLEN]; 5730 IMA_STATUS status; 5731 IMA_UINT getValue; 5732 ISCSI_TUNABLE_PARAM getObj; 5733 char *endptr; 5734 5735 if (key == CONN_LOGIN_MAX) { 5736 getObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY; 5737 } else if (key == POLLING_LOGIN_DELAY) { 5738 getObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX; 5739 } else { 5740 return (0); 5741 } 5742 valuep[0] = '\0'; 5743 getObj.tunable_objectValue = valuep; 5744 status = SUN_IMA_GetTunableProperties(oid, &getObj); 5745 if (!IMA_SUCCESS(status)) { 5746 printLibError(status); 5747 return (1); 5748 } 5749 if (valuep[0] == '\0') { 5750 if (key == CONN_LOGIN_MAX) { 5751 (void) strlcpy(valuep, 5752 ISCSI_DEFAULT_LOGIN_POLLING_DELAY, 5753 strlen(ISCSI_DEFAULT_LOGIN_POLLING_DELAY) +1); 5754 } else { 5755 (void) strlcpy(valuep, 5756 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX, 5757 strlen(ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX) +1); 5758 } 5759 } 5760 5761 errno = 0; 5762 getValue = strtoul(valuep, &endptr, 0); 5763 if (*endptr != '\0' || errno != 0) { 5764 (void) fprintf(stderr, "%s: %s - %s\n", 5765 cmdName, 5766 gettext("cannot convert tunable string"), 5767 valuep); 5768 return (1); 5769 } 5770 if (key == CONN_LOGIN_MAX) { 5771 if (uintValue < getValue) { 5772 (void) fprintf(stderr, "%s: %s %ld\n", 5773 cmdName, gettext("value must larger than"), 5774 getValue); 5775 return (1); 5776 } 5777 } else { 5778 if (uintValue > getValue) { 5779 (void) fprintf(stderr, "%s: %s %ld\n", 5780 cmdName, gettext("value must smaller than"), 5781 getValue); 5782 return (1); 5783 } 5784 } 5785 return (0); 5786 } 5787