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