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