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