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