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