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, 0} 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 = '\0'; 656 } 657 } else { 658 *colPos = '\0'; 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 == '\0') { 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 = '\0'; 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 = '\0'; 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 = '\0'; 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 = '\0'; 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 = '\0'; 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 int nameLen = 0; 3111 3112 IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1]; 3113 3114 assert(funcRet != NULL); 3115 3116 /* 3117 * Start with existing parameters and modify with the desired change 3118 * before passing along. We ignore any failures as they probably 3119 * are caused by non-existence of auth params for the given node. 3120 */ 3121 status = IMA_GetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3122 &authParams); 3123 3124 switch (param) { 3125 case AUTH_NAME: 3126 if (chapName == NULL) { 3127 (void) fprintf(stderr, "CHAP name cannot be NULL.\n"); 3128 return (1); 3129 } 3130 nameLen = strlen(chapName); 3131 if (nameLen == 0) { 3132 (void) fprintf(stderr, "CHAP name cannot be empty.\n"); 3133 return (1); 3134 } 3135 if (nameLen > ISCSI_MAX_C_USER_LEN) { 3136 (void) fprintf(stderr, "CHAP name is too long.\n"); 3137 return (1); 3138 } 3139 (void) memset(&authParams.chapParms.name, 0, 3140 sizeof (authParams.chapParms.name)); 3141 (void) memcpy(&authParams.chapParms.name, 3142 &chapName[0], nameLen); 3143 authParams.chapParms.nameLength = nameLen; 3144 break; 3145 3146 case AUTH_PASSWORD : 3147 ret = getSecret((char *)&chapSecret[0], &secretLen, 3148 MIN_CHAP_SECRET_LEN, MAX_CHAP_SECRET_LEN); 3149 3150 if (ret != 0) { 3151 return (ret); 3152 } 3153 3154 (void) memset(&authParams.chapParms.challengeSecret, 0, 3155 sizeof (authParams.chapParms.challengeSecret)); 3156 (void) memcpy(&authParams.chapParms.challengeSecret, 3157 &chapSecret[0], secretLen); 3158 authParams.chapParms.challengeSecretLength = secretLen; 3159 break; 3160 3161 default: 3162 (void) fprintf(stderr, "Invalid auth parameter %d\n", param); 3163 return (1); 3164 } 3165 3166 status = IMA_SetInitiatorAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3167 &authParams); 3168 if (!IMA_SUCCESS(status)) { 3169 printLibError(status); 3170 *funcRet = 1; 3171 } 3172 return (ret); 3173 } 3174 3175 /* 3176 * Set the target's authentication method 3177 */ 3178 static int 3179 modifyTargetAuthParam(IMA_OID oid, int param, char *chapName, int *funcRet) 3180 { 3181 IMA_INITIATOR_AUTHPARMS authParams; 3182 IMA_STATUS status; 3183 int ret; 3184 int secretLen = MAX_CHAP_SECRET_LEN; 3185 int nameLen = 0; 3186 3187 IMA_BYTE chapSecret[MAX_CHAP_SECRET_LEN + 1]; 3188 3189 assert(funcRet != NULL); 3190 3191 /* 3192 * Start with existing parameters and modify with the desired change 3193 * before passing along. We ignore any get failures as they probably 3194 * are caused by non-existence of auth params for the given target. 3195 */ 3196 status = SUN_IMA_GetTargetAuthParms(oid, IMA_AUTHMETHOD_CHAP, 3197 &authParams); 3198 3199 switch (param) { 3200 case AUTH_NAME: 3201 if (chapName == NULL) { 3202 (void) fprintf(stderr, "CHAP name cannot be NULL.\n"); 3203 return (1); 3204 } 3205 nameLen = strlen(chapName); 3206 if (nameLen == 0) { 3207 (void) fprintf(stderr, "CHAP name cannot be empty.\n"); 3208 return (1); 3209 } 3210 if (nameLen > ISCSI_MAX_C_USER_LEN) { 3211 (void) fprintf(stderr, "CHAP name is too long.\n"); 3212 return (1); 3213 } 3214 (void) memset(&authParams.chapParms.name, 0, 3215 sizeof (authParams.chapParms.name)); 3216 (void) memcpy(&authParams.chapParms.name, 3217 &chapName[0], nameLen); 3218 authParams.chapParms.nameLength = nameLen; 3219 break; 3220 3221 case AUTH_PASSWORD : 3222 ret = getSecret((char *)&chapSecret[0], &secretLen, 3223 1, MAX_CHAP_SECRET_LEN); 3224 3225 if (ret != 0) { 3226 return (ret); 3227 } 3228 3229 (void) memset(&authParams.chapParms.challengeSecret, 0, 3230 sizeof (authParams.chapParms.challengeSecret)); 3231 (void) memcpy(&authParams.chapParms.challengeSecret, 3232 &chapSecret[0], secretLen); 3233 authParams.chapParms.challengeSecretLength = secretLen; 3234 break; 3235 3236 default: 3237 (void) fprintf(stderr, "Invalid auth parameter %d\n", param); 3238 return (1); 3239 } 3240 3241 status = SUN_IMA_SetTargetAuthParams(oid, IMA_AUTHMETHOD_CHAP, 3242 &authParams); 3243 if (!IMA_SUCCESS(status)) { 3244 printLibError(status); 3245 *funcRet = 1; 3246 } 3247 return (0); 3248 } 3249 3250 static int 3251 modifyTargetBidirAuthFlag(IMA_OID targetOid, char *optarg, int *funcRet) 3252 { 3253 IMA_BOOL boolValue; 3254 IMA_STATUS status; 3255 3256 assert(funcRet != NULL); 3257 3258 if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) { 3259 boolValue = IMA_TRUE; 3260 } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) { 3261 boolValue = IMA_FALSE; 3262 } else { 3263 (void) fprintf(stderr, "%s: %s %s\n", 3264 cmdName, gettext("invalid option argument"), optarg); 3265 return (1); 3266 } 3267 3268 status = SUN_IMA_SetTargetBidirAuthFlag(targetOid, &boolValue); 3269 if (!IMA_SUCCESS(status)) { 3270 printLibError(status); 3271 *funcRet = 1; 3272 } 3273 return (0); 3274 } 3275 3276 static int 3277 modifyConfiguredSessions(IMA_OID targetOid, char *optarg) 3278 { 3279 SUN_IMA_CONFIG_SESSIONS *pConfigSessions; 3280 IMA_STATUS status; 3281 int sessions; 3282 int size; 3283 char tmp[1024]; 3284 boolean_t isIpv6 = B_FALSE; 3285 uint16_t port; 3286 char address[MAX_ADDRESS_LEN]; 3287 char *commaPos; 3288 char *addressPos; 3289 int rtn; 3290 3291 /* 3292 * Strip the first int value from the string. If we sprintf 3293 * this back to a string and it matches the original string 3294 * then this command is using default binding. If not a 3295 * match we have hard coded binding or a usage error. 3296 */ 3297 sessions = atoi(optarg); 3298 (void) sprintf(tmp, "%d", sessions); 3299 if (strcmp(optarg, tmp) == 0) { 3300 /* default binding */ 3301 3302 /* allocate the required pConfigSessions */ 3303 size = sizeof (SUN_IMA_CONFIG_SESSIONS); 3304 pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 3305 if (pConfigSessions == NULL) { 3306 return (1); 3307 } 3308 3309 /* setup pConfigSessions */ 3310 pConfigSessions->bound = IMA_FALSE; 3311 pConfigSessions->in = sessions; 3312 pConfigSessions->out = 0; 3313 } else { 3314 /* hardcoded binding */ 3315 3316 /* 3317 * First we need to determine how many bindings 3318 * are available. This can be done by scanning 3319 * for the number of ',' + 1. 3320 */ 3321 sessions = 1; 3322 commaPos = strchr(optarg, ','); 3323 while (commaPos != NULL) { 3324 sessions++; 3325 commaPos = strchr(++commaPos, ','); 3326 } 3327 3328 /* allocate the required pConfigSessions */ 3329 size = sizeof (SUN_IMA_CONFIG_SESSIONS) + ((sessions - 1) * 3330 sizeof (IMA_ADDRESS_KEY)); 3331 pConfigSessions = (SUN_IMA_CONFIG_SESSIONS *)calloc(1, size); 3332 if (pConfigSessions == NULL) { 3333 return (1); 3334 } 3335 3336 /* setup pConfigSessions */ 3337 pConfigSessions->bound = IMA_TRUE; 3338 pConfigSessions->in = sessions; 3339 pConfigSessions->out = 0; 3340 3341 /* Now fill in the binding information. */ 3342 sessions = 0; 3343 addressPos = optarg; 3344 /* 3345 * Walk thru possible address strings 3346 * stop once all strings are processed. 3347 */ 3348 while (addressPos != NULL) { 3349 /* 3350 * Check if there is another address after this 3351 * one. If so terminate the current address and 3352 * keep a pointer to the next one. 3353 */ 3354 commaPos = strchr(addressPos, ','); 3355 if (commaPos != NULL) { 3356 *commaPos++ = 0x00; 3357 } 3358 3359 /* 3360 * Parse current address. If invalid abort 3361 * processing of addresses and free memory. 3362 */ 3363 if (parseAddress(addressPos, 0, address, 3364 MAX_ADDRESS_LEN, &port, &isIpv6) != PARSE_ADDR_OK) { 3365 free(pConfigSessions); 3366 printLibError(IMA_ERROR_INVALID_PARAMETER); 3367 return (1); 3368 } 3369 3370 /* Convert address into binary form */ 3371 if (isIpv6 == B_FALSE) { 3372 pConfigSessions->bindings[sessions]. 3373 ipAddress.ipv4Address = IMA_TRUE; 3374 rtn = inet_pton(AF_INET, address, 3375 pConfigSessions->bindings[sessions]. 3376 ipAddress.ipAddress); 3377 } else { 3378 pConfigSessions->bindings[sessions].ipAddress. 3379 ipv4Address = 3380 IMA_FALSE; 3381 rtn = inet_pton(AF_INET6, address, 3382 pConfigSessions->bindings[sessions]. 3383 ipAddress.ipAddress); 3384 } 3385 if (rtn == 0) { 3386 /* inet_pton found address invalid */ 3387 free(pConfigSessions); 3388 printLibError(IMA_ERROR_INVALID_PARAMETER); 3389 return (1); 3390 } 3391 3392 /* update addressPos to next address */ 3393 sessions++; 3394 addressPos = commaPos; 3395 } 3396 } 3397 3398 /* issue SUN_IMA request */ 3399 status = SUN_IMA_SetConfigSessions(targetOid, 3400 pConfigSessions); 3401 if (!IMA_SUCCESS(status)) { 3402 printLibError(status); 3403 free(pConfigSessions); 3404 return (1); 3405 } 3406 3407 free(pConfigSessions); 3408 return (0); 3409 } 3410 3411 static int 3412 getAuthMethodValue(char *method, IMA_AUTHMETHOD *value) 3413 { 3414 if (strcasecmp(method, "chap") == 0) { 3415 *value = IMA_AUTHMETHOD_CHAP; 3416 return (0); 3417 } 3418 3419 if (strcasecmp(method, "none") == 0) { 3420 *value = IMA_AUTHMETHOD_NONE; 3421 return (0); 3422 } 3423 3424 return (1); 3425 } 3426 3427 3428 /* 3429 * Set the authentication method 3430 * Currently only supports CHAP and NONE 3431 */ 3432 static int 3433 modifyNodeAuthMethod(IMA_OID oid, char *optarg, int *funcRet) 3434 { 3435 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 3436 IMA_UINT methodCount = 0; 3437 IMA_STATUS status; 3438 IMA_AUTHMETHOD value; 3439 char *method; 3440 char *commaPos; 3441 3442 assert(funcRet != NULL); 3443 3444 /* 3445 * optarg will be a , delimited set of auth methods, in order 3446 * of preference 3447 * if any values here are incorrect, return without setting 3448 * anything. 3449 */ 3450 method = optarg; 3451 3452 commaPos = strchr(optarg, ','); 3453 3454 while (commaPos && methodCount < MAX_AUTH_METHODS) { 3455 *commaPos = '\0'; 3456 if (getAuthMethodValue(method, &value) != 0) { 3457 (void) fprintf(stderr, "%s: a: %s\n", 3458 cmdName, gettext("invalid option argument")); 3459 return (1); 3460 } 3461 methodList[methodCount++] = value; 3462 commaPos++; 3463 method = commaPos; 3464 commaPos = strchr(method, ','); 3465 } 3466 /* Should not find more method specified - if found, error */ 3467 if (commaPos) { 3468 (void) fprintf(stderr, "%s: -a: %s\n", 3469 cmdName, gettext("invalid option argument")); 3470 return (1); 3471 } 3472 if (getAuthMethodValue(method, &value) != 0) { 3473 (void) fprintf(stderr, "%s: -a: %s\n", 3474 cmdName, gettext("invalid option argument")); 3475 return (1); 3476 } 3477 methodList[methodCount++] = value; 3478 3479 status = IMA_SetInitiatorAuthMethods(oid, methodCount, &methodList[0]); 3480 if (!IMA_SUCCESS(status)) { 3481 printLibError(status); 3482 *funcRet = 1; 3483 } 3484 return (0); 3485 } 3486 3487 static int 3488 modifyTargetAuthMethod(IMA_OID oid, char *optarg, int *funcRet) 3489 { 3490 IMA_AUTHMETHOD methodList[MAX_AUTH_METHODS]; 3491 IMA_UINT methodCount = 0; 3492 IMA_STATUS status; 3493 IMA_AUTHMETHOD value; 3494 char *method; 3495 char *commaPos; 3496 3497 assert(funcRet != NULL); 3498 3499 /* 3500 * optarg will be a , delimited set of auth methods, in order 3501 * of preference 3502 * if any values here are incorrect, return without setting 3503 * anything. 3504 */ 3505 method = optarg; 3506 3507 commaPos = strchr(optarg, ','); 3508 3509 while (commaPos && methodCount < MAX_AUTH_METHODS) { 3510 *commaPos = '\0'; 3511 if (getAuthMethodValue(method, &value) != 0) { 3512 (void) fprintf(stderr, "%s: a: %s\n", 3513 cmdName, gettext("invalid option argument")); 3514 return (1); 3515 } 3516 methodList[methodCount++] = value; 3517 commaPos++; 3518 method = commaPos; 3519 commaPos = strchr(method, ','); 3520 } 3521 /* Should not find more method specified - if found, error */ 3522 if (commaPos) { 3523 (void) fprintf(stderr, "%s: -a: %s\n", 3524 cmdName, gettext("invalid option argument")); 3525 return (1); 3526 } 3527 if (getAuthMethodValue(method, &value) != 0) { 3528 (void) fprintf(stderr, "%s: -a: %s\n", 3529 cmdName, gettext("invalid option argument")); 3530 return (1); 3531 } 3532 methodList[methodCount++] = value; 3533 3534 status = SUN_IMA_SetTargetAuthMethods(oid, &methodCount, 3535 &methodList[0]); 3536 if (!IMA_SUCCESS(status)) { 3537 printLibError(status); 3538 *funcRet = 1; 3539 } 3540 return (0); 3541 } 3542 3543 /* 3544 * Modify the RADIUS configuration of the initiator node. 3545 * 3546 * Return 0 on success. 3547 */ 3548 static int 3549 modifyNodeRadiusConfig(IMA_OID oid, char *optarg, int *funcRet) 3550 { 3551 SUN_IMA_RADIUS_CONFIG config; 3552 IMA_STATUS status; 3553 boolean_t isIpv6 = B_FALSE; 3554 uint16_t port; 3555 3556 assert(funcRet != NULL); 3557 3558 (void) memset(&config, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3559 if (parseAddress(optarg, DEFAULT_RADIUS_PORT, 3560 &config.hostnameIpAddress[0], SUN_IMA_IP_ADDRESS_PORT_LEN, 3561 &port, &isIpv6) != 3562 PARSE_ADDR_OK) { 3563 return (1); 3564 } 3565 config.port = (IMA_UINT16)port; 3566 config.isIpv6 = (isIpv6 == B_TRUE) ? IMA_TRUE : IMA_FALSE; 3567 /* Not setting shared secret here. */ 3568 config.sharedSecretValid = IMA_FALSE; 3569 3570 status = SUN_IMA_SetInitiatorRadiusConfig(oid, &config); 3571 if (!IMA_SUCCESS(status)) { 3572 printLibError(status); 3573 *funcRet = 1; 3574 } 3575 3576 return (0); 3577 } 3578 3579 /* 3580 * Modify the RADIUS access flag of the initiator node. 3581 * 3582 * Return 0 on success. 3583 */ 3584 static int 3585 modifyNodeRadiusAccess(IMA_OID oid, char *optarg, int *funcRet) 3586 { 3587 IMA_BOOL radiusAccess; 3588 IMA_OID initiatorOid; 3589 IMA_STATUS status; 3590 SUN_IMA_RADIUS_CONFIG radiusConfig; 3591 int ret; 3592 3593 assert(funcRet != NULL); 3594 3595 /* Check if Radius Config is there */ 3596 ret = sunInitiatorFind(&initiatorOid); 3597 if (ret != 0) { 3598 (void) fprintf(stderr, "%s: %s\n", 3599 cmdName, gettext("no initiator found")); 3600 return (1); 3601 } 3602 (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3603 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 3604 if (!IMA_SUCCESS(status)) { 3605 (void) fprintf(stderr, "%s: %s\n", 3606 cmdName, gettext("RADIUS server not configured yet")); 3607 *funcRet = 1; 3608 return (ret); 3609 } 3610 3611 /* Check if Radius Shared is set */ 3612 if (radiusConfig.sharedSecretValid == IMA_FALSE) { 3613 (void) fprintf(stderr, "%s: %s\n", cmdName, 3614 gettext("RADIUS server secret not configured yet")); 3615 return (1); 3616 } 3617 3618 if (strcasecmp(optarg, ISCSIADM_ARG_ENABLE) == 0) { 3619 radiusAccess = IMA_TRUE; 3620 } else if (strcasecmp(optarg, ISCSIADM_ARG_DISABLE) == 0) { 3621 radiusAccess = IMA_FALSE; 3622 } else { 3623 (void) fprintf(stderr, "%s: %s %s\n", 3624 cmdName, 3625 gettext("invalid option argument"), 3626 optarg); 3627 return (1); 3628 } 3629 status = SUN_IMA_SetInitiatorRadiusAccess(oid, radiusAccess); 3630 if (!IMA_SUCCESS(status)) { 3631 printLibError(status); 3632 *funcRet = 1; 3633 } 3634 3635 return (ret); 3636 } 3637 3638 /* 3639 * Modify the RADIUS shared secret. 3640 * 3641 * Returns: 3642 * zero on success. 3643 * > 0 on failure. 3644 */ 3645 static int 3646 modifyNodeRadiusSharedSecret(IMA_OID oid, int *funcRet) 3647 { 3648 IMA_BYTE radiusSharedSecret[SUN_IMA_MAX_RADIUS_SECRET_LEN + 1]; 3649 IMA_OID initiatorOid; 3650 IMA_STATUS status; 3651 SUN_IMA_RADIUS_CONFIG radiusConfig; 3652 int ret; 3653 int secretLen = SUN_IMA_MAX_RADIUS_SECRET_LEN; 3654 3655 assert(funcRet != NULL); 3656 3657 ret = getSecret((char *)&radiusSharedSecret[0], &secretLen, 3658 0, SUN_IMA_MAX_RADIUS_SECRET_LEN); 3659 if (ret != 0) { 3660 return (1); 3661 } 3662 3663 ret = sunInitiatorFind(&initiatorOid); 3664 if (ret > 0) { 3665 (void) fprintf(stderr, "%s: %s\n", 3666 cmdName, gettext("no initiator found")); 3667 } 3668 if (ret != 0) { 3669 return (1); 3670 } 3671 /* First obtain existing RADIUS configuration (if any) */ 3672 (void) memset(&radiusConfig, 0, sizeof (SUN_IMA_RADIUS_CONFIG)); 3673 status = SUN_IMA_GetInitiatorRadiusConfig(initiatorOid, &radiusConfig); 3674 if (!IMA_SUCCESS(status)) { 3675 (void) fprintf(stderr, "%s: %s\n", 3676 cmdName, gettext("RADIUS server not configured yet")); 3677 return (1); 3678 } 3679 3680 /* Modify the shared secret only */ 3681 radiusConfig.sharedSecretLength = secretLen; 3682 (void) memcpy(&radiusConfig.sharedSecret, 3683 &radiusSharedSecret[0], secretLen); 3684 radiusConfig.sharedSecretValid = IMA_TRUE; 3685 status = SUN_IMA_SetInitiatorRadiusConfig(oid, &radiusConfig); 3686 if (!IMA_SUCCESS(status)) { 3687 printLibError(status); 3688 *funcRet = 1; 3689 } 3690 3691 return (0); 3692 } 3693 3694 /* 3695 * Set initiator node attributes. 3696 */ 3697 static int 3698 modifyNode(cmdOptions_t *options, int *funcRet) 3699 { 3700 IMA_NODE_NAME nodeName; 3701 IMA_NODE_ALIAS nodeAlias; 3702 IMA_OID oid; 3703 IMA_STATUS status; 3704 cmdOptions_t *optionList = options; 3705 int ret; 3706 iSCSINameCheckStatusType nameCheckStatus; 3707 IMA_OID sharedNodeOid; 3708 int i; 3709 int lowerCase; 3710 IMA_BOOL iscsiBoot = IMA_FALSE; 3711 IMA_BOOL mpxioEnabled = IMA_FALSE; 3712 char *mb_name = NULL; 3713 int prefixlen = 0; 3714 3715 assert(funcRet != NULL); 3716 3717 /* Get boot session's info */ 3718 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 3719 if (iscsiBoot == IMA_TRUE) { 3720 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 3721 if (!IMA_SUCCESS(status)) { 3722 (void) fprintf(stderr, "%s: %s\n", 3723 cmdName, gettext("unable to get MPxIO info" 3724 " of root disk")); 3725 *funcRet = 1; 3726 return (1); 3727 } 3728 } 3729 3730 /* Find Sun initiator */ 3731 ret = sunInitiatorFind(&oid); 3732 if (ret != 0) { 3733 (void) fprintf(stderr, "%s: %s\n", 3734 cmdName, gettext("no initiator found")); 3735 return (ret); 3736 } 3737 3738 for (; optionList->optval; optionList++) { 3739 switch (optionList->optval) { 3740 case 'N': 3741 if (strlen(optionList->optarg) >= 3742 MAX_ISCSI_NAME_LEN) { 3743 (void) fprintf(stderr, "%s: %s %d\n", 3744 cmdName, 3745 gettext("name too long, \ 3746 maximum length is:"), 3747 MAX_ISCSI_NAME_LEN); 3748 } 3749 3750 /* Take the first operand as node name. */ 3751 (void) memset(&nodeName, 0, 3752 sizeof (IMA_NODE_NAME)); 3753 if (mbstowcs(nodeName, optionList->optarg, 3754 IMA_NODE_NAME_LEN) == (size_t)-1) { 3755 (void) fprintf(stderr, "%s: %s\n", 3756 cmdName, 3757 gettext("conversion error")); 3758 return (1); 3759 } 3760 3761 prefixlen = strlen(ISCSI_IQN_NAME_PREFIX); 3762 mb_name = (char *)calloc(1, prefixlen + 1); 3763 if (mb_name == NULL) { 3764 return (1); 3765 } 3766 3767 if (wcstombs(mb_name, nodeName, 3768 prefixlen) == (size_t)-1) { 3769 (void) fprintf(stderr, "%s: %s\n", 3770 cmdName, 3771 gettext("conversion error")); 3772 (void) IMA_FreeMemory(mb_name); 3773 return (1); 3774 } 3775 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 3776 prefixlen) == 0) { 3777 /* 3778 * For iqn format, we should map 3779 * the upper-case characters to 3780 * their lower-case equivalents. 3781 */ 3782 for (i = 0; nodeName[i] != 0; i++) { 3783 lowerCase = 3784 tolower(nodeName[i]); 3785 nodeName[i] = lowerCase; 3786 } 3787 } 3788 (void) IMA_FreeMemory(mb_name); 3789 3790 /* Perform string profile checks */ 3791 nameCheckStatus = 3792 iSCSINameStringProfileCheck(nodeName); 3793 iSCSINameCheckStatusDisplay(nameCheckStatus); 3794 if (nameCheckStatus != iSCSINameCheckOK) { 3795 *funcRet = 1; /* DIY message fix */ 3796 return (1); 3797 } 3798 3799 /* 3800 * IMA_GetSharedNodeOid(&sharedNodeOid); 3801 * if (!IMA_SUCCESS(status)) { 3802 * printLibError(status); 3803 * return (INF_ERROR); 3804 * } 3805 */ 3806 if (iscsiBoot == IMA_TRUE) { 3807 (void) fprintf(stderr, "%s: %s\n", 3808 cmdName, gettext("iscsi boot, not" 3809 " allowed to change" 3810 " initiator's name")); 3811 return (1); 3812 } 3813 oid.objectType = IMA_OBJECT_TYPE_NODE; 3814 status = IMA_SetNodeName(oid, nodeName); 3815 if (!IMA_SUCCESS(status)) { 3816 printLibError(status); 3817 *funcRet = 1; 3818 return (ret); 3819 } 3820 break; 3821 3822 case 'A': 3823 if (iscsiBoot == IMA_TRUE) { 3824 (void) fprintf(stderr, "%s: %s\n", 3825 cmdName, gettext("iscsi boot, not" 3826 " allowed to change" 3827 " initiator's alias")); 3828 return (1); 3829 } 3830 /* Take the first operand as node alias. */ 3831 if (strlen(optionList->optarg) >= 3832 MAX_ISCSI_NAME_LEN) { 3833 (void) fprintf(stderr, "%s: %s %d\n", 3834 cmdName, 3835 gettext("alias too long, maximum \ 3836 length is:"), 3837 MAX_ISCSI_NAME_LEN); 3838 } 3839 3840 (void) memset(&nodeAlias, 0, 3841 sizeof (IMA_NODE_ALIAS)); 3842 if (mbstowcs(nodeAlias, optionList->optarg, 3843 IMA_NODE_ALIAS_LEN) == (size_t)-1) { 3844 (void) fprintf(stderr, "%s: %s\n", 3845 cmdName, 3846 gettext("conversion error")); 3847 return (1); 3848 } 3849 3850 status = IMA_GetSharedNodeOid(&sharedNodeOid); 3851 if (!IMA_SUCCESS(status)) { 3852 printLibError(status); 3853 *funcRet = 1; 3854 return (ret); 3855 } 3856 3857 status = IMA_SetNodeAlias(sharedNodeOid, 3858 nodeAlias); 3859 if (!IMA_SUCCESS(status)) { 3860 printLibError(status); 3861 *funcRet = 1; 3862 return (ret); 3863 } 3864 break; 3865 3866 case 'a': 3867 if (iscsiBoot == IMA_TRUE) { 3868 (void) fprintf(stderr, "%s: %s\n", 3869 cmdName, gettext("iscsi boot, not" 3870 " allowed to change authentication" 3871 " method")); 3872 return (1); 3873 } 3874 if (modifyNodeAuthMethod(oid, options->optarg, 3875 funcRet) != 0) { 3876 return (1); 3877 } 3878 break; 3879 3880 case 'R': 3881 if (modifyNodeRadiusAccess(oid, options->optarg, 3882 funcRet) != 0) { 3883 return (1); 3884 } 3885 break; 3886 3887 case 'r': 3888 if (modifyNodeRadiusConfig(oid, options->optarg, 3889 funcRet) != 0) { 3890 return (1); 3891 } 3892 break; 3893 3894 case 'P': 3895 if (modifyNodeRadiusSharedSecret(oid, funcRet) 3896 != 0) { 3897 return (1); 3898 } 3899 break; 3900 3901 case 'C': 3902 if (iscsiBoot == IMA_TRUE) { 3903 (void) fprintf(stderr, "%s: %s\n", 3904 cmdName, gettext("iscsi boot, not" 3905 " allowed to change CHAP secret")); 3906 return (1); 3907 } 3908 if (modifyNodeAuthParam(oid, AUTH_PASSWORD, 3909 NULL, funcRet) != 0) { 3910 return (1); 3911 } 3912 break; 3913 3914 case 'c': 3915 if (iscsiBoot == IMA_TRUE) { 3916 if (mpxioEnabled == IMA_FALSE) { 3917 (void) fprintf(stderr, 3918 "%s: %s\n", cmdName, 3919 gettext("iscsi" 3920 " boot and MPxIO" 3921 " is disabled, not allowed" 3922 " to change number of" 3923 " sessions to be" 3924 " configured")); 3925 return (1); 3926 } 3927 } 3928 if (modifyConfiguredSessions(oid, 3929 optionList->optarg) != 0) { 3930 if (iscsiBoot == IMA_TRUE) { 3931 (void) fprintf(stderr, 3932 "%s: %s\n", cmdName, 3933 gettext("iscsi boot," 3934 " fail to set configured" 3935 " session")); 3936 } 3937 return (1); 3938 } 3939 break; 3940 3941 3942 case 'H': 3943 if (iscsiBoot == IMA_TRUE) { 3944 (void) fprintf(stderr, "%s: %s\n", 3945 cmdName, gettext("iscsi boot, not" 3946 " allowed to change CHAP name")); 3947 return (1); 3948 } 3949 if (modifyNodeAuthParam(oid, AUTH_NAME, 3950 optionList->optarg, funcRet) != 0) { 3951 return (1); 3952 } 3953 break; 3954 3955 3956 case 'd': 3957 if (iscsiBoot == IMA_TRUE) { 3958 if (mpxioEnabled == IMA_FALSE) { 3959 (void) fprintf(stderr, 3960 "%s: %s\n", cmdName, 3961 gettext("iscsi" 3962 " boot and MPxIO" 3963 " is disabled, not" 3964 " allowed to" 3965 " change initiator's" 3966 " login params")); 3967 return (1); 3968 } 3969 } 3970 if (setLoginParameter(oid, DATA_DIGEST, 3971 optionList->optarg) != 0) { 3972 return (1); 3973 } 3974 break; 3975 3976 case 'h': 3977 if (iscsiBoot == IMA_TRUE) { 3978 if (mpxioEnabled == IMA_FALSE) { 3979 (void) fprintf(stderr, 3980 "%s: %s\n", cmdName, 3981 gettext("iscsi" 3982 " boot and MPxIO" 3983 " is disabled, not" 3984 " allowed to" 3985 " change initiator's" 3986 " login params")); 3987 return (1); 3988 } 3989 } 3990 if (setLoginParameter(oid, HEADER_DIGEST, 3991 optionList->optarg) != 0) { 3992 return (1); 3993 } 3994 break; 3995 3996 case 'T': 3997 if (setTunableParameters(oid, 3998 optionList->optarg) != 0) { 3999 return (1); 4000 } 4001 break; 4002 default: 4003 (void) fprintf(stderr, "%s: %c: %s\n", 4004 cmdName, optionList->optval, 4005 gettext("unknown option")); 4006 break; 4007 } 4008 } 4009 4010 return (ret); 4011 } 4012 4013 /* 4014 * Modify target parameters 4015 */ 4016 static int 4017 modifyTargetParam(cmdOptions_t *options, char *targetName, int *funcRet) 4018 { 4019 IMA_OID oid; 4020 IMA_OID targetOid; 4021 IMA_STATUS status; 4022 IMA_OID_LIST *targetList; 4023 SUN_IMA_TARGET_PROPERTIES targetProps; 4024 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 4025 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4026 int ret; 4027 boolean_t found; 4028 boolean_t targetAddressSpecified = B_TRUE; 4029 boolean_t tpgtSpecified = B_FALSE; 4030 boolean_t isIpv6 = B_FALSE; 4031 int i; 4032 iSCSINameCheckStatusType nameCheckStatus; 4033 IMA_UINT16 port = 0; 4034 IMA_UINT16 tpgt = 0; 4035 4036 IMA_NODE_NAME bootTargetName; 4037 IMA_INITIATOR_AUTHPARMS bootTargetCHAP; 4038 IMA_BOOL iscsiBoot; 4039 IMA_BOOL mpxioEnabled; 4040 4041 cmdOptions_t *optionList = options; 4042 4043 assert(funcRet != NULL); 4044 4045 /* Find Sun initiator */ 4046 ret = sunInitiatorFind(&oid); 4047 if (ret > 0) { 4048 (void) fprintf(stderr, "%s: %s\n", 4049 cmdName, gettext("no initiator found")); 4050 } 4051 4052 if (ret != 0) { 4053 return (ret); 4054 } 4055 4056 if (parseTarget(targetName, 4057 &wcInputObject[0], 4058 MAX_ISCSI_NAME_LEN + 1, 4059 &targetAddressSpecified, 4060 &targetAddress[0], 4061 SUN_IMA_IP_ADDRESS_PORT_LEN, 4062 &port, 4063 &tpgtSpecified, 4064 &tpgt, 4065 &isIpv6) != PARSE_TARGET_OK) { 4066 return (1); 4067 } 4068 4069 /* Perform string profile checks */ 4070 nameCheckStatus = iSCSINameStringProfileCheck(wcInputObject); 4071 iSCSINameCheckStatusDisplay(nameCheckStatus); 4072 if (nameCheckStatus != iSCSINameCheckOK) { 4073 return (1); 4074 } 4075 4076 status = IMA_GetTargetOidList(oid, &targetList); 4077 if (!IMA_SUCCESS(status)) { 4078 printLibError(status); 4079 *funcRet = 1; 4080 return (0); 4081 } 4082 4083 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 4084 if (iscsiBoot == IMA_TRUE) { 4085 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 4086 if (!IMA_SUCCESS(status)) { 4087 (void) fprintf(stderr, "%s: %s\n", 4088 cmdName, gettext("unable to get MPxIO info" 4089 " of root disk")); 4090 *funcRet = 1; 4091 return (ret); 4092 } 4093 status = SUN_IMA_GetBootTargetName(bootTargetName); 4094 if (!IMA_SUCCESS(status)) { 4095 (void) fprintf(stderr, "%s: %s\n", 4096 cmdName, gettext("unable to get boot target's" 4097 " name")); 4098 *funcRet = 1; 4099 return (ret); 4100 } 4101 status = SUN_IMA_GetBootTargetAuthParams(&bootTargetCHAP); 4102 if (!IMA_SUCCESS(status)) { 4103 (void) fprintf(stderr, "%s: %s\n", 4104 cmdName, gettext("unable to get boot target's" 4105 " auth param")); 4106 *funcRet = 1; 4107 return (ret); 4108 } 4109 } 4110 4111 /* find target oid */ 4112 for (found = B_FALSE, i = 0; i < targetList->oidCount; i++) { 4113 status = SUN_IMA_GetTargetProperties(targetList->oids[i], 4114 &targetProps); 4115 if (!IMA_SUCCESS(status)) { 4116 printLibError(status); 4117 (void) IMA_FreeMemory(targetList); 4118 *funcRet = 1; 4119 return (ret); 4120 } 4121 4122 /* 4123 * Compare the target name with the input name 4124 */ 4125 if ((targetNamesEqual(wcInputObject, targetProps.imaProps.name) 4126 == B_TRUE)) { 4127 /* 4128 * For now, regardless of whether a target address 4129 * is specified, we return B_TRUE because 4130 * IMA_TARGET_PROPERTIES does not have a field for 4131 * specifying address. 4132 */ 4133 found = B_TRUE; 4134 targetOid = targetList->oids[i]; 4135 4136 if ((targetNamesEqual(bootTargetName, wcInputObject) 4137 == B_TRUE) && (iscsiBoot == IMA_TRUE)) { 4138 /* 4139 * iscsi booting, need changed target param is 4140 * booting target, for auth param, not allow 4141 * to change, for others dependent on mpxio 4142 */ 4143 4144 if ((optionList->optval == 'C') || 4145 (optionList->optval == 'H') || 4146 (optionList->optval == 'B') || 4147 (optionList->optval == 'a')) { 4148 /* 4149 * -C CHAP secret set 4150 * -H CHAP name set 4151 * -a authentication 4152 * -B bi-directional-authentication 4153 */ 4154 (void) fprintf(stderr, "%s: %s\n", 4155 cmdName, gettext("iscsi boot," 4156 " not allowed to modify" 4157 " authentication parameters" 4158 " of boot target")); 4159 return (1); 4160 } 4161 if (mpxioEnabled == IMA_FALSE) { 4162 (void) fprintf(stderr, "%s: %s\n", 4163 cmdName, gettext("iscsi boot and" 4164 " MPxIO is disabled, not allowed" 4165 " to modify boot target's" 4166 " parameters")); 4167 return (1); 4168 } 4169 4170 } 4171 4172 if (modifyIndividualTargetParam(optionList, targetOid, 4173 funcRet) != 0) { 4174 return (ret); 4175 } 4176 4177 /* 4178 * Even after finding a matched target, keep going 4179 * since there could be multiple target objects 4180 * associated with one target name in the system 4181 * because of different TPGTs. 4182 */ 4183 } 4184 } 4185 4186 /* If the target OID cannot be found create one */ 4187 if (!found) { 4188 status = SUN_IMA_CreateTargetOid(wcInputObject, &targetOid); 4189 if (!IMA_SUCCESS(status)) { 4190 printLibError(status); 4191 (void) IMA_FreeMemory(targetList); 4192 *funcRet = 1; 4193 return (ret); 4194 } 4195 if (modifyIndividualTargetParam(optionList, targetOid, 4196 funcRet) != 0) { 4197 return (ret); 4198 } 4199 } 4200 4201 (void) IMA_FreeMemory(targetList); 4202 return (ret); 4203 } 4204 4205 /* 4206 * Add one or more addresses 4207 */ 4208 static int 4209 addAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4210 { 4211 IMA_STATUS status; 4212 IMA_OID oid, addressOid; 4213 SUN_IMA_TARGET_ADDRESS address; 4214 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4215 int ret; 4216 int i; 4217 4218 assert(funcRet != NULL); 4219 4220 /* Find Sun initiator */ 4221 ret = sunInitiatorFind(&oid); 4222 if (ret > 0) { 4223 (void) fprintf(stderr, "%s: %s\n", 4224 cmdName, gettext("no initiator found")); 4225 } 4226 4227 if (ret != 0) { 4228 return (ret); 4229 } 4230 4231 /* 4232 * Format of discovery address operand: 4233 * 4234 * <IP address|hostname>:<port> 4235 */ 4236 for (i = 0; i < operandLen; i++) { 4237 /* initialize */ 4238 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4239 (void) memset(&address, 0, sizeof (address)); 4240 4241 if (mbstowcs(wcInputObject, operand[i], 4242 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 4243 (void) fprintf(stderr, "%s: %s\n", 4244 cmdName, gettext("conversion error")); 4245 ret = 1; 4246 continue; 4247 } 4248 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4249 != 0) { 4250 ret = 1; 4251 continue; 4252 } 4253 if (addrType == DISCOVERY_ADDRESS) { 4254 status = IMA_AddDiscoveryAddress(oid, 4255 address.imaStruct, &addressOid); 4256 if (!IMA_SUCCESS(status)) { 4257 printLibError(status); 4258 *funcRet = 1; 4259 return (ret); 4260 } 4261 } else if (addrType == ISNS_SERVER_ADDRESS) { 4262 status = SUN_IMA_AddISNSServerAddress(address); 4263 if (!IMA_SUCCESS(status)) { 4264 printLibError(status); 4265 *funcRet = 1; 4266 return (ret); 4267 } 4268 } 4269 } 4270 return (ret); 4271 } 4272 4273 /* 4274 * Add one or more static configuration targets 4275 */ 4276 static int 4277 addStaticConfig(int operandLen, char *operand[], int *funcRet) 4278 { 4279 int i; 4280 boolean_t targetAddressSpecified = B_FALSE; 4281 boolean_t tpgtSpecified = B_FALSE; 4282 boolean_t isIpv6 = B_FALSE; 4283 int ret; 4284 int addrType; 4285 IMA_STATUS status; 4286 IMA_OID oid; 4287 SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig; 4288 IMA_UINT16 port = 0; 4289 IMA_UINT16 tpgt = 0; 4290 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4291 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4292 iSCSINameCheckStatusType nameCheckStatus; 4293 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4294 4295 assert(funcRet != NULL); 4296 4297 /* Find Sun initiator */ 4298 ret = sunInitiatorFind(&oid); 4299 if (ret > 0) { 4300 (void) fprintf(stderr, "%s: %s\n", 4301 cmdName, gettext("no initiator found")); 4302 } 4303 4304 if (ret != 0) { 4305 return (ret); 4306 } 4307 4308 /* 4309 * Format of static config operand: 4310 * <target-name>,<IP address|hostname>[:port][,tpgt] 4311 */ 4312 for (i = 0; i < operandLen; i++) { 4313 if (parseTarget(operand[i], 4314 &staticTargetName[0], 4315 MAX_ISCSI_NAME_LEN + 1, 4316 &targetAddressSpecified, 4317 &staticTargetAddress[0], 4318 SUN_IMA_IP_ADDRESS_PORT_LEN, 4319 &port, 4320 &tpgtSpecified, 4321 &tpgt, 4322 &isIpv6) != PARSE_TARGET_OK) { 4323 ret = 1; 4324 continue; 4325 } 4326 4327 if (targetAddressSpecified != B_TRUE) { 4328 (void) fprintf(stderr, "%s: %s\n", 4329 cmdName, gettext("missing target address")); 4330 *funcRet = 1; /* DIY message fix */ 4331 return (1); 4332 } 4333 /* Perform string profile checks */ 4334 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4335 iSCSINameCheckStatusDisplay(nameCheckStatus); 4336 if (nameCheckStatus != iSCSINameCheckOK) { 4337 *funcRet = 1; /* DIY message fix */ 4338 return (1); 4339 } 4340 (void) wcsncpy(staticConfig.targetName, staticTargetName, 4341 MAX_ISCSI_NAME_LEN + 1); 4342 4343 (void) wcstombs(sAddr, staticTargetAddress, sizeof (sAddr)); 4344 4345 if (isIpv6 == B_TRUE) { 4346 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4347 id.ipAddress.ipv4Address = B_FALSE; 4348 addrType = AF_INET6; 4349 } else { 4350 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4351 id.ipAddress.ipv4Address = B_TRUE; 4352 addrType = AF_INET; 4353 } 4354 4355 if (inet_pton(addrType, sAddr, staticConfig.targetAddress. 4356 imaStruct.hostnameIpAddress.id.ipAddress.ipAddress) != 1) { 4357 (void) fprintf(stderr, "%s: %s\n", 4358 cmdName, gettext("static config conversion error")); 4359 ret = 1; 4360 continue; 4361 } 4362 4363 staticConfig.targetAddress.imaStruct.portNumber = port; 4364 if (tpgtSpecified == B_TRUE) { 4365 staticConfig.targetAddress.defaultTpgt = B_FALSE; 4366 staticConfig.targetAddress.tpgt = tpgt; 4367 } else { 4368 staticConfig.targetAddress.defaultTpgt = B_TRUE; 4369 staticConfig.targetAddress.tpgt = 0; 4370 } 4371 4372 status = SUN_IMA_AddStaticTarget(oid, staticConfig, &oid); 4373 if (!IMA_SUCCESS(status)) { 4374 printLibError(status); 4375 *funcRet = 1; 4376 return (1); 4377 } 4378 } 4379 4380 if (ret != 0) { 4381 *funcRet = 1; 4382 } 4383 4384 return (ret); 4385 } 4386 4387 /* 4388 * Remove one or more addresses 4389 */ 4390 static int 4391 removeAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4392 { 4393 IMA_STATUS status; 4394 IMA_OID initiatorOid; 4395 SUN_IMA_TARGET_ADDRESS address; 4396 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4397 int ret; 4398 int i; 4399 4400 assert(funcRet != NULL); 4401 4402 /* Find Sun initiator */ 4403 ret = sunInitiatorFind(&initiatorOid); 4404 if (ret > 0) { 4405 (void) fprintf(stderr, "%s: %s\n", 4406 cmdName, gettext("no initiator found")); 4407 } 4408 4409 if (ret != 0) { 4410 return (ret); 4411 } 4412 4413 for (i = 0; i < operandLen; i++) { 4414 /* initialize */ 4415 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4416 (void) memset(&address, 0, sizeof (address)); 4417 4418 if (mbstowcs(wcInputObject, operand[i], 4419 MAX_ADDRESS_LEN + 1) == (size_t)-1) { 4420 (void) fprintf(stderr, "%s: %s\n", 4421 cmdName, gettext("conversion error")); 4422 ret = 1; 4423 continue; 4424 } 4425 4426 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4427 != 0) { 4428 ret = 1; 4429 continue; 4430 } 4431 4432 if (addrType == DISCOVERY_ADDRESS) { 4433 status = SUN_IMA_RemoveDiscoveryAddress(address); 4434 if (!IMA_SUCCESS(status)) { 4435 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4436 (void) fprintf(stderr, "%s: %s\n", 4437 operand[i], gettext("not found")); 4438 } else { 4439 printLibError(status); 4440 } 4441 *funcRet = 1; 4442 } 4443 } else { 4444 status = SUN_IMA_RemoveISNSServerAddress(address); 4445 if (!IMA_SUCCESS(status)) { 4446 printLibError(status); 4447 *funcRet = 1; 4448 } 4449 } 4450 } 4451 return (ret); 4452 } 4453 4454 /* 4455 * Remove one or more static configuration targets 4456 */ 4457 static int 4458 removeStaticConfig(int operandLen, char *operand[], int *funcRet) 4459 { 4460 IMA_STATUS status; 4461 IMA_OID initiatorOid; 4462 IMA_OID_LIST *staticTargetList; 4463 SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps; 4464 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4465 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4466 int ret; 4467 boolean_t atLeastFoundOne; 4468 boolean_t matched; 4469 boolean_t targetAddressSpecified = B_TRUE; 4470 boolean_t tpgtSpecified = B_FALSE; 4471 boolean_t isIpv6 = B_FALSE; 4472 int i, j; 4473 IMA_UINT16 port = 0; 4474 IMA_UINT16 tpgt = 0; 4475 iSCSINameCheckStatusType nameCheckStatus; 4476 char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4477 wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4478 4479 assert(funcRet != NULL); 4480 4481 /* Find Sun initiator */ 4482 ret = sunInitiatorFind(&initiatorOid); 4483 if (ret > 0) { 4484 (void) fprintf(stderr, "%s: %s\n", 4485 cmdName, gettext("no initiator found")); 4486 } 4487 4488 if (ret != 0) { 4489 return (ret); 4490 } 4491 4492 status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid, 4493 &staticTargetList); 4494 if (!IMA_SUCCESS(status)) { 4495 printLibError(status); 4496 *funcRet = 1; 4497 return (ret); 4498 } 4499 4500 for (i = 0; i < operandLen; i++) { 4501 if (parseTarget(operand[i], 4502 &staticTargetName[0], 4503 MAX_ISCSI_NAME_LEN + 1, 4504 &targetAddressSpecified, 4505 &staticTargetAddress[0], 4506 SUN_IMA_IP_ADDRESS_PORT_LEN, 4507 &port, 4508 &tpgtSpecified, 4509 &tpgt, 4510 &isIpv6) != PARSE_TARGET_OK) { 4511 ret = 1; 4512 continue; 4513 } 4514 4515 /* Perform string profile checks */ 4516 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4517 iSCSINameCheckStatusDisplay(nameCheckStatus); 4518 if (nameCheckStatus != iSCSINameCheckOK) { 4519 return (1); 4520 } 4521 4522 for (atLeastFoundOne = B_FALSE, j = 0; 4523 j < staticTargetList->oidCount; 4524 j++) { 4525 IMA_UINT16 stpgt; 4526 4527 matched = B_FALSE; 4528 status = SUN_IMA_GetStaticTargetProperties( 4529 staticTargetList->oids[j], &staticTargetProps); 4530 if (!IMA_SUCCESS(status)) { 4531 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4532 /* 4533 * When removing multiple static-config 4534 * entries we need to expect get 4535 * failures. These failures occur when 4536 * we are trying to get entry 4537 * information we have just removed. 4538 * Ignore the failure and continue. 4539 */ 4540 ret = 1; 4541 continue; 4542 } else { 4543 printLibError(status); 4544 (void) IMA_FreeMemory(staticTargetList); 4545 *funcRet = 1; 4546 return (ret); 4547 } 4548 } 4549 4550 stpgt = 4551 staticTargetProps.staticTarget.targetAddress.tpgt; 4552 4553 /* 4554 * Compare the static target name with the input if 4555 * one was input 4556 */ 4557 if ((targetNamesEqual( 4558 staticTargetProps.staticTarget.targetName, 4559 staticTargetName) == B_TRUE)) { 4560 if (targetAddressSpecified == B_FALSE) { 4561 matched = B_TRUE; 4562 } else { 4563 4564 if (staticTargetProps.staticTarget. 4565 targetAddress.imaStruct. 4566 hostnameIpAddress. 4567 id.ipAddress.ipv4Address == 4568 IMA_TRUE) { 4569 (void) inet_ntop(AF_INET, 4570 staticTargetProps. 4571 staticTarget.targetAddress. 4572 imaStruct.hostnameIpAddress. 4573 id.ipAddress.ipAddress, 4574 tmpStr, 4575 sizeof (tmpStr)); 4576 } else { 4577 (void) inet_ntop(AF_INET6, 4578 staticTargetProps. 4579 staticTarget.targetAddress. 4580 imaStruct.hostnameIpAddress. 4581 id.ipAddress.ipAddress, 4582 tmpStr, 4583 sizeof (tmpStr)); 4584 } 4585 4586 if (mbstowcs(tmpTargetAddress, tmpStr, 4587 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4588 (size_t)-1) { 4589 (void) fprintf(stderr, 4590 "%s: %s\n", 4591 cmdName, gettext( 4592 "conversion error")); 4593 ret = 1; 4594 continue; 4595 } 4596 4597 if ((wcsncmp(tmpTargetAddress, 4598 staticTargetAddress, 4599 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4600 0) && (staticTargetProps. 4601 staticTarget.targetAddress. 4602 imaStruct.portNumber == port)) { 4603 if (tpgtSpecified == B_FALSE) { 4604 matched = B_TRUE; 4605 } else { 4606 if (tpgt == stpgt) { 4607 matched = 4608 B_TRUE; 4609 } 4610 } 4611 } 4612 } 4613 4614 if (matched) { 4615 status = 4616 IMA_RemoveStaticDiscoveryTarget( 4617 staticTargetList->oids[j]); 4618 if (!IMA_SUCCESS(status)) { 4619 printLibError(status); 4620 *funcRet = 1; 4621 return (ret); 4622 } 4623 atLeastFoundOne = B_TRUE; 4624 } 4625 } 4626 } 4627 if (!atLeastFoundOne) { 4628 (void) fprintf(stderr, gettext("%ws,%ws: %s\n"), 4629 staticTargetName, staticTargetAddress, 4630 gettext("not found")); 4631 } 4632 } 4633 return (ret); 4634 } 4635 4636 /* 4637 * Remove one or more target params. 4638 */ 4639 static int 4640 removeTargetParam(int operandLen, char *operand[], int *funcRet) 4641 { 4642 char *commaPos; 4643 IMA_STATUS status; 4644 IMA_OID initiatorOid; 4645 IMA_OID_LIST *targetList; 4646 SUN_IMA_TARGET_PROPERTIES targetProps; 4647 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 4648 int ret; 4649 boolean_t found; 4650 int i, j; 4651 IMA_NODE_NAME bootTargetName; 4652 IMA_BOOL iscsiBoot = IMA_FALSE; 4653 IMA_BOOL mpxioEnabled = IMA_FALSE; 4654 4655 /* Get boot session's info */ 4656 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 4657 if (iscsiBoot == IMA_TRUE) { 4658 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 4659 if (!IMA_SUCCESS(status)) { 4660 (void) fprintf(stderr, "%s: %s\n", 4661 cmdName, gettext("unable to get MPxIO info of" 4662 " root disk")); 4663 *funcRet = 1; 4664 return (1); 4665 } 4666 status = SUN_IMA_GetBootTargetName(bootTargetName); 4667 if (!IMA_SUCCESS(status)) { 4668 (void) fprintf(stderr, "%s: %s\n", 4669 cmdName, gettext("unable to get boot" 4670 " target's name")); 4671 *funcRet = 1; 4672 return (1); 4673 } 4674 } 4675 4676 assert(funcRet != NULL); 4677 4678 /* Find Sun initiator */ 4679 ret = sunInitiatorFind(&initiatorOid); 4680 if (ret > 0) { 4681 (void) fprintf(stderr, "%s: %s\n", 4682 cmdName, gettext("no initiator found")); 4683 } 4684 4685 if (ret != 0) { 4686 return (ret); 4687 } 4688 4689 status = IMA_GetTargetOidList(initiatorOid, &targetList); 4690 if (!IMA_SUCCESS(status)) { 4691 printLibError(status); 4692 *funcRet = 1; 4693 return (ret); 4694 } 4695 4696 for (i = 0; i < operandLen; i++) { 4697 /* initialize */ 4698 commaPos = strchr(operand[i], ','); 4699 if (commaPos) { 4700 /* Ignore IP address. */ 4701 *commaPos = '\0'; 4702 } 4703 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4704 if (mbstowcs(wcInputObject, operand[i], 4705 MAX_ISCSI_NAME_LEN + 1) == (size_t)-1) { 4706 (void) fprintf(stderr, "%s: %s\n", cmdName, 4707 gettext("conversion error")); 4708 ret = 1; 4709 continue; 4710 } 4711 4712 for (found = B_FALSE, j = 0; j < targetList->oidCount; 4713 j++) { 4714 status = SUN_IMA_GetTargetProperties( 4715 targetList->oids[j], &targetProps); 4716 if (!IMA_SUCCESS(status)) { 4717 printLibError(status); 4718 (void) IMA_FreeMemory(targetList); 4719 *funcRet = 1; 4720 return (ret); 4721 } 4722 4723 /* 4724 * Compare the target name with the input if 4725 * one was input 4726 */ 4727 if (targetNamesEqual(targetProps.imaProps.name, 4728 wcInputObject) == B_TRUE) { 4729 found = B_TRUE; 4730 if ((targetNamesEqual(bootTargetName, 4731 wcInputObject) == B_TRUE) && 4732 (iscsiBoot == IMA_TRUE)) { 4733 /* 4734 * iscsi booting, need changed target 4735 * param is booting target, booting 4736 * session mpxio disabled, not 4737 * allow to update 4738 */ 4739 if (mpxioEnabled == IMA_FALSE) { 4740 (void) fprintf(stderr, 4741 "%s: %s\n", cmdName, 4742 gettext("iscsi boot" 4743 " with MPxIO disabled," 4744 " not allowed to remove" 4745 " boot sess param")); 4746 ret = 1; 4747 continue; 4748 } 4749 4750 } 4751 4752 status = SUN_IMA_RemoveTargetParam( 4753 targetList->oids[j]); 4754 if (!IMA_SUCCESS(status)) { 4755 printLibError(status); 4756 (void) IMA_FreeMemory(targetList); 4757 *funcRet = 1; 4758 return (ret); 4759 } 4760 } 4761 } 4762 if (!found) { 4763 /* Silently ignoring it? */ 4764 (void) fprintf(stderr, gettext("%ws: %s\n"), 4765 wcInputObject, gettext("not found")); 4766 } 4767 } 4768 4769 (void) IMA_FreeMemory(targetList); 4770 return (ret); 4771 } 4772 4773 /*ARGSUSED*/ 4774 static int 4775 addFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4776 void *addArgs, int *funcRet) 4777 { 4778 int ret; 4779 4780 assert(funcRet != NULL); 4781 4782 switch (object) { 4783 case DISCOVERY_ADDRESS: 4784 case ISNS_SERVER_ADDRESS: 4785 ret = addAddress(object, operandLen, operand, funcRet); 4786 break; 4787 case STATIC_CONFIG: 4788 ret = addStaticConfig(operandLen, operand, funcRet); 4789 break; 4790 default: 4791 (void) fprintf(stderr, "%s: %s\n", 4792 cmdName, gettext("unknown object")); 4793 ret = 1; 4794 break; 4795 } 4796 return (ret); 4797 } 4798 4799 /*ARGSUSED*/ 4800 static int 4801 listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4802 void *addArgs, int *funcRet) 4803 { 4804 int ret; 4805 4806 assert(funcRet != NULL); 4807 4808 switch (object) { 4809 case DISCOVERY: 4810 ret = listDiscovery(funcRet); 4811 break; 4812 case DISCOVERY_ADDRESS: 4813 ret = listDiscoveryAddress(operandLen, operand, options, 4814 funcRet); 4815 break; 4816 case ISNS_SERVER_ADDRESS: 4817 ret = listISNSServerAddress(operandLen, operand, options, 4818 funcRet); 4819 break; 4820 case NODE: 4821 ret = listNode(funcRet); 4822 break; 4823 case STATIC_CONFIG: 4824 ret = listStaticConfig(operandLen, operand, funcRet); 4825 break; 4826 case TARGET: 4827 ret = listTarget(operandLen, operand, options, funcRet); 4828 break; 4829 case TARGET_PARAM: 4830 ret = listTargetParam(operandLen, operand, options, funcRet); 4831 break; 4832 default: 4833 (void) fprintf(stderr, "%s: %s\n", 4834 cmdName, gettext("unknown object")); 4835 ret = 1; 4836 break; 4837 } 4838 return (ret); 4839 } 4840 4841 /*ARGSUSED*/ 4842 static int 4843 modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4844 void *addArgs, int *funcRet) 4845 { 4846 int ret, i; 4847 4848 assert(funcRet != NULL); 4849 4850 switch (object) { 4851 case DISCOVERY: 4852 ret = modifyDiscovery(options, funcRet); 4853 break; 4854 case NODE: 4855 ret = modifyNode(options, funcRet); 4856 break; 4857 case TARGET_PARAM: 4858 i = 0; 4859 while (operand[i]) { 4860 ret = modifyTargetParam(options, operand[i], funcRet); 4861 4862 if (ret) { 4863 (void) fprintf(stderr, "%s: %s: %s\n", 4864 cmdName, gettext("modify failed"), 4865 operand[i]); 4866 return (ret); 4867 } 4868 i++; 4869 } 4870 4871 break; 4872 default: 4873 (void) fprintf(stderr, "%s: %s\n", 4874 cmdName, gettext("unknown object")); 4875 ret = 1; 4876 break; 4877 } 4878 return (ret); 4879 } 4880 4881 /*ARGSUSED*/ 4882 static int 4883 removeFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4884 void *addArgs, int *funcRet) 4885 { 4886 int ret; 4887 4888 switch (object) { 4889 case DISCOVERY_ADDRESS: 4890 case ISNS_SERVER_ADDRESS: 4891 ret = removeAddress(object, operandLen, operand, 4892 funcRet); 4893 break; 4894 case STATIC_CONFIG: 4895 ret = removeStaticConfig(operandLen, operand, funcRet); 4896 break; 4897 case TARGET_PARAM: 4898 ret = removeTargetParam(operandLen, operand, funcRet); 4899 break; 4900 default: 4901 (void) fprintf(stderr, "%s: %s\n", 4902 cmdName, gettext("unknown object")); 4903 ret = 1; 4904 break; 4905 } 4906 return (ret); 4907 } 4908 4909 static void 4910 iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status) 4911 { 4912 switch (status) { 4913 case iSCSINameLenZero: 4914 (void) fprintf(stderr, "%s: %s\n", 4915 cmdName, gettext("empty iSCSI name.")); 4916 break; 4917 case iSCSINameLenExceededMax: 4918 (void) fprintf(stderr, "%s: %s\n", cmdName, 4919 gettext("iSCSI name exceeded maximum length.")); 4920 break; 4921 case iSCSINameUnknownType: 4922 (void) fprintf(stderr, "%s: %s\n", cmdName, 4923 gettext("unknown iSCSI name type.")); 4924 break; 4925 case iSCSINameInvalidCharacter: 4926 (void) fprintf(stderr, "%s: %s\n", 4927 cmdName, 4928 gettext("iSCSI name invalid character used")); 4929 break; 4930 case iSCSINameIqnFormatError: 4931 (void) fprintf(stderr, "%s: %s\n", cmdName, 4932 gettext("iqn formatting error.")); 4933 break; 4934 case iSCSINameIqnDateFormatError: 4935 (void) fprintf(stderr, "%s: %s\n", 4936 cmdName, gettext("invalid iqn date." \ 4937 " format is: YYYY-MM")); 4938 break; 4939 case iSCSINameIqnSubdomainFormatError: 4940 (void) fprintf(stderr, "%s: %s\n", 4941 cmdName, gettext("missing subdomain after \":\"")); 4942 break; 4943 case iSCSINameIqnInvalidYearError: 4944 (void) fprintf(stderr, "%s: %s\n", 4945 cmdName, gettext("invalid year")); 4946 break; 4947 case iSCSINameIqnInvalidMonthError: 4948 (void) fprintf(stderr, "%s: %s\n", 4949 cmdName, gettext("invalid month")); 4950 break; 4951 case iSCSINameIqnFQDNError: 4952 (void) fprintf(stderr, "%s: %s\n", 4953 cmdName, gettext("missing reversed fully qualified"\ 4954 " domain name")); 4955 break; 4956 case iSCSINameEUIFormatError: 4957 (void) fprintf(stderr, "%s: %s\n", cmdName, 4958 gettext("eui formatting error.")); 4959 break; 4960 } 4961 } 4962 4963 /* 4964 * A convenient function to modify the target parameters of an individual 4965 * target. 4966 * 4967 * Return 0 if successful 4968 * Return 1 if failed 4969 */ 4970 static int 4971 modifyIndividualTargetParam(cmdOptions_t *optionList, IMA_OID targetOid, 4972 int *funcRet) 4973 { 4974 assert(funcRet != NULL); 4975 4976 for (; optionList->optval; optionList++) { 4977 switch (optionList->optval) { 4978 case 'a': 4979 if (modifyTargetAuthMethod(targetOid, 4980 optionList->optarg, funcRet) != 0) { 4981 return (1); 4982 } 4983 break; 4984 case 'B': 4985 if (modifyTargetBidirAuthFlag(targetOid, 4986 optionList->optarg, funcRet) != 0) { 4987 return (1); 4988 } 4989 break; 4990 case 'C': 4991 if (modifyTargetAuthParam(targetOid, 4992 AUTH_PASSWORD, NULL, funcRet) != 0) { 4993 return (1); 4994 } 4995 break; 4996 case 'd': 4997 if (setLoginParameter(targetOid, DATA_DIGEST, 4998 optionList->optarg) != 0) { 4999 return (1); 5000 } 5001 break; 5002 case 'h': 5003 if (setLoginParameter(targetOid, HEADER_DIGEST, 5004 optionList->optarg) != 0) { 5005 return (1); 5006 } 5007 break; 5008 case 'p': 5009 /* Login parameter */ 5010 if (setLoginParameters(targetOid, 5011 optionList->optarg) != 0) { 5012 return (1); 5013 } 5014 break; 5015 case 'c': 5016 /* Modify configure sessions */ 5017 if (modifyConfiguredSessions(targetOid, 5018 optionList->optarg) != 0) { 5019 return (1); 5020 } 5021 break; 5022 case 'H': 5023 if (modifyTargetAuthParam(targetOid, AUTH_NAME, 5024 optionList->optarg, funcRet) != 0) { 5025 return (1); 5026 } 5027 break; 5028 case 'T': 5029 if (setTunableParameters(targetOid, 5030 optionList->optarg) != 0) { 5031 return (1); 5032 } 5033 break; 5034 } 5035 } 5036 5037 return (0); 5038 } 5039 5040 /* 5041 * This helper function could go into a utility module for general use. 5042 */ 5043 static int 5044 parseAddress(char *address_port_str, 5045 uint16_t defaultPort, 5046 char *address_str, 5047 size_t address_str_len, 5048 uint16_t *port, 5049 boolean_t *isIpv6) 5050 { 5051 char port_str[64]; 5052 int tmp_port; 5053 char *errchr; 5054 5055 if (address_port_str[0] == '[') { 5056 /* IPv6 address */ 5057 char *close_bracket_pos; 5058 close_bracket_pos = strchr(address_port_str, ']'); 5059 if (!close_bracket_pos) { 5060 syslog(LOG_USER|LOG_DEBUG, 5061 "IP address format error: %s\n", address_str); 5062 return (PARSE_ADDR_MISSING_CLOSING_BRACKET); 5063 } 5064 5065 *close_bracket_pos = '\0'; 5066 (void) strlcpy(address_str, &address_port_str[1], 5067 address_str_len); 5068 5069 /* Extract the port number */ 5070 close_bracket_pos++; 5071 if (*close_bracket_pos == ':') { 5072 close_bracket_pos++; 5073 if (*close_bracket_pos != '\0') { 5074 (void) strlcpy(port_str, close_bracket_pos, 64); 5075 tmp_port = strtol(port_str, &errchr, 10); 5076 if (tmp_port == 0 && errchr != NULL) { 5077 (void) fprintf(stderr, "%s: %s:%s %s\n", 5078 cmdName, address_str, 5079 close_bracket_pos, 5080 gettext("port number invalid")); 5081 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5082 } 5083 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 5084 (tmp_port < 0)) { 5085 /* Port number out of range */ 5086 syslog(LOG_USER|LOG_DEBUG, 5087 "Specified port out of range: %d", 5088 tmp_port); 5089 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5090 } else { 5091 *port = (uint16_t)tmp_port; 5092 } 5093 } else { 5094 *port = defaultPort; 5095 } 5096 } else { 5097 *port = defaultPort; 5098 } 5099 5100 *isIpv6 = B_TRUE; 5101 } else { 5102 /* IPv4 address */ 5103 char *colon_pos; 5104 colon_pos = strchr(address_port_str, ':'); 5105 if (!colon_pos) { 5106 /* No port number specified. */ 5107 *port = defaultPort; 5108 (void) strlcpy(address_str, address_port_str, 5109 address_str_len); 5110 } else { 5111 *colon_pos = '\0'; 5112 (void) strlcpy(address_str, address_port_str, 5113 address_str_len); 5114 5115 /* Extract the port number */ 5116 colon_pos++; 5117 if (*colon_pos != '\0') { 5118 5119 (void) strlcpy(port_str, colon_pos, 64); 5120 tmp_port = strtol(port_str, &errchr, 10); 5121 if (tmp_port == 0 && errchr != NULL) { 5122 (void) fprintf(stderr, "%s: %s:%s %s\n", 5123 cmdName, address_str, colon_pos, 5124 gettext("port number invalid")); 5125 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5126 } 5127 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 5128 (tmp_port < 0)) { 5129 /* Port number out of range */ 5130 syslog(LOG_USER|LOG_DEBUG, 5131 "Specified port out of range: %d", 5132 tmp_port); 5133 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 5134 } else { 5135 *port = (uint16_t)tmp_port; 5136 } 5137 } else { 5138 *port = defaultPort; 5139 } 5140 } 5141 5142 *isIpv6 = B_FALSE; 5143 } 5144 5145 return (PARSE_ADDR_OK); 5146 } 5147 5148 /* 5149 * This helper function could go into a utility module for general use. 5150 */ 5151 iSCSINameCheckStatusType 5152 iSCSINameStringProfileCheck(wchar_t *name) 5153 { 5154 char mb_name[MAX_ISCSI_NAME_LEN + 1]; 5155 size_t name_len; 5156 char *tmp; 5157 5158 (void) wcstombs(mb_name, name, MAX_ISCSI_NAME_LEN + 1); 5159 5160 if ((name_len = strlen(mb_name)) == 0) { 5161 return (iSCSINameLenZero); 5162 } else if (name_len > MAX_ISCSI_NAME_LEN) { 5163 return (iSCSINameLenExceededMax); 5164 } 5165 5166 /* 5167 * check for invalid characters 5168 * According to RFC 3722 iSCSI name must be either a letter, 5169 * a digit or one of the following '-' '.' ':' 5170 */ 5171 for (tmp = mb_name; *tmp != '\0'; tmp++) { 5172 if ((isalnum(*tmp) == 0) && 5173 (*tmp != '-') && 5174 (*tmp != '.') && 5175 (*tmp != ':')) { 5176 return (iSCSINameInvalidCharacter); 5177 } 5178 } 5179 5180 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 5181 strlen(ISCSI_IQN_NAME_PREFIX)) == 0) { 5182 /* 5183 * If name is of type iqn, check date string and naming 5184 * authority. 5185 */ 5186 char *strp = NULL; 5187 5188 /* 5189 * Don't allow the string to end with a colon. If there is a 5190 * colon then there must be a subdomain provided. 5191 */ 5192 if (mb_name[strlen(mb_name) - 1] == ':') { 5193 return (iSCSINameIqnSubdomainFormatError); 5194 } 5195 5196 /* Date string */ 5197 strp = strtok(&mb_name[3], "."); 5198 if (strp) { 5199 char tmpYear[5], tmpMonth[3], *endPtr = NULL; 5200 int year, month; 5201 5202 /* Date string should be in YYYY-MM format */ 5203 if (strlen(strp) != strlen("YYYY-MM") || 5204 strp[4] != '-') { 5205 return (iSCSINameIqnDateFormatError); 5206 } 5207 5208 /* 5209 * Validate year. Only validating that the 5210 * year can be converted to a number. No 5211 * validation will be done on year's actual 5212 * value. 5213 */ 5214 (void) strncpy(tmpYear, strp, 4); 5215 tmpYear[4] = '\0'; 5216 5217 errno = 0; 5218 year = strtol(tmpYear, &endPtr, 10); 5219 if (errno != 0 || *endPtr != '\0' || 5220 year < 0 || year > 9999) { 5221 return (iSCSINameIqnInvalidYearError); 5222 } 5223 5224 /* 5225 * Validate month is valid. 5226 */ 5227 (void) strncpy(tmpMonth, &strp[5], 2); 5228 tmpMonth[2] = '\0'; 5229 errno = 0; 5230 month = strtol(tmpMonth, &endPtr, 10); 5231 5232 if (errno != 0 || *endPtr != '\0' || 5233 month < 1 || month > 12) { 5234 return (iSCSINameIqnInvalidMonthError); 5235 } 5236 5237 /* 5238 * A reversed FQDN needs to be provided. We 5239 * will only check for a "." followed by more 5240 * than two or more characters. The list of domains is 5241 * too large and changes too frequently to 5242 * add validation for. 5243 */ 5244 strp = strtok(NULL, "."); 5245 if (!strp || strlen(strp) < 2) { 5246 return (iSCSINameIqnFQDNError); 5247 } 5248 5249 /* Name authority string */ 5250 strp = strtok(NULL, ":"); 5251 if (strp) { 5252 return (iSCSINameCheckOK); 5253 } else { 5254 return (iSCSINameIqnFQDNError); 5255 } 5256 } else { 5257 return (iSCSINameIqnFormatError); 5258 } 5259 } else if (strncmp(mb_name, ISCSI_EUI_NAME_PREFIX, 5260 strlen(ISCSI_EUI_NAME_PREFIX)) == 0) { 5261 /* If name is of type EUI, change its length */ 5262 5263 if (strlen(mb_name) != ISCSI_EUI_NAME_LEN) { 5264 return (iSCSINameEUIFormatError); 5265 } 5266 5267 for (tmp = mb_name + strlen(ISCSI_EUI_NAME_PREFIX) + 1; 5268 *tmp != '\0'; tmp++) { 5269 if (isxdigit(*tmp)) { 5270 continue; 5271 } 5272 return (iSCSINameEUIFormatError); 5273 } 5274 5275 return (iSCSINameCheckOK); 5276 } else { 5277 return (iSCSINameUnknownType); 5278 } 5279 } 5280 5281 /* 5282 * This helper function could go into a utility module for general use. 5283 * 5284 * Returns: 5285 * B_TRUE is the numberStr is an unsigned natural number and within the 5286 * specified bound. 5287 * B_FALSE otherwise. 5288 */ 5289 boolean_t 5290 isNaturalNumber(char *numberStr, uint32_t upperBound) 5291 { 5292 int i; 5293 int number_str_len; 5294 5295 if ((number_str_len = strlen(numberStr)) == 0) { 5296 return (B_FALSE); 5297 } 5298 5299 for (i = 0; i < number_str_len; i++) { 5300 if (numberStr[i] < 060 || numberStr[i] > 071) { 5301 return (B_FALSE); 5302 } 5303 } 5304 5305 if (atoi(numberStr) > upperBound) { 5306 return (B_FALSE); 5307 } 5308 5309 return (B_TRUE); 5310 } 5311 5312 /* 5313 * This helper function could go into a utility module for general use. 5314 * It parses a target string in the format of: 5315 * 5316 * <target_name>,[<ip_address>[:port][,tpgt]] 5317 * 5318 * and creates wchar strings for target name and target address. It 5319 * also populates port and tpgt if found. 5320 * 5321 * Returns: 5322 * PARSE_TARGET_OK if parsing is successful. 5323 * PARSE_TARGET_INVALID_TPGT if the specified tpgt is 5324 * invalid. 5325 * PARSE_TARGET_INVALID_ADDR if the address specified is 5326 * invalid. 5327 */ 5328 int 5329 parseTarget(char *targetStr, wchar_t *targetNameStr, size_t targetNameStrLen, 5330 boolean_t *targetAddressSpecified, wchar_t *targetAddressStr, 5331 size_t targetAddressStrLen, uint16_t *port, boolean_t *tpgtSpecified, 5332 uint16_t *tpgt, boolean_t *isIpv6) 5333 { 5334 char *commaPos; 5335 char *commaPos2; 5336 char targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 5337 int i; 5338 int lowerCase; 5339 5340 (void) memset(targetNameStr, 0, 5341 targetNameStrLen * sizeof (wchar_t)); 5342 (void) memset(targetAddressStr, 0, 5343 targetAddressStrLen * sizeof (wchar_t)); 5344 5345 commaPos = strchr(targetStr, ','); 5346 if (commaPos != NULL) { 5347 *commaPos = '\0'; 5348 commaPos++; 5349 *targetAddressSpecified = B_TRUE; 5350 5351 /* 5352 * Checking of tpgt makes sense only when 5353 * the target address/port are specified. 5354 */ 5355 commaPos2 = strchr(commaPos, ','); 5356 if (commaPos2 != NULL) { 5357 *commaPos2 = '\0'; 5358 commaPos2++; 5359 if (isNaturalNumber(commaPos2, ISCSI_MAX_TPGT_VALUE) == 5360 B_TRUE) { 5361 *tpgt = atoi(commaPos2); 5362 *tpgtSpecified = B_TRUE; 5363 } else { 5364 (void) fprintf(stderr, "%s: %s\n", cmdName, 5365 gettext("parse target invalid TPGT")); 5366 return (PARSE_TARGET_INVALID_TPGT); 5367 } 5368 } 5369 5370 switch (parseAddress(commaPos, ISCSI_LISTEN_PORT, 5371 &targetAddress[0], MAX_ADDRESS_LEN + 1, port, isIpv6)) { 5372 case PARSE_ADDR_PORT_OUT_OF_RANGE: 5373 return (PARSE_TARGET_INVALID_ADDR); 5374 case PARSE_ADDR_OK: 5375 break; 5376 default: 5377 (void) fprintf(stderr, "%s: %s\n", 5378 cmdName, gettext("cannot parse target name")); 5379 return (PARSE_TARGET_INVALID_ADDR); 5380 } 5381 (void) mbstowcs(targetAddressStr, targetAddress, 5382 targetAddressStrLen); 5383 for (i = 0; targetAddressStr[i] != 0; i++) { 5384 lowerCase = tolower(targetAddressStr[i]); 5385 targetAddressStr[i] = lowerCase; 5386 } 5387 } else { 5388 *targetAddressSpecified = B_FALSE; 5389 *tpgtSpecified = B_FALSE; 5390 } 5391 5392 (void) mbstowcs(targetNameStr, targetStr, targetNameStrLen); 5393 for (i = 0; targetNameStr[i] != 0; i++) { 5394 lowerCase = tolower(targetNameStr[i]); 5395 targetNameStr[i] = lowerCase; 5396 } 5397 5398 return (PARSE_TARGET_OK); 5399 } 5400 5401 /*ARGSUSED*/ 5402 static void 5403 listCHAPName(IMA_OID oid) 5404 { 5405 IMA_INITIATOR_AUTHPARMS authParams; 5406 IMA_STATUS status; 5407 IMA_BYTE chapName [MAX_CHAP_NAME_LEN + 1]; 5408 5409 /* Get Chap Name depending upon oid object type */ 5410 if (oid.objectType == IMA_OBJECT_TYPE_LHBA) { 5411 status = IMA_GetInitiatorAuthParms(oid, 5412 IMA_AUTHMETHOD_CHAP, &authParams); 5413 } else { 5414 status = SUN_IMA_GetTargetAuthParms(oid, 5415 IMA_AUTHMETHOD_CHAP, &authParams); 5416 } 5417 5418 (void) fprintf(stdout, "\n\t\t%s: ", gettext("CHAP Name")); 5419 5420 if (IMA_SUCCESS(status)) { 5421 /* 5422 * Default chap name will be the node name. The default will 5423 * be set by the driver. 5424 */ 5425 if (authParams.chapParms.nameLength != 0) { 5426 (void) memset(chapName, 0, sizeof (chapName)); 5427 (void) memcpy(chapName, authParams.chapParms.name, 5428 authParams.chapParms.nameLength); 5429 (void) fprintf(stdout, "%s", chapName); 5430 5431 } else { 5432 (void) fprintf(stdout, "%s", "-"); 5433 } 5434 } else { 5435 (void) fprintf(stdout, "%s", "-"); 5436 } 5437 } 5438 5439 static boolean_t 5440 checkServiceStatus(void) 5441 { 5442 IMA_STATUS status = IMA_ERROR_UNKNOWN_ERROR; 5443 IMA_BOOL enabled = 0; 5444 5445 status = SUN_IMA_GetSvcStatus(&enabled); 5446 5447 if (status != IMA_STATUS_SUCCESS) { 5448 (void) fprintf(stdout, "%s\n%s\n", 5449 gettext("Unable to query the service status of" 5450 " iSCSI initiator."), 5451 gettext("For more information, please refer to" 5452 " iscsi(7D).")); 5453 return (B_FALSE); 5454 } 5455 5456 if (enabled == 0) { 5457 (void) fprintf(stdout, "%s\n%s\n", 5458 gettext("iSCSI Initiator Service is disabled," 5459 " try 'svcadm enable network/iscsi/initiator' to" 5460 " enable the service."), 5461 gettext("For more information, please refer to" 5462 " iscsi(7D).")); 5463 return (B_FALSE); 5464 } 5465 5466 return (B_TRUE); 5467 } 5468 5469 /* 5470 * Prints out see manual page. 5471 * Called out through atexit(3C) so is always last thing displayed. 5472 */ 5473 void 5474 seeMan(void) 5475 { 5476 static int sent = 0; 5477 5478 if (sent) 5479 return; 5480 5481 (void) fprintf(stdout, "%s %s(1M)\n", 5482 gettext("For more information, please see"), cmdName); 5483 5484 sent = 1; 5485 } 5486 5487 5488 /* 5489 * main calls a parser that checks syntax of the input command against 5490 * various rules tables. 5491 * 5492 * The parser provides usage feedback based upon same tables by calling 5493 * two usage functions, usage and subUsage, handling command and subcommand 5494 * usage respectively. 5495 * 5496 * The parser handles all printing of usage syntactical errors 5497 * 5498 * When syntax is successfully validated, the parser calls the associated 5499 * function using the subcommands table functions. 5500 * 5501 * Syntax is as follows: 5502 * command subcommand [options] resource-type [<object>] 5503 * 5504 * The return value from the function is placed in funcRet 5505 */ 5506 int 5507 main(int argc, char *argv[]) 5508 { 5509 synTables_t synTables; 5510 char versionString[VERSION_STRING_MAX_LEN]; 5511 int ret; 5512 int funcRet = 0; 5513 void *subcommandArgs = NULL; 5514 5515 if (geteuid() != 0) { 5516 (void) fprintf(stderr, "%s\n", gettext("permission denied")); 5517 return (1); 5518 } 5519 5520 if (checkServiceStatus() == B_FALSE) { 5521 return (1); 5522 } 5523 5524 /* set global command name */ 5525 cmdName = getExecBasename(argv[0]); 5526 5527 (void) snprintf(versionString, sizeof (versionString), "%s.%s", 5528 VERSION_STRING_MAJOR, VERSION_STRING_MINOR); 5529 synTables.versionString = versionString; 5530 synTables.longOptionTbl = &longOptions[0]; 5531 synTables.subcommandTbl = &subcommands[0]; 5532 synTables.objectTbl = &objects[0]; 5533 synTables.objectRulesTbl = &objectRules[0]; 5534 synTables.optionRulesTbl = &optionRules[0]; 5535 5536 /* call the CLI parser */ 5537 ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); 5538 if (ret == -1) { 5539 perror(cmdName); 5540 ret = 1; 5541 } 5542 5543 if (funcRet != 0) { 5544 (void) fprintf(stderr, "%s: %s\n", 5545 cmdName, gettext("Unable to complete operation")); 5546 ret = 1; 5547 } 5548 return (ret); 5549 } 5550 5551 static int 5552 setTunableParameters(IMA_OID oid, char *optarg) 5553 { 5554 char keyp[MAXOPTARGLEN]; 5555 char valp[MAXOPTARGLEN]; 5556 int key; 5557 IMA_STATUS status; 5558 IMA_UINT uintValue; 5559 ISCSI_TUNABLE_PARAM tunableObj; 5560 char *nameValueString, *endptr; 5561 5562 if ((nameValueString = strdup(optarg)) == NULL) { 5563 if (errno == ENOMEM) { 5564 (void) fprintf(stderr, "%s: %s\n", 5565 cmdName, strerror(errno)); 5566 } else { 5567 (void) fprintf(stderr, "%s: %s\n", cmdName, 5568 gettext("unknown error")); 5569 } 5570 return (1); 5571 } 5572 5573 (void) memset(keyp, 0, sizeof (keyp)); 5574 (void) memset(valp, 0, sizeof (valp)); 5575 if (sscanf(nameValueString, gettext("%[^=]=%s"), keyp, valp) != 2) { 5576 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5577 gettext("Unknown param"), nameValueString); 5578 if (nameValueString) { 5579 free(nameValueString); 5580 nameValueString = NULL; 5581 } 5582 return (1); 5583 } 5584 if ((key = getTunableParam(keyp)) == -1) { 5585 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5586 gettext("Unknown key"), keyp); 5587 if (nameValueString) { 5588 free(nameValueString); 5589 nameValueString = NULL; 5590 } 5591 return (1); 5592 } 5593 switch (key) { 5594 case RECV_LOGIN_RSP_TIMEOUT: 5595 case CONN_LOGIN_MAX: 5596 case POLLING_LOGIN_DELAY: 5597 errno = 0; 5598 uintValue = strtoul(valp, &endptr, 0); 5599 if (*endptr != '\0' || errno != 0) { 5600 (void) fprintf(stderr, "%s: %s - %s\n", 5601 cmdName, 5602 gettext("invalid option argument"), 5603 optarg); 5604 if (nameValueString) { 5605 free(nameValueString); 5606 nameValueString = NULL; 5607 } 5608 return (1); 5609 } 5610 if (uintValue > 3600) { 5611 (void) fprintf(stderr, "%s: %s\n", 5612 cmdName, 5613 gettext("value must be between 0 and 3600")); 5614 if (nameValueString) { 5615 free(nameValueString); 5616 nameValueString = NULL; 5617 } 5618 return (1); 5619 } 5620 5621 if (chkConnLoginMaxPollingLoginDelay(oid, key, uintValue) > 0) { 5622 if (nameValueString) { 5623 free(nameValueString); 5624 nameValueString = NULL; 5625 } 5626 return (1); 5627 } 5628 5629 if (key == RECV_LOGIN_RSP_TIMEOUT) { 5630 tunableObj.tunable_objectType = 5631 ISCSI_RX_TIMEOUT_VALUE; 5632 } else if (key == CONN_LOGIN_MAX) { 5633 tunableObj.tunable_objectType = 5634 ISCSI_CONN_DEFAULT_LOGIN_MAX; 5635 } else if (key == POLLING_LOGIN_DELAY) { 5636 tunableObj.tunable_objectType = 5637 ISCSI_LOGIN_POLLING_DELAY; 5638 } 5639 tunableObj.tunable_objectValue = valp; 5640 status = SUN_IMA_SetTunableProperties(oid, &tunableObj); 5641 break; 5642 default: 5643 (void) fprintf(stderr, "%s: %s: %s\n", cmdName, 5644 gettext("Unsupported key"), keyp); 5645 if (nameValueString) { 5646 free(nameValueString); 5647 nameValueString = NULL; 5648 } 5649 return (1); 5650 } 5651 if (!IMA_SUCCESS(status)) { 5652 printLibError(status); 5653 if (nameValueString) { 5654 free(nameValueString); 5655 nameValueString = NULL; 5656 } 5657 return (1); 5658 } 5659 5660 if (nameValueString) { 5661 free(nameValueString); 5662 nameValueString = NULL; 5663 } 5664 return (0); 5665 } 5666 5667 /* 5668 * Print tunable parameters information 5669 */ 5670 static int 5671 printTunableParameters(IMA_OID oid) 5672 { 5673 ISCSI_TUNABLE_PARAM tunableObj; 5674 char value[MAXOPTARGLEN] = "\0"; 5675 IMA_STATUS status; 5676 5677 tunableObj.tunable_objectValue = value; 5678 (void) fprintf(stdout, "\t%s:\n", 5679 gettext("Tunable Parameters (Default/Configured)")); 5680 tunableObj.tunable_objectType = ISCSI_RX_TIMEOUT_VALUE; 5681 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5682 if (!IMA_SUCCESS(status)) { 5683 printLibError(status); 5684 return (1); 5685 } 5686 if (value[0] == '\0') { 5687 value[0] = '-'; 5688 value[1] = '\0'; 5689 } 5690 (void) fprintf(stdout, "\t\t%s: ", 5691 gettext("Session Login Response Time")); 5692 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_RX_TIMEOUT_VALUE, 5693 tunableObj.tunable_objectValue); 5694 5695 value[0] = '\0'; 5696 tunableObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX; 5697 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5698 if (!IMA_SUCCESS(status)) { 5699 printLibError(status); 5700 return (1); 5701 } 5702 if (value[0] == '\0') { 5703 value[0] = '-'; 5704 value[1] = '\0'; 5705 } 5706 (void) fprintf(stdout, "\t\t%s: ", 5707 gettext("Maximum Connection Retry Time")); 5708 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX, 5709 tunableObj.tunable_objectValue); 5710 5711 value[0] = '\0'; 5712 tunableObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY; 5713 status = SUN_IMA_GetTunableProperties(oid, &tunableObj); 5714 if (!IMA_SUCCESS(status)) { 5715 printLibError(status); 5716 return (1); 5717 } 5718 if (value[0] == '\0') { 5719 value[0] = '-'; 5720 value[1] = '\0'; 5721 } 5722 (void) fprintf(stdout, "\t\t%s: ", 5723 gettext("Login Retry Time Interval")); 5724 (void) fprintf(stdout, "%s/%s\n", ISCSI_DEFAULT_LOGIN_POLLING_DELAY, 5725 tunableObj.tunable_objectValue); 5726 return (0); 5727 } 5728 5729 /* 5730 * This is helper function to check conn_login_max and polling_login_delay. 5731 */ 5732 static int 5733 chkConnLoginMaxPollingLoginDelay(IMA_OID oid, int key, int uintValue) 5734 { 5735 char valuep[MAXOPTARGLEN]; 5736 IMA_STATUS status; 5737 IMA_UINT getValue; 5738 ISCSI_TUNABLE_PARAM getObj; 5739 char *endptr; 5740 5741 if (key == CONN_LOGIN_MAX) { 5742 getObj.tunable_objectType = ISCSI_LOGIN_POLLING_DELAY; 5743 } else if (key == POLLING_LOGIN_DELAY) { 5744 getObj.tunable_objectType = ISCSI_CONN_DEFAULT_LOGIN_MAX; 5745 } else { 5746 return (0); 5747 } 5748 valuep[0] = '\0'; 5749 getObj.tunable_objectValue = valuep; 5750 status = SUN_IMA_GetTunableProperties(oid, &getObj); 5751 if (!IMA_SUCCESS(status)) { 5752 printLibError(status); 5753 return (1); 5754 } 5755 if (valuep[0] == '\0') { 5756 if (key == CONN_LOGIN_MAX) { 5757 (void) strlcpy(valuep, 5758 ISCSI_DEFAULT_LOGIN_POLLING_DELAY, 5759 strlen(ISCSI_DEFAULT_LOGIN_POLLING_DELAY) +1); 5760 } else { 5761 (void) strlcpy(valuep, 5762 ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX, 5763 strlen(ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX) +1); 5764 } 5765 } 5766 5767 errno = 0; 5768 getValue = strtoul(valuep, &endptr, 0); 5769 if (*endptr != '\0' || errno != 0) { 5770 (void) fprintf(stderr, "%s: %s - %s\n", 5771 cmdName, 5772 gettext("cannot convert tunable string"), 5773 valuep); 5774 return (1); 5775 } 5776 if (key == CONN_LOGIN_MAX) { 5777 if (uintValue < getValue) { 5778 (void) fprintf(stderr, "%s: %s %ld\n", 5779 cmdName, gettext("value must larger than"), 5780 getValue); 5781 return (1); 5782 } 5783 } else { 5784 if (uintValue > getValue) { 5785 (void) fprintf(stderr, "%s: %s %ld\n", 5786 cmdName, gettext("value must smaller than"), 5787 getValue); 5788 return (1); 5789 } 5790 } 5791 return (0); 5792 } 5793