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 char *mb_name = NULL; 3592 int prefixlen = 0; 3593 3594 assert(funcRet != NULL); 3595 3596 /* Get boot session's info */ 3597 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 3598 if (iscsiBoot == IMA_TRUE) { 3599 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 3600 if (!IMA_SUCCESS(status)) { 3601 (void) fprintf(stderr, "%s: %s\n", 3602 cmdName, gettext("unable to get MPxIO info" 3603 " of root disk")); 3604 *funcRet = 1; 3605 return (1); 3606 } 3607 } 3608 3609 /* Find Sun initiator */ 3610 ret = sunInitiatorFind(&oid); 3611 if (ret > 0) { 3612 (void) fprintf(stderr, "%s: %s\n", 3613 cmdName, gettext("no initiator found")); 3614 } 3615 3616 if (ret != 0) { 3617 return (ret); 3618 } 3619 3620 for (; optionList->optval; optionList++) { 3621 switch (optionList->optval) { 3622 case 'N': 3623 if (strlen(optionList->optarg) >= 3624 MAX_ISCSI_NAME_LEN) { 3625 (void) fprintf(stderr, "%s: %s %d\n", 3626 cmdName, 3627 gettext("name too long, \ 3628 maximum length is:"), 3629 MAX_ISCSI_NAME_LEN); 3630 } 3631 3632 /* Take the first operand as node name. */ 3633 (void) memset(&nodeName, 0, 3634 sizeof (IMA_NODE_NAME)); 3635 if (mbstowcs(nodeName, optionList->optarg, 3636 IMA_NODE_NAME_LEN) == (size_t)-1) { 3637 (void) fprintf(stderr, "%s: %s\n", 3638 cmdName, 3639 gettext("conversion error")); 3640 return (1); 3641 } 3642 3643 prefixlen = strlen(ISCSI_IQN_NAME_PREFIX); 3644 mb_name = (char *)calloc(1, prefixlen + 1); 3645 if (mb_name == NULL) { 3646 return (1); 3647 } 3648 3649 if (wcstombs(mb_name, nodeName, 3650 prefixlen) == (size_t)-1) { 3651 (void) fprintf(stderr, "%s: %s\n", 3652 cmdName, 3653 gettext("conversion error")); 3654 (void) IMA_FreeMemory(mb_name); 3655 return (1); 3656 } 3657 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 3658 prefixlen) == 0) { 3659 /* 3660 * For iqn format, we should map 3661 * the upper-case characters to 3662 * their lower-case equivalents. 3663 */ 3664 for (i = 0; nodeName[i] != 0; i++) { 3665 lowerCase = 3666 tolower(nodeName[i]); 3667 nodeName[i] = lowerCase; 3668 } 3669 } 3670 (void) IMA_FreeMemory(mb_name); 3671 3672 /* Perform string profile checks */ 3673 nameCheckStatus = 3674 iSCSINameStringProfileCheck(nodeName); 3675 iSCSINameCheckStatusDisplay(nameCheckStatus); 3676 if (nameCheckStatus != iSCSINameCheckOK) { 3677 *funcRet = 1; /* DIY message fix */ 3678 return (1); 3679 } 3680 3681 /* 3682 * IMA_GetSharedNodeOid(&sharedNodeOid); 3683 * if (!IMA_SUCCESS(status)) { 3684 * printLibError(status); 3685 * return (INF_ERROR); 3686 * } 3687 */ 3688 if (iscsiBoot == IMA_TRUE) { 3689 (void) fprintf(stderr, "%s: %s\n", 3690 cmdName, gettext("iscsi boot, not" 3691 " allowed to change" 3692 " initiator's name")); 3693 return (1); 3694 } 3695 oid.objectType = IMA_OBJECT_TYPE_NODE; 3696 status = IMA_SetNodeName(oid, nodeName); 3697 if (!IMA_SUCCESS(status)) { 3698 printLibError(status); 3699 *funcRet = 1; 3700 return (ret); 3701 } 3702 break; 3703 3704 case 'A': 3705 if (iscsiBoot == IMA_TRUE) { 3706 (void) fprintf(stderr, "%s: %s\n", 3707 cmdName, gettext("iscsi boot, not" 3708 " allowed to change" 3709 " initiator's alias")); 3710 return (1); 3711 } 3712 /* Take the first operand as node alias. */ 3713 if (strlen(optionList->optarg) >= 3714 MAX_ISCSI_NAME_LEN) { 3715 (void) fprintf(stderr, "%s: %s %d\n", 3716 cmdName, 3717 gettext("alias too long, maximum \ 3718 length is:"), 3719 MAX_ISCSI_NAME_LEN); 3720 } 3721 3722 (void) memset(&nodeAlias, 0, 3723 sizeof (IMA_NODE_ALIAS)); 3724 if (mbstowcs(nodeAlias, optionList->optarg, 3725 IMA_NODE_ALIAS_LEN) == (size_t)-1) { 3726 (void) fprintf(stderr, "%s: %s\n", 3727 cmdName, 3728 gettext("conversion error")); 3729 return (1); 3730 } 3731 3732 status = IMA_GetSharedNodeOid(&sharedNodeOid); 3733 if (!IMA_SUCCESS(status)) { 3734 printLibError(status); 3735 *funcRet = 1; 3736 return (ret); 3737 } 3738 3739 status = IMA_SetNodeAlias(sharedNodeOid, 3740 nodeAlias); 3741 if (!IMA_SUCCESS(status)) { 3742 printLibError(status); 3743 *funcRet = 1; 3744 return (ret); 3745 } 3746 break; 3747 3748 case 'a': 3749 if (iscsiBoot == IMA_TRUE) { 3750 (void) fprintf(stderr, "%s: %s\n", 3751 cmdName, gettext("iscsi boot, not" 3752 " allowed to change authentication" 3753 " method")); 3754 return (1); 3755 } 3756 if (modifyNodeAuthMethod(oid, options->optarg, 3757 funcRet) != 0) { 3758 return (1); 3759 } 3760 break; 3761 3762 case 'R': 3763 if (modifyNodeRadiusAccess(oid, options->optarg, 3764 funcRet) != 0) { 3765 return (1); 3766 } 3767 break; 3768 3769 case 'r': 3770 if (modifyNodeRadiusConfig(oid, options->optarg, 3771 funcRet) != 0) { 3772 return (1); 3773 } 3774 break; 3775 3776 case 'P': 3777 if (modifyNodeRadiusSharedSecret(oid, funcRet) 3778 != 0) { 3779 return (1); 3780 } 3781 break; 3782 3783 case 'C': 3784 if (iscsiBoot == IMA_TRUE) { 3785 (void) fprintf(stderr, "%s: %s\n", 3786 cmdName, gettext("iscsi boot, not" 3787 " allowed to change CHAP secret")); 3788 return (1); 3789 } 3790 if (modifyNodeAuthParam(oid, AUTH_PASSWORD, 3791 NULL, funcRet) != 0) { 3792 return (1); 3793 } 3794 break; 3795 3796 case 'c': 3797 if (iscsiBoot == IMA_TRUE) { 3798 if (mpxioEnabled == IMA_FALSE) { 3799 (void) fprintf(stderr, 3800 "%s: %s\n", cmdName, 3801 gettext("iscsi" 3802 " boot and MPxIO" 3803 " is disabled, not allowed" 3804 " to change number of" 3805 " sessions to be" 3806 " configured")); 3807 return (1); 3808 } 3809 } 3810 if (modifyConfiguredSessions(oid, 3811 optionList->optarg) != 0) { 3812 if (iscsiBoot == IMA_TRUE) { 3813 (void) fprintf(stderr, 3814 "%s: %s\n", cmdName, 3815 gettext("iscsi boot," 3816 " fail to set configured" 3817 " session")); 3818 } 3819 return (1); 3820 } 3821 break; 3822 3823 3824 case 'H': 3825 if (iscsiBoot == IMA_TRUE) { 3826 (void) fprintf(stderr, "%s: %s\n", 3827 cmdName, gettext("iscsi boot, not" 3828 " allowed to change CHAP name")); 3829 return (1); 3830 } 3831 if (modifyNodeAuthParam(oid, AUTH_NAME, 3832 optionList->optarg, funcRet) != 0) { 3833 return (1); 3834 } 3835 break; 3836 3837 3838 case 'd': 3839 if (iscsiBoot == IMA_TRUE) { 3840 if (mpxioEnabled == IMA_FALSE) { 3841 (void) fprintf(stderr, 3842 "%s: %s\n", cmdName, 3843 gettext("iscsi" 3844 " boot and MPxIO" 3845 " is disabled, not" 3846 " allowed to" 3847 " change initiator's" 3848 " login params")); 3849 return (1); 3850 } 3851 } 3852 if (setLoginParameter(oid, DATA_DIGEST, 3853 optionList->optarg) != 0) { 3854 return (1); 3855 } 3856 break; 3857 3858 case 'h': 3859 if (iscsiBoot == IMA_TRUE) { 3860 if (mpxioEnabled == IMA_FALSE) { 3861 (void) fprintf(stderr, 3862 "%s: %s\n", cmdName, 3863 gettext("iscsi" 3864 " boot and MPxIO" 3865 " is disabled, not" 3866 " allowed to" 3867 " change initiator's" 3868 " login params")); 3869 return (1); 3870 } 3871 } 3872 if (setLoginParameter(oid, HEADER_DIGEST, 3873 optionList->optarg) != 0) { 3874 return (1); 3875 } 3876 break; 3877 3878 default: 3879 (void) fprintf(stderr, "%s: %c: %s\n", 3880 cmdName, optionList->optval, 3881 gettext("unknown option")); 3882 break; 3883 } 3884 } 3885 3886 return (ret); 3887 } 3888 3889 /* 3890 * Modify target parameters 3891 */ 3892 static int 3893 modifyTargetParam(cmdOptions_t *options, char *targetName, int *funcRet) 3894 { 3895 IMA_OID oid; 3896 IMA_OID targetOid; 3897 IMA_STATUS status; 3898 IMA_OID_LIST *targetList; 3899 SUN_IMA_TARGET_PROPERTIES targetProps; 3900 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 3901 wchar_t targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 3902 int ret; 3903 boolean_t found; 3904 boolean_t targetAddressSpecified = B_TRUE; 3905 boolean_t tpgtSpecified = B_FALSE; 3906 boolean_t isIpv6 = B_FALSE; 3907 int i; 3908 iSCSINameCheckStatusType nameCheckStatus; 3909 IMA_UINT16 port = 0; 3910 IMA_UINT16 tpgt = 0; 3911 3912 IMA_NODE_NAME bootTargetName; 3913 IMA_INITIATOR_AUTHPARMS bootTargetCHAP; 3914 IMA_BOOL iscsiBoot; 3915 IMA_BOOL mpxioEnabled; 3916 3917 cmdOptions_t *optionList = options; 3918 3919 assert(funcRet != NULL); 3920 3921 /* Find Sun initiator */ 3922 ret = sunInitiatorFind(&oid); 3923 if (ret > 0) { 3924 (void) fprintf(stderr, "%s: %s\n", 3925 cmdName, gettext("no initiator found")); 3926 } 3927 3928 if (ret != 0) { 3929 return (ret); 3930 } 3931 3932 if (parseTarget(targetName, 3933 &wcInputObject[0], 3934 MAX_ISCSI_NAME_LEN + 1, 3935 &targetAddressSpecified, 3936 &targetAddress[0], 3937 SUN_IMA_IP_ADDRESS_PORT_LEN, 3938 &port, 3939 &tpgtSpecified, 3940 &tpgt, 3941 &isIpv6) != PARSE_TARGET_OK) { 3942 return (1); 3943 } 3944 3945 /* Perform string profile checks */ 3946 nameCheckStatus = iSCSINameStringProfileCheck(wcInputObject); 3947 iSCSINameCheckStatusDisplay(nameCheckStatus); 3948 if (nameCheckStatus != iSCSINameCheckOK) { 3949 return (1); 3950 } 3951 3952 status = IMA_GetTargetOidList(oid, &targetList); 3953 if (!IMA_SUCCESS(status)) { 3954 printLibError(status); 3955 *funcRet = 1; 3956 return (0); 3957 } 3958 3959 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 3960 if (iscsiBoot == IMA_TRUE) { 3961 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 3962 if (!IMA_SUCCESS(status)) { 3963 (void) fprintf(stderr, "%s: %s\n", 3964 cmdName, gettext("unable to get MPxIO info" 3965 " of root disk")); 3966 *funcRet = 1; 3967 return (ret); 3968 } 3969 status = SUN_IMA_GetBootTargetName(bootTargetName); 3970 if (!IMA_SUCCESS(status)) { 3971 (void) fprintf(stderr, "%s: %s\n", 3972 cmdName, gettext("unable to get boot target's" 3973 " name")); 3974 *funcRet = 1; 3975 return (ret); 3976 } 3977 status = SUN_IMA_GetBootTargetAuthParams(&bootTargetCHAP); 3978 if (!IMA_SUCCESS(status)) { 3979 (void) fprintf(stderr, "%s: %s\n", 3980 cmdName, gettext("unable to get boot target's" 3981 " auth param")); 3982 *funcRet = 1; 3983 return (ret); 3984 } 3985 } 3986 3987 /* find target oid */ 3988 for (found = B_FALSE, i = 0; i < targetList->oidCount; i++) { 3989 status = SUN_IMA_GetTargetProperties(targetList->oids[i], 3990 &targetProps); 3991 if (!IMA_SUCCESS(status)) { 3992 printLibError(status); 3993 (void) IMA_FreeMemory(targetList); 3994 *funcRet = 1; 3995 return (ret); 3996 } 3997 3998 /* 3999 * Compare the target name with the input name 4000 */ 4001 if ((targetNamesEqual(wcInputObject, targetProps.imaProps.name) 4002 == B_TRUE)) { 4003 /* 4004 * For now, regardless of whether a target address 4005 * is specified, we return B_TRUE because 4006 * IMA_TARGET_PROPERTIES does not have a field for 4007 * specifying address. 4008 */ 4009 found = B_TRUE; 4010 targetOid = targetList->oids[i]; 4011 4012 if ((targetNamesEqual(bootTargetName, wcInputObject) 4013 == B_TRUE) && (iscsiBoot == IMA_TRUE)) { 4014 /* 4015 * iscsi booting, need changed target param is 4016 * booting target, for auth param, not allow 4017 * to change, for others dependent on mpxio 4018 */ 4019 4020 if ((optionList->optval == 'C') || 4021 (optionList->optval == 'H') || 4022 (optionList->optval == 'B') || 4023 (optionList->optval == 'a')) { 4024 /* 4025 * -C CHAP secret set 4026 * -H CHAP name set 4027 * -a authentication 4028 * -B bi-directional-authentication 4029 */ 4030 (void) fprintf(stderr, "%s: %s\n", 4031 cmdName, gettext("iscsi boot," 4032 " not allowed to modify" 4033 " authentication parameters" 4034 " of boot target")); 4035 return (1); 4036 } 4037 if (mpxioEnabled == IMA_FALSE) { 4038 (void) fprintf(stderr, "%s: %s\n", 4039 cmdName, gettext("iscsi boot and" 4040 " MPxIO is disabled, not allowed" 4041 " to modify boot target's" 4042 " parameters")); 4043 return (1); 4044 } 4045 4046 } 4047 4048 if (modifyIndividualTargetParam(optionList, targetOid, 4049 funcRet) != 0) { 4050 return (ret); 4051 } 4052 4053 /* 4054 * Even after finding a matched target, keep going 4055 * since there could be multiple target objects 4056 * associated with one target name in the system 4057 * because of different TPGTs. 4058 */ 4059 } 4060 } 4061 4062 /* If the target OID cannot be found create one */ 4063 if (!found) { 4064 status = SUN_IMA_CreateTargetOid(wcInputObject, &targetOid); 4065 if (!IMA_SUCCESS(status)) { 4066 printLibError(status); 4067 (void) IMA_FreeMemory(targetList); 4068 *funcRet = 1; 4069 return (ret); 4070 } 4071 if (modifyIndividualTargetParam(optionList, targetOid, 4072 funcRet) != 0) { 4073 return (ret); 4074 } 4075 } 4076 4077 (void) IMA_FreeMemory(targetList); 4078 return (ret); 4079 } 4080 4081 /* 4082 * Add one or more addresses 4083 */ 4084 static int 4085 addAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4086 { 4087 IMA_STATUS status; 4088 IMA_OID oid, addressOid; 4089 SUN_IMA_TARGET_ADDRESS address; 4090 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4091 int ret; 4092 int i; 4093 4094 assert(funcRet != NULL); 4095 4096 /* Find Sun initiator */ 4097 ret = sunInitiatorFind(&oid); 4098 if (ret > 0) { 4099 (void) fprintf(stderr, "%s: %s\n", 4100 cmdName, gettext("no initiator found")); 4101 } 4102 4103 if (ret != 0) { 4104 return (ret); 4105 } 4106 4107 /* 4108 * Format of discovery address operand: 4109 * 4110 * <IP address|hostname>:<port> 4111 */ 4112 for (i = 0; i < operandLen; i++) { 4113 /* initialize */ 4114 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4115 (void) memset(&address, 0, sizeof (address)); 4116 4117 if (mbstowcs(wcInputObject, operand[i], 4118 (MAX_ADDRESS_LEN + 1)) == (size_t)-1) { 4119 (void) fprintf(stderr, "%s: %s\n", 4120 cmdName, gettext("conversion error")); 4121 ret = 1; 4122 continue; 4123 } 4124 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4125 != 0) { 4126 ret = 1; 4127 continue; 4128 } 4129 if (addrType == DISCOVERY_ADDRESS) { 4130 status = IMA_AddDiscoveryAddress(oid, 4131 address.imaStruct, &addressOid); 4132 if (!IMA_SUCCESS(status)) { 4133 printLibError(status); 4134 *funcRet = 1; 4135 return (ret); 4136 } 4137 } else if (addrType == ISNS_SERVER_ADDRESS) { 4138 status = SUN_IMA_AddISNSServerAddress(address); 4139 if (!IMA_SUCCESS(status)) { 4140 printLibError(status); 4141 *funcRet = 1; 4142 return (ret); 4143 } 4144 } 4145 } 4146 return (ret); 4147 } 4148 4149 /* 4150 * Add one or more static configuration targets 4151 */ 4152 static int 4153 addStaticConfig(int operandLen, char *operand[], int *funcRet) 4154 { 4155 int i; 4156 boolean_t targetAddressSpecified = B_FALSE; 4157 boolean_t tpgtSpecified = B_FALSE; 4158 boolean_t isIpv6 = B_FALSE; 4159 int ret; 4160 int addrType; 4161 IMA_STATUS status; 4162 IMA_OID oid; 4163 SUN_IMA_STATIC_DISCOVERY_TARGET staticConfig; 4164 IMA_UINT16 port = 0; 4165 IMA_UINT16 tpgt = 0; 4166 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4167 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4168 iSCSINameCheckStatusType nameCheckStatus; 4169 char sAddr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4170 4171 assert(funcRet != NULL); 4172 4173 /* Find Sun initiator */ 4174 ret = sunInitiatorFind(&oid); 4175 if (ret > 0) { 4176 (void) fprintf(stderr, "%s: %s\n", 4177 cmdName, gettext("no initiator found")); 4178 } 4179 4180 if (ret != 0) { 4181 return (ret); 4182 } 4183 4184 /* 4185 * Format of static config operand: 4186 * <target-name>,<IP address|hostname>[:port][,tpgt] 4187 */ 4188 for (i = 0; i < operandLen; i++) { 4189 if (parseTarget(operand[i], 4190 &staticTargetName[0], 4191 MAX_ISCSI_NAME_LEN + 1, 4192 &targetAddressSpecified, 4193 &staticTargetAddress[0], 4194 SUN_IMA_IP_ADDRESS_PORT_LEN, 4195 &port, 4196 &tpgtSpecified, 4197 &tpgt, 4198 &isIpv6) != PARSE_TARGET_OK) { 4199 ret = 1; 4200 continue; 4201 } 4202 4203 if (targetAddressSpecified != B_TRUE) { 4204 (void) fprintf(stderr, "%s: %s\n", 4205 cmdName, gettext("missing target address")); 4206 *funcRet = 1; /* DIY message fix */ 4207 return (1); 4208 } 4209 /* Perform string profile checks */ 4210 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4211 iSCSINameCheckStatusDisplay(nameCheckStatus); 4212 if (nameCheckStatus != iSCSINameCheckOK) { 4213 *funcRet = 1; /* DIY message fix */ 4214 return (1); 4215 } 4216 (void) wcsncpy(staticConfig.targetName, staticTargetName, 4217 MAX_ISCSI_NAME_LEN + 1); 4218 4219 (void) wcstombs(sAddr, staticTargetAddress, sizeof (sAddr)); 4220 4221 if (isIpv6 == B_TRUE) { 4222 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4223 id.ipAddress.ipv4Address = B_FALSE; 4224 addrType = AF_INET6; 4225 } else { 4226 staticConfig.targetAddress.imaStruct.hostnameIpAddress. 4227 id.ipAddress.ipv4Address = B_TRUE; 4228 addrType = AF_INET; 4229 } 4230 4231 if (inet_pton(addrType, sAddr, staticConfig.targetAddress. 4232 imaStruct.hostnameIpAddress.id.ipAddress.ipAddress) != 1) { 4233 (void) fprintf(stderr, "%s: %s\n", 4234 cmdName, gettext("static config conversion error")); 4235 ret = 1; 4236 continue; 4237 } 4238 4239 staticConfig.targetAddress.imaStruct.portNumber = port; 4240 if (tpgtSpecified == B_TRUE) { 4241 staticConfig.targetAddress.defaultTpgt = B_FALSE; 4242 staticConfig.targetAddress.tpgt = tpgt; 4243 } else { 4244 staticConfig.targetAddress.defaultTpgt = B_TRUE; 4245 staticConfig.targetAddress.tpgt = 0; 4246 } 4247 4248 status = SUN_IMA_AddStaticTarget(oid, staticConfig, &oid); 4249 if (!IMA_SUCCESS(status)) { 4250 printLibError(status); 4251 *funcRet = 1; 4252 return (1); 4253 } 4254 } 4255 return (ret); 4256 } 4257 4258 /* 4259 * Remove one or more addresses 4260 */ 4261 static int 4262 removeAddress(int addrType, int operandLen, char *operand[], int *funcRet) 4263 { 4264 IMA_STATUS status; 4265 IMA_OID initiatorOid; 4266 SUN_IMA_TARGET_ADDRESS address; 4267 wchar_t wcInputObject[MAX_ADDRESS_LEN + 1]; 4268 int ret; 4269 int i; 4270 4271 assert(funcRet != NULL); 4272 4273 /* Find Sun initiator */ 4274 ret = sunInitiatorFind(&initiatorOid); 4275 if (ret > 0) { 4276 (void) fprintf(stderr, "%s: %s\n", 4277 cmdName, gettext("no initiator found")); 4278 } 4279 4280 if (ret != 0) { 4281 return (ret); 4282 } 4283 4284 for (i = 0; i < operandLen; i++) { 4285 /* initialize */ 4286 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4287 (void) memset(&address, 0, sizeof (address)); 4288 4289 if (mbstowcs(wcInputObject, operand[i], 4290 MAX_ADDRESS_LEN + 1) == (size_t)-1) { 4291 (void) fprintf(stderr, "%s: %s\n", 4292 cmdName, gettext("conversion error")); 4293 ret = 1; 4294 continue; 4295 } 4296 4297 if (getTargetAddress(addrType, operand[i], &address.imaStruct) 4298 != 0) { 4299 ret = 1; 4300 continue; 4301 } 4302 4303 if (addrType == DISCOVERY_ADDRESS) { 4304 status = SUN_IMA_RemoveDiscoveryAddress(address); 4305 if (!IMA_SUCCESS(status)) { 4306 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4307 (void) fprintf(stderr, "%s: %s\n", 4308 operand[i], gettext("not found")); 4309 } else { 4310 printLibError(status); 4311 } 4312 *funcRet = 1; 4313 } 4314 } else { 4315 status = SUN_IMA_RemoveISNSServerAddress(address); 4316 if (!IMA_SUCCESS(status)) { 4317 printLibError(status); 4318 *funcRet = 1; 4319 } 4320 } 4321 } 4322 return (ret); 4323 } 4324 4325 /* 4326 * Remove one or more static configuration targets 4327 */ 4328 static int 4329 removeStaticConfig(int operandLen, char *operand[], int *funcRet) 4330 { 4331 IMA_STATUS status; 4332 IMA_OID initiatorOid; 4333 IMA_OID_LIST *staticTargetList; 4334 SUN_IMA_STATIC_TARGET_PROPERTIES staticTargetProps; 4335 wchar_t staticTargetName[MAX_ISCSI_NAME_LEN + 1]; 4336 wchar_t staticTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4337 int ret; 4338 boolean_t atLeastFoundOne; 4339 boolean_t matched; 4340 boolean_t targetAddressSpecified = B_TRUE; 4341 boolean_t tpgtSpecified = B_FALSE; 4342 boolean_t isIpv6 = B_FALSE; 4343 int i, j; 4344 IMA_UINT16 port = 0; 4345 IMA_UINT16 tpgt = 0; 4346 iSCSINameCheckStatusType nameCheckStatus; 4347 char tmpStr[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4348 wchar_t tmpTargetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 4349 4350 assert(funcRet != NULL); 4351 4352 /* Find Sun initiator */ 4353 ret = sunInitiatorFind(&initiatorOid); 4354 if (ret > 0) { 4355 (void) fprintf(stderr, "%s: %s\n", 4356 cmdName, gettext("no initiator found")); 4357 } 4358 4359 if (ret != 0) { 4360 return (ret); 4361 } 4362 4363 status = IMA_GetStaticDiscoveryTargetOidList(initiatorOid, 4364 &staticTargetList); 4365 if (!IMA_SUCCESS(status)) { 4366 printLibError(status); 4367 *funcRet = 1; 4368 return (ret); 4369 } 4370 4371 for (i = 0; i < operandLen; i++) { 4372 if (parseTarget(operand[i], 4373 &staticTargetName[0], 4374 MAX_ISCSI_NAME_LEN + 1, 4375 &targetAddressSpecified, 4376 &staticTargetAddress[0], 4377 SUN_IMA_IP_ADDRESS_PORT_LEN, 4378 &port, 4379 &tpgtSpecified, 4380 &tpgt, 4381 &isIpv6) != PARSE_TARGET_OK) { 4382 ret = 1; 4383 continue; 4384 } 4385 4386 /* Perform string profile checks */ 4387 nameCheckStatus = iSCSINameStringProfileCheck(staticTargetName); 4388 iSCSINameCheckStatusDisplay(nameCheckStatus); 4389 if (nameCheckStatus != iSCSINameCheckOK) { 4390 return (1); 4391 } 4392 4393 for (atLeastFoundOne = B_FALSE, j = 0; 4394 j < staticTargetList->oidCount; 4395 j++) { 4396 IMA_UINT16 stpgt; 4397 4398 matched = B_FALSE; 4399 status = SUN_IMA_GetStaticTargetProperties( 4400 staticTargetList->oids[j], &staticTargetProps); 4401 if (!IMA_SUCCESS(status)) { 4402 if (status == IMA_ERROR_OBJECT_NOT_FOUND) { 4403 /* 4404 * When removing multiple static-config 4405 * entries we need to expect get 4406 * failures. These failures occur when 4407 * we are trying to get entry 4408 * information we have just removed. 4409 * Ignore the failure and continue. 4410 */ 4411 ret = 1; 4412 continue; 4413 } else { 4414 printLibError(status); 4415 (void) IMA_FreeMemory(staticTargetList); 4416 *funcRet = 1; 4417 return (ret); 4418 } 4419 } 4420 4421 stpgt = 4422 staticTargetProps.staticTarget.targetAddress.tpgt; 4423 4424 /* 4425 * Compare the static target name with the input if 4426 * one was input 4427 */ 4428 if ((targetNamesEqual( 4429 staticTargetProps.staticTarget.targetName, 4430 staticTargetName) == B_TRUE)) { 4431 if (targetAddressSpecified == B_FALSE) { 4432 matched = B_TRUE; 4433 } else { 4434 4435 if (staticTargetProps.staticTarget. 4436 targetAddress.imaStruct. 4437 hostnameIpAddress. 4438 id.ipAddress.ipv4Address == 4439 IMA_TRUE) { 4440 (void) inet_ntop(AF_INET, 4441 staticTargetProps. 4442 staticTarget.targetAddress. 4443 imaStruct.hostnameIpAddress. 4444 id.ipAddress.ipAddress, 4445 tmpStr, 4446 sizeof (tmpStr)); 4447 } else { 4448 (void) inet_ntop(AF_INET6, 4449 staticTargetProps. 4450 staticTarget.targetAddress. 4451 imaStruct.hostnameIpAddress. 4452 id.ipAddress.ipAddress, 4453 tmpStr, 4454 sizeof (tmpStr)); 4455 } 4456 4457 if (mbstowcs(tmpTargetAddress, tmpStr, 4458 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4459 (size_t)-1) { 4460 (void) fprintf(stderr, 4461 "%s: %s\n", 4462 cmdName, gettext( 4463 "conversion error")); 4464 ret = 1; 4465 continue; 4466 } 4467 4468 if ((wcsncmp(tmpTargetAddress, 4469 staticTargetAddress, 4470 SUN_IMA_IP_ADDRESS_PORT_LEN) == 4471 0) && (staticTargetProps. 4472 staticTarget.targetAddress. 4473 imaStruct.portNumber == port)) { 4474 if (tpgtSpecified == B_FALSE) { 4475 matched = B_TRUE; 4476 } else { 4477 if (tpgt == stpgt) { 4478 matched = 4479 B_TRUE; 4480 } 4481 } 4482 } 4483 } 4484 4485 if (matched) { 4486 status = 4487 IMA_RemoveStaticDiscoveryTarget( 4488 staticTargetList->oids[j]); 4489 if (!IMA_SUCCESS(status)) { 4490 printLibError(status); 4491 *funcRet = 1; 4492 return (ret); 4493 } 4494 atLeastFoundOne = B_TRUE; 4495 } 4496 } 4497 } 4498 if (!atLeastFoundOne) { 4499 (void) fprintf(stderr, gettext("%ws,%ws: %s\n"), 4500 staticTargetName, staticTargetAddress, 4501 gettext("not found")); 4502 } 4503 } 4504 return (ret); 4505 } 4506 4507 /* 4508 * Remove one or more target params. 4509 */ 4510 static int 4511 removeTargetParam(int operandLen, char *operand[], int *funcRet) 4512 { 4513 char *commaPos; 4514 IMA_STATUS status; 4515 IMA_OID initiatorOid; 4516 IMA_OID_LIST *targetList; 4517 SUN_IMA_TARGET_PROPERTIES targetProps; 4518 wchar_t wcInputObject[MAX_ISCSI_NAME_LEN + 1]; 4519 int ret; 4520 boolean_t found; 4521 int i, j; 4522 IMA_NODE_NAME bootTargetName; 4523 IMA_BOOL iscsiBoot = IMA_FALSE; 4524 IMA_BOOL mpxioEnabled = IMA_FALSE; 4525 4526 /* Get boot session's info */ 4527 (void) SUN_IMA_GetBootIscsi(&iscsiBoot); 4528 if (iscsiBoot == IMA_TRUE) { 4529 status = SUN_IMA_GetBootMpxio(&mpxioEnabled); 4530 if (!IMA_SUCCESS(status)) { 4531 (void) fprintf(stderr, "%s: %s\n", 4532 cmdName, gettext("unable to get MPxIO info of" 4533 " root disk")); 4534 *funcRet = 1; 4535 return (1); 4536 } 4537 status = SUN_IMA_GetBootTargetName(bootTargetName); 4538 if (!IMA_SUCCESS(status)) { 4539 (void) fprintf(stderr, "%s: %s\n", 4540 cmdName, gettext("unable to get boot" 4541 " target's name")); 4542 *funcRet = 1; 4543 return (1); 4544 } 4545 } 4546 4547 assert(funcRet != NULL); 4548 4549 /* Find Sun initiator */ 4550 ret = sunInitiatorFind(&initiatorOid); 4551 if (ret > 0) { 4552 (void) fprintf(stderr, "%s: %s\n", 4553 cmdName, gettext("no initiator found")); 4554 } 4555 4556 if (ret != 0) { 4557 return (ret); 4558 } 4559 4560 status = IMA_GetTargetOidList(initiatorOid, &targetList); 4561 if (!IMA_SUCCESS(status)) { 4562 printLibError(status); 4563 *funcRet = 1; 4564 return (ret); 4565 } 4566 4567 for (i = 0; i < operandLen; i++) { 4568 /* initialize */ 4569 commaPos = strchr(operand[i], ','); 4570 if (commaPos) { 4571 /* Ignore IP address. */ 4572 *commaPos = NULL; 4573 } 4574 (void) memset(&wcInputObject[0], 0, sizeof (wcInputObject)); 4575 if (mbstowcs(wcInputObject, operand[i], 4576 MAX_ISCSI_NAME_LEN + 1) == (size_t)-1) { 4577 (void) fprintf(stderr, "%s: %s\n", cmdName, 4578 gettext("conversion error")); 4579 ret = 1; 4580 continue; 4581 } 4582 4583 for (found = B_FALSE, j = 0; j < targetList->oidCount; 4584 j++) { 4585 status = SUN_IMA_GetTargetProperties( 4586 targetList->oids[j], &targetProps); 4587 if (!IMA_SUCCESS(status)) { 4588 printLibError(status); 4589 (void) IMA_FreeMemory(targetList); 4590 *funcRet = 1; 4591 return (ret); 4592 } 4593 4594 /* 4595 * Compare the target name with the input if 4596 * one was input 4597 */ 4598 if (targetNamesEqual(targetProps.imaProps.name, 4599 wcInputObject) == B_TRUE) { 4600 found = B_TRUE; 4601 if ((targetNamesEqual(bootTargetName, 4602 wcInputObject) == B_TRUE) && 4603 (iscsiBoot == IMA_TRUE)) { 4604 /* 4605 * iscsi booting, need changed target 4606 * param is booting target, booting 4607 * session mpxio disabled, not 4608 * allow to update 4609 */ 4610 if (mpxioEnabled == IMA_FALSE) { 4611 (void) fprintf(stderr, 4612 "%s: %s\n", cmdName, 4613 gettext("iscsi boot" 4614 " with MPxIO disabled," 4615 " not allowed to remove" 4616 " boot sess param")); 4617 ret = 1; 4618 continue; 4619 } 4620 4621 } 4622 4623 status = SUN_IMA_RemoveTargetParam( 4624 targetList->oids[j]); 4625 if (!IMA_SUCCESS(status)) { 4626 printLibError(status); 4627 (void) IMA_FreeMemory(targetList); 4628 *funcRet = 1; 4629 return (ret); 4630 } 4631 } 4632 } 4633 if (!found) { 4634 /* Silently ignoring it? */ 4635 (void) fprintf(stderr, gettext("%ws: %s\n"), 4636 wcInputObject, gettext("not found")); 4637 } 4638 } 4639 4640 (void) IMA_FreeMemory(targetList); 4641 return (ret); 4642 } 4643 4644 /*ARGSUSED*/ 4645 static int 4646 addFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4647 void *addArgs, int *funcRet) 4648 { 4649 int ret; 4650 4651 assert(funcRet != NULL); 4652 4653 switch (object) { 4654 case DISCOVERY_ADDRESS: 4655 case ISNS_SERVER_ADDRESS: 4656 ret = addAddress(object, operandLen, operand, funcRet); 4657 break; 4658 case STATIC_CONFIG: 4659 ret = addStaticConfig(operandLen, operand, funcRet); 4660 break; 4661 default: 4662 (void) fprintf(stderr, "%s: %s\n", 4663 cmdName, gettext("unknown object")); 4664 ret = 1; 4665 break; 4666 } 4667 return (ret); 4668 } 4669 4670 /*ARGSUSED*/ 4671 static int 4672 listFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4673 void *addArgs, int *funcRet) 4674 { 4675 int ret; 4676 4677 assert(funcRet != NULL); 4678 4679 switch (object) { 4680 case DISCOVERY: 4681 ret = listDiscovery(funcRet); 4682 break; 4683 case DISCOVERY_ADDRESS: 4684 ret = listDiscoveryAddress(operandLen, operand, options, 4685 funcRet); 4686 break; 4687 case ISNS_SERVER_ADDRESS: 4688 ret = listISNSServerAddress(operandLen, operand, options, 4689 funcRet); 4690 break; 4691 case NODE: 4692 ret = listNode(funcRet); 4693 break; 4694 case STATIC_CONFIG: 4695 ret = listStaticConfig(operandLen, operand, funcRet); 4696 break; 4697 case TARGET: 4698 ret = listTarget(operandLen, operand, options, funcRet); 4699 break; 4700 case TARGET_PARAM: 4701 ret = listTargetParam(operandLen, operand, options, funcRet); 4702 break; 4703 default: 4704 (void) fprintf(stderr, "%s: %s\n", 4705 cmdName, gettext("unknown object")); 4706 ret = 1; 4707 break; 4708 } 4709 return (ret); 4710 } 4711 4712 /*ARGSUSED*/ 4713 static int 4714 modifyFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4715 void *addArgs, int *funcRet) 4716 { 4717 int ret, i; 4718 4719 assert(funcRet != NULL); 4720 4721 switch (object) { 4722 case DISCOVERY: 4723 ret = modifyDiscovery(options, funcRet); 4724 break; 4725 case NODE: 4726 ret = modifyNode(options, funcRet); 4727 break; 4728 case TARGET_PARAM: 4729 i = 0; 4730 while (operand[i]) { 4731 ret = modifyTargetParam(options, operand[i], funcRet); 4732 4733 if (ret) { 4734 (void) fprintf(stderr, "%s: %s: %s\n", 4735 cmdName, gettext("modify failed"), 4736 operand[i]); 4737 return (ret); 4738 } 4739 i++; 4740 } 4741 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 /*ARGSUSED*/ 4753 static int 4754 removeFunc(int operandLen, char *operand[], int object, cmdOptions_t *options, 4755 void *addArgs, int *funcRet) 4756 { 4757 int ret; 4758 4759 switch (object) { 4760 case DISCOVERY_ADDRESS: 4761 case ISNS_SERVER_ADDRESS: 4762 ret = removeAddress(object, operandLen, operand, 4763 funcRet); 4764 break; 4765 case STATIC_CONFIG: 4766 ret = removeStaticConfig(operandLen, operand, funcRet); 4767 break; 4768 case TARGET_PARAM: 4769 ret = removeTargetParam(operandLen, operand, funcRet); 4770 break; 4771 default: 4772 (void) fprintf(stderr, "%s: %s\n", 4773 cmdName, gettext("unknown object")); 4774 ret = 1; 4775 break; 4776 } 4777 return (ret); 4778 } 4779 4780 static void 4781 iSCSINameCheckStatusDisplay(iSCSINameCheckStatusType status) 4782 { 4783 switch (status) { 4784 case iSCSINameLenZero: 4785 (void) fprintf(stderr, "%s: %s\n", 4786 cmdName, gettext("empty iSCSI name.")); 4787 break; 4788 case iSCSINameLenExceededMax: 4789 (void) fprintf(stderr, "%s: %s\n", cmdName, 4790 gettext("iSCSI name exceeded maximum length.")); 4791 break; 4792 case iSCSINameUnknownType: 4793 (void) fprintf(stderr, "%s: %s\n", cmdName, 4794 gettext("unknown iSCSI name type.")); 4795 break; 4796 case iSCSINameInvalidCharacter: 4797 (void) fprintf(stderr, "%s: %s\n", 4798 cmdName, 4799 gettext("iSCSI name invalid character used")); 4800 break; 4801 case iSCSINameIqnFormatError: 4802 (void) fprintf(stderr, "%s: %s\n", cmdName, 4803 gettext("iqn formatting error.")); 4804 break; 4805 case iSCSINameIqnDateFormatError: 4806 (void) fprintf(stderr, "%s: %s\n", 4807 cmdName, gettext("invalid iqn date." \ 4808 " format is: YYYY-MM")); 4809 break; 4810 case iSCSINameIqnSubdomainFormatError: 4811 (void) fprintf(stderr, "%s: %s\n", 4812 cmdName, gettext("missing subdomain after \":\"")); 4813 break; 4814 case iSCSINameIqnInvalidYearError: 4815 (void) fprintf(stderr, "%s: %s\n", 4816 cmdName, gettext("invalid year")); 4817 break; 4818 case iSCSINameIqnInvalidMonthError: 4819 (void) fprintf(stderr, "%s: %s\n", 4820 cmdName, gettext("invalid month")); 4821 break; 4822 case iSCSINameIqnFQDNError: 4823 (void) fprintf(stderr, "%s: %s\n", 4824 cmdName, gettext("missing reversed fully qualified"\ 4825 " domain name")); 4826 break; 4827 case iSCSINameEUIFormatError: 4828 (void) fprintf(stderr, "%s: %s\n", cmdName, 4829 gettext("eui formatting error.")); 4830 break; 4831 } 4832 } 4833 4834 /* 4835 * A convenient function to modify the target parameters of an individual 4836 * target. 4837 * 4838 * Return 0 if successful 4839 * Return 1 if failed 4840 */ 4841 static int 4842 modifyIndividualTargetParam(cmdOptions_t *optionList, IMA_OID targetOid, 4843 int *funcRet) 4844 { 4845 assert(funcRet != NULL); 4846 4847 for (; optionList->optval; optionList++) { 4848 switch (optionList->optval) { 4849 case 'a': 4850 if (modifyTargetAuthMethod(targetOid, 4851 optionList->optarg, funcRet) != 0) { 4852 return (1); 4853 } 4854 break; 4855 case 'B': 4856 if (modifyTargetBidirAuthFlag(targetOid, 4857 optionList->optarg, funcRet) != 0) { 4858 return (1); 4859 } 4860 break; 4861 case 'C': 4862 if (modifyTargetAuthParam(targetOid, 4863 AUTH_PASSWORD, NULL, funcRet) != 0) { 4864 return (1); 4865 } 4866 break; 4867 case 'd': 4868 if (setLoginParameter(targetOid, DATA_DIGEST, 4869 optionList->optarg) != 0) { 4870 return (1); 4871 } 4872 break; 4873 case 'h': 4874 if (setLoginParameter(targetOid, HEADER_DIGEST, 4875 optionList->optarg) != 0) { 4876 return (1); 4877 } 4878 break; 4879 case 'p': 4880 /* Login parameter */ 4881 if (setLoginParameters(targetOid, 4882 optionList->optarg) != 0) { 4883 return (1); 4884 } 4885 break; 4886 case 'c': 4887 /* Modify configure sessions */ 4888 if (modifyConfiguredSessions(targetOid, 4889 optionList->optarg) != 0) { 4890 return (1); 4891 } 4892 break; 4893 case 'H': 4894 if (modifyTargetAuthParam(targetOid, AUTH_NAME, 4895 optionList->optarg, funcRet) != 0) { 4896 return (1); 4897 } 4898 break; 4899 } 4900 } 4901 4902 return (0); 4903 } 4904 4905 /* 4906 * This helper function could go into a utility module for general use. 4907 */ 4908 static int 4909 parseAddress(char *address_port_str, 4910 uint16_t defaultPort, 4911 char *address_str, 4912 size_t address_str_len, 4913 uint16_t *port, 4914 boolean_t *isIpv6) 4915 { 4916 char port_str[64]; 4917 int tmp_port; 4918 char *errchr; 4919 4920 if (address_port_str[0] == '[') { 4921 /* IPv6 address */ 4922 char *close_bracket_pos; 4923 close_bracket_pos = strchr(address_port_str, ']'); 4924 if (!close_bracket_pos) { 4925 syslog(LOG_USER|LOG_DEBUG, 4926 "IP address format error: %s\n", address_str); 4927 return (PARSE_ADDR_MISSING_CLOSING_BRACKET); 4928 } 4929 4930 *close_bracket_pos = NULL; 4931 (void) strlcpy(address_str, &address_port_str[1], 4932 address_str_len); 4933 4934 /* Extract the port number */ 4935 close_bracket_pos++; 4936 if (*close_bracket_pos == ':') { 4937 close_bracket_pos++; 4938 if (*close_bracket_pos != NULL) { 4939 (void) strlcpy(port_str, close_bracket_pos, 64); 4940 tmp_port = strtol(port_str, &errchr, 10); 4941 if (tmp_port == 0 && errchr != NULL) { 4942 (void) fprintf(stderr, "%s: %s:%s %s\n", 4943 cmdName, address_str, 4944 close_bracket_pos, 4945 gettext("port number invalid")); 4946 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 4947 } 4948 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 4949 (tmp_port < 0)) { 4950 /* Port number out of range */ 4951 syslog(LOG_USER|LOG_DEBUG, 4952 "Specified port out of range: %d", 4953 tmp_port); 4954 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 4955 } else { 4956 *port = (uint16_t)tmp_port; 4957 } 4958 } else { 4959 *port = defaultPort; 4960 } 4961 } else { 4962 *port = defaultPort; 4963 } 4964 4965 *isIpv6 = B_TRUE; 4966 } else { 4967 /* IPv4 address */ 4968 char *colon_pos; 4969 colon_pos = strchr(address_port_str, ':'); 4970 if (!colon_pos) { 4971 /* No port number specified. */ 4972 *port = defaultPort; 4973 (void) strlcpy(address_str, address_port_str, 4974 address_str_len); 4975 } else { 4976 *colon_pos = (char)NULL; 4977 (void) strlcpy(address_str, address_port_str, 4978 address_str_len); 4979 4980 /* Extract the port number */ 4981 colon_pos++; 4982 if (*colon_pos != NULL) { 4983 4984 (void) strlcpy(port_str, colon_pos, 64); 4985 tmp_port = strtol(port_str, &errchr, 10); 4986 if (tmp_port == 0 && errchr != NULL) { 4987 (void) fprintf(stderr, "%s: %s:%s %s\n", 4988 cmdName, address_str, colon_pos, 4989 gettext("port number invalid")); 4990 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 4991 } 4992 if ((tmp_port > 0) && (tmp_port > USHRT_MAX) || 4993 (tmp_port < 0)) { 4994 /* Port number out of range */ 4995 syslog(LOG_USER|LOG_DEBUG, 4996 "Specified port out of range: %d", 4997 tmp_port); 4998 return (PARSE_ADDR_PORT_OUT_OF_RANGE); 4999 } else { 5000 *port = (uint16_t)tmp_port; 5001 } 5002 } else { 5003 *port = defaultPort; 5004 } 5005 } 5006 5007 *isIpv6 = B_FALSE; 5008 } 5009 5010 return (PARSE_ADDR_OK); 5011 } 5012 5013 /* 5014 * This helper function could go into a utility module for general use. 5015 */ 5016 iSCSINameCheckStatusType 5017 iSCSINameStringProfileCheck(wchar_t *name) 5018 { 5019 char mb_name[MAX_ISCSI_NAME_LEN + 1]; 5020 size_t name_len; 5021 char *tmp; 5022 5023 (void) wcstombs(mb_name, name, MAX_ISCSI_NAME_LEN + 1); 5024 5025 if ((name_len = strlen(mb_name)) == 0) { 5026 return (iSCSINameLenZero); 5027 } else if (name_len > MAX_ISCSI_NAME_LEN) { 5028 return (iSCSINameLenExceededMax); 5029 } 5030 5031 /* 5032 * check for invalid characters 5033 * According to RFC 3722 iSCSI name must be either a letter, 5034 * a digit or one of the following '-' '.' ':' 5035 */ 5036 for (tmp = mb_name; *tmp != NULL; tmp++) { 5037 if ((isalnum(*tmp) == 0) && 5038 (*tmp != '-') && 5039 (*tmp != '.') && 5040 (*tmp != ':')) { 5041 return (iSCSINameInvalidCharacter); 5042 } 5043 } 5044 5045 if (strncmp(mb_name, ISCSI_IQN_NAME_PREFIX, 5046 strlen(ISCSI_IQN_NAME_PREFIX)) == 0) { 5047 /* 5048 * If name is of type iqn, check date string and naming 5049 * authority. 5050 */ 5051 char *strp = NULL; 5052 5053 /* 5054 * Don't allow the string to end with a colon. If there is a 5055 * colon then there must be a subdomain provided. 5056 */ 5057 if (mb_name[strlen(mb_name) - 1] == ':') { 5058 return (iSCSINameIqnSubdomainFormatError); 5059 } 5060 5061 /* Date string */ 5062 strp = strtok(&mb_name[3], "."); 5063 if (strp) { 5064 char tmpYear[5], tmpMonth[3], *endPtr = NULL; 5065 int year, month; 5066 5067 /* Date string should be in YYYY-MM format */ 5068 if (strlen(strp) != strlen("YYYY-MM") || 5069 strp[4] != '-') { 5070 return (iSCSINameIqnDateFormatError); 5071 } 5072 5073 /* 5074 * Validate year. Only validating that the 5075 * year can be converted to a number. No 5076 * validation will be done on year's actual 5077 * value. 5078 */ 5079 (void) strncpy(tmpYear, strp, 4); 5080 tmpYear[4] = '\0'; 5081 5082 errno = 0; 5083 year = strtol(tmpYear, &endPtr, 10); 5084 if (errno != 0 || *endPtr != '\0' || 5085 year < 0 || year > 9999) { 5086 return (iSCSINameIqnInvalidYearError); 5087 } 5088 5089 /* 5090 * Validate month is valid. 5091 */ 5092 (void) strncpy(tmpMonth, &strp[5], 2); 5093 tmpMonth[2] = '\0'; 5094 errno = 0; 5095 month = strtol(tmpMonth, &endPtr, 10); 5096 5097 if (errno != 0 || *endPtr != '\0' || 5098 month < 1 || month > 12) { 5099 return (iSCSINameIqnInvalidMonthError); 5100 } 5101 5102 /* 5103 * A reversed FQDN needs to be provided. We 5104 * will only check for a "." followed by more 5105 * than two or more characters. The list of domains is 5106 * too large and changes too frequently to 5107 * add validation for. 5108 */ 5109 strp = strtok(NULL, "."); 5110 if (!strp || strlen(strp) < 2) { 5111 return (iSCSINameIqnFQDNError); 5112 } 5113 5114 /* Name authority string */ 5115 strp = strtok(NULL, ":"); 5116 if (strp) { 5117 return (iSCSINameCheckOK); 5118 } else { 5119 return (iSCSINameIqnFQDNError); 5120 } 5121 } else { 5122 return (iSCSINameIqnFormatError); 5123 } 5124 } else if (strncmp(mb_name, ISCSI_EUI_NAME_PREFIX, 5125 strlen(ISCSI_EUI_NAME_PREFIX)) == 0) { 5126 /* If name is of type EUI, change its length */ 5127 5128 if (strlen(mb_name) != ISCSI_EUI_NAME_LEN) { 5129 return (iSCSINameEUIFormatError); 5130 } 5131 5132 for (tmp = mb_name + strlen(ISCSI_EUI_NAME_PREFIX) + 1; 5133 *tmp != '\0'; tmp++) { 5134 if (isxdigit(*tmp)) { 5135 continue; 5136 } 5137 return (iSCSINameEUIFormatError); 5138 } 5139 5140 return (iSCSINameCheckOK); 5141 } else { 5142 return (iSCSINameUnknownType); 5143 } 5144 } 5145 5146 /* 5147 * This helper function could go into a utility module for general use. 5148 * 5149 * Returns: 5150 * B_TRUE is the numberStr is an unsigned natural number and within the 5151 * specified bound. 5152 * B_FALSE otherwise. 5153 */ 5154 boolean_t 5155 isNaturalNumber(char *numberStr, uint32_t upperBound) 5156 { 5157 int i; 5158 int number_str_len; 5159 5160 if ((number_str_len = strlen(numberStr)) == 0) { 5161 return (B_FALSE); 5162 } 5163 5164 for (i = 0; i < number_str_len; i++) { 5165 if (numberStr[i] < 060 || numberStr[i] > 071) { 5166 return (B_FALSE); 5167 } 5168 } 5169 5170 if (atoi(numberStr) > upperBound) { 5171 return (B_FALSE); 5172 } 5173 5174 return (B_TRUE); 5175 } 5176 5177 /* 5178 * This helper function could go into a utility module for general use. 5179 * It parses a target string in the format of: 5180 * 5181 * <target_name>,[<ip_address>[:port][,tpgt]] 5182 * 5183 * and creates wchar strings for target name and target address. It 5184 * also populates port and tpgt if found. 5185 * 5186 * Returns: 5187 * PARSE_TARGET_OK if parsing is successful. 5188 * PARSE_TARGET_INVALID_TPGT if the specified tpgt is 5189 * invalid. 5190 * PARSE_TARGET_INVALID_ADDR if the address specified is 5191 * invalid. 5192 */ 5193 int 5194 parseTarget(char *targetStr, 5195 wchar_t *targetNameStr, 5196 size_t targetNameStrLen, 5197 boolean_t *targetAddressSpecified, 5198 wchar_t *targetAddressStr, 5199 size_t targetAddressStrLen, 5200 uint16_t *port, 5201 boolean_t *tpgtSpecified, 5202 uint16_t *tpgt, 5203 boolean_t *isIpv6) 5204 { 5205 char *commaPos; 5206 char *commaPos2; 5207 char targetAddress[SUN_IMA_IP_ADDRESS_PORT_LEN]; 5208 int i; 5209 int lowerCase; 5210 5211 (void) memset(targetNameStr, 0, 5212 targetNameStrLen * sizeof (wchar_t)); 5213 (void) memset(targetAddressStr, 0, 5214 targetAddressStrLen * sizeof (wchar_t)); 5215 5216 commaPos = strchr(targetStr, ','); 5217 if (commaPos != NULL) { 5218 *commaPos = NULL; 5219 commaPos++; 5220 *targetAddressSpecified = B_TRUE; 5221 5222 /* 5223 * Checking of tpgt makes sense only when 5224 * the target address/port are specified. 5225 */ 5226 commaPos2 = strchr(commaPos, ','); 5227 if (commaPos2 != NULL) { 5228 *commaPos2 = NULL; 5229 commaPos2++; 5230 if (isNaturalNumber(commaPos2, ISCSI_MAX_TPGT_VALUE) == 5231 B_TRUE) { 5232 *tpgt = atoi(commaPos2); 5233 *tpgtSpecified = B_TRUE; 5234 } else { 5235 return (PARSE_TARGET_INVALID_TPGT); 5236 } 5237 } 5238 5239 switch (parseAddress(commaPos, ISCSI_LISTEN_PORT, 5240 &targetAddress[0], MAX_ADDRESS_LEN + 1, port, isIpv6)) { 5241 case PARSE_ADDR_PORT_OUT_OF_RANGE: 5242 return (PARSE_TARGET_INVALID_ADDR); 5243 case PARSE_ADDR_OK: 5244 break; 5245 default: 5246 (void) fprintf(stderr, "%s: %s\n", 5247 cmdName, gettext("cannot parse target name")); 5248 return (PARSE_TARGET_INVALID_ADDR); 5249 } 5250 (void) mbstowcs(targetAddressStr, targetAddress, 5251 targetAddressStrLen); 5252 for (i = 0; targetAddressStr[i] != 0; i++) { 5253 lowerCase = tolower(targetAddressStr[i]); 5254 targetAddressStr[i] = lowerCase; 5255 } 5256 } else { 5257 *targetAddressSpecified = B_FALSE; 5258 *tpgtSpecified = B_FALSE; 5259 } 5260 5261 (void) mbstowcs(targetNameStr, targetStr, targetNameStrLen); 5262 for (i = 0; targetNameStr[i] != 0; i++) { 5263 lowerCase = tolower(targetNameStr[i]); 5264 targetNameStr[i] = lowerCase; 5265 } 5266 5267 return (PARSE_TARGET_OK); 5268 } 5269 5270 /*ARGSUSED*/ 5271 static void 5272 listCHAPName(IMA_OID oid) 5273 { 5274 IMA_INITIATOR_AUTHPARMS authParams; 5275 IMA_STATUS status; 5276 IMA_BYTE chapName [MAX_CHAP_NAME_LEN + 1]; 5277 5278 /* Get Chap Name depending upon oid object type */ 5279 if (oid.objectType == IMA_OBJECT_TYPE_LHBA) { 5280 status = IMA_GetInitiatorAuthParms(oid, 5281 IMA_AUTHMETHOD_CHAP, &authParams); 5282 } else { 5283 status = SUN_IMA_GetTargetAuthParms(oid, 5284 IMA_AUTHMETHOD_CHAP, &authParams); 5285 } 5286 5287 (void) fprintf(stdout, "\n\t\t%s: ", gettext("CHAP Name")); 5288 5289 if (IMA_SUCCESS(status)) { 5290 /* 5291 * Default chap name will be the node name. The default will 5292 * be set by the driver. 5293 */ 5294 if (authParams.chapParms.nameLength != 0) { 5295 (void) memset(chapName, 0, sizeof (chapName)); 5296 (void) memcpy(chapName, authParams.chapParms.name, 5297 authParams.chapParms.nameLength); 5298 (void) fprintf(stdout, "%s", chapName); 5299 5300 } else { 5301 (void) fprintf(stdout, "%s", "-"); 5302 } 5303 } else { 5304 (void) fprintf(stdout, "%s", "-"); 5305 } 5306 } 5307 5308 /* 5309 * Prints out see manual page. 5310 * Called out through atexit(3C) so is always last thing displayed. 5311 */ 5312 void 5313 seeMan(void) 5314 { 5315 static int sent = 0; 5316 5317 if (sent) 5318 return; 5319 5320 (void) fprintf(stdout, "%s %s(1M)\n", 5321 gettext("For more information, please see"), cmdName); 5322 5323 sent = 1; 5324 } 5325 5326 5327 /* 5328 * main calls a parser that checks syntax of the input command against 5329 * various rules tables. 5330 * 5331 * The parser provides usage feedback based upon same tables by calling 5332 * two usage functions, usage and subUsage, handling command and subcommand 5333 * usage respectively. 5334 * 5335 * The parser handles all printing of usage syntactical errors 5336 * 5337 * When syntax is successfully validated, the parser calls the associated 5338 * function using the subcommands table functions. 5339 * 5340 * Syntax is as follows: 5341 * command subcommand [options] resource-type [<object>] 5342 * 5343 * The return value from the function is placed in funcRet 5344 */ 5345 int 5346 main(int argc, char *argv[]) 5347 { 5348 synTables_t synTables; 5349 char versionString[VERSION_STRING_MAX_LEN]; 5350 int ret; 5351 int funcRet = 0; 5352 void *subcommandArgs = NULL; 5353 5354 if (geteuid() != 0) { 5355 (void) fprintf(stderr, "%s\n", gettext("permission denied")); 5356 return (1); 5357 } 5358 5359 /* set global command name */ 5360 cmdName = getExecBasename(argv[0]); 5361 5362 (void) snprintf(versionString, sizeof (versionString), "%s.%s", 5363 VERSION_STRING_MAJOR, VERSION_STRING_MINOR); 5364 synTables.versionString = versionString; 5365 synTables.longOptionTbl = &longOptions[0]; 5366 synTables.subcommandTbl = &subcommands[0]; 5367 synTables.objectTbl = &objects[0]; 5368 synTables.objectRulesTbl = &objectRules[0]; 5369 synTables.optionRulesTbl = &optionRules[0]; 5370 5371 /* call the CLI parser */ 5372 ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet); 5373 if (ret == -1) { 5374 perror(cmdName); 5375 ret = 1; 5376 } 5377 5378 if (funcRet != 0) { 5379 (void) fprintf(stderr, "%s: %s\n", 5380 cmdName, gettext("Unable to complete operation")); 5381 ret = 1; 5382 } 5383 return (ret); 5384 } 5385